Estou lendo Coders at Work , e há muita conversa sobre invariantes. Até onde eu entendi, uma invariante é uma condição que vale antes e depois de uma expressão. Eles são, entre outras coisas, úteis para provar que o loop está correto, se me lembro corretamente do meu curso de lógica.
Minha descrição está correta ou perdi alguma coisa? Você já os usou em seu programa? E se sim, como eles se beneficiaram?
invariants
gablin
fonte
fonte
Respostas:
No OOP, invariável é um conjunto de asserções que sempre devem ser verdadeiras durante a vida de um objeto para que o programa seja válido. Ele deve ser verdadeiro desde o final do construtor até o início do destruidor sempre que o objeto não estiver executando atualmente um método que altera seu estado.
Um exemplo de invariante pode ser que exatamente uma das duas variáveis de membro seja nula. Ou que, se um tiver um determinado valor, o conjunto de valores permitidos para o outro é este ou aquele ...
Em algum momento, uso uma função de membro do objeto para verificar se o invariante é válido. Se não for esse o caso, é feita uma afirmação. E o método é chamado no início e na saída de cada método que altera o objeto (em C ++, essa é apenas uma linha ...)
fonte
Bem, as coisas que estou vendo neste tópico são ótimas, mas tenho uma definição de 'invariável' que foi tremendamente útil para mim no trabalho.
Essa definição é útil porque separa as condições em dois grupos: aquelas em que o compilador pode confiar, e aquelas que devem ser documentadas, discutidas, comentadas ou comunicadas aos colaboradores para que eles interajam com a base de código sem introduzir bugs. .
Além disso, essa definição é útil porque permite que você use a generalização "Invariantes são ruins".
Como exemplo, o câmbio em um carro de transmissão manual é projetado para evitar uma invariância. Se eu quisesse, eu poderia construir uma transmissão com uma alavanca para cada marcha. Essa alavanca pode estar para a frente ("engatada") ou para trás ("desengatada"). Nesse sistema, criei um "invariável", que pode ser documentado da seguinte maneira:
E assim, pode-se culpar transmissões quebradas em direção desleixada. Os carros modernos, no entanto, usam um único manípulo que gira entre as engrenagens. Ele foi projetado de tal maneira que, em um carro moderno, não é possível engatar duas marchas ao mesmo tempo.
Dessa maneira, poderíamos dizer que a transmissão foi projetada para 'remover o invariante', porque não se permite ser mecanicamente configurada de maneira a violar a regra lógica.
Cada invariante desse tipo que você remove do seu código é uma melhoria, pois diminui a carga cognitiva de trabalhar com ele.
fonte
Um invariante (no senso comum) significa algumas condições que devem ser verdadeiras em algum momento ou mesmo sempre enquanto o programa está sendo executado. por exemplo, PreConditions e PostConditions podem ser usadas para afirmar algumas condições que devem ser verdadeiras quando uma função é chamada e quando ela retorna. Invariantes de objetos podem ser usados para afirmar que um objeto deve ter um estado válido durante todo o tempo em que existe. Esse é o princípio do projeto por contrato.
Eu usei invariantes informalmente usando verificações no código. Mais recentemente, porém, estou brincando com a biblioteca de contratos de código para .Net que suporta diretamente invariantes.
fonte
Baseado na seguinte citação de Coders At Work ...
... Eu acho que "invariável" = "condição que você deseja manter para garantir o efeito desejado".
Parece que invariante tem dois sentidos que diferem de maneira sutil:
Então 1 é como uma afirmação; 2 é como uma ferramenta para provar a correção, desempenho ou outras propriedades - eu acho. Veja o artigo da Wikipedia para obter um exemplo de 2 (comprovando a correção da solução do quebra-cabeça da MU).
Na verdade, um terceiro sentido de invariante é:
.3 O que o programa (ou módulo ou função) deve fazer; em outras palavras, seu propósito.
Da mesma entrevista do Coders At Work:
fonte
Um invariante é como uma regra ou suposição que pode ser usada para ditar a lógica do seu programa.
Por exemplo, suponha que você tenha algum aplicativo de software que rastreie as contas de usuário. Suponha também que o usuário possa ter várias contas, mas por qualquer motivo, você precisa diferenciar entre a conta principal de um usuário e as contas de "alias".
Pode ser um registro de banco de dados ou algo mais, mas, por enquanto, vamos supor que cada conta de usuário seja representada por um objeto de classe.
classe userAccount {private char * pUserName; char privado * pParentAccountUserName;
...}
Uma invariável pode ser a suposição de que, se pParentAccountUserName for NULL ou vazio, esse objeto será a conta pai. Você pode usar esse invariante para distinguir diferentes tipos de conta. Provavelmente, existem métodos melhores para distinguir diferentes tipos de contas de usuário; lembre-se de que este é apenas um exemplo para mostrar como uma invariável pode ser usada.
fonte
Vindo de uma formação em física, na física temos invariantes, que são essencialmente quantidades que não variam ao longo de uma computação / simulação inteira. Por exemplo, na física, para um sistema fechado, a energia total é conservada. Ou ainda na física, se duas partículas colidem, os fragmentos resultantes devem conter exatamente a energia com a qual começaram e exatamente o mesmo momento (uma quantidade vetorial). Geralmente, não há invariantes suficientes para especificar totalmente o resultado. Por exemplo, na colisão de duas partículas, temos quatro invariantes, três componentes de momento e um componente de energia, mas o sistema tem seis graus de liberdade (seis números para descrever seu estado). Os invariantes devem ser conservados dentro de um erro de arredondamento, mas sua conservação não prova que a solução esteja correta.
Normalmente, essas coisas são importantes como verificações de sanidade, mas elas mesmas não podem provar a correção.
fonte