Não sei de onde vem a afirmação de que "ela não realiza e frequentemente não pode executar uma análise estática". A primeira parte da afirmação está claramente errada. O segundo depende do que você quer dizer com "frequentemente". Eu prefiro dizer isso frequentemente realiza análises estáticas e raramente falha. Em aplicativos de negócios comuns, raramente fica muito mais próximo de nunca .
Então, aqui está, o primeiro benefício:
Benefício 1: análise estática
Asserções comuns e verificação de argumentos têm uma desvantagem: elas são adiadas até que o código seja executado. Por outro lado, os contratos de código se manifestam em um nível muito anterior, na etapa de codificação ou durante a compilação do aplicativo. Quanto mais cedo você detectar um erro, menos caro será corrigi-lo.
Benefício 2: tipo de documentação sempre atualizada
Os contratos de código também fornecem um tipo de documentação sempre atualizada. Se o comentário XML do método indicar SetProductPrice(int newPrice)
que newPrice
deve ser superior ou igual a zero, você pode esperar que a documentação esteja atualizada, mas também pode descobrir que alguém alterou o método para quenewPrice = 0
gerar uma ArgumentOutOfRangeException
, mas nunca alterou a documentação correspondente. Dada a correlação entre os contratos de código e o próprio código, você não tem o problema de documentação fora de sincronia.
O tipo de documentação fornecida pelos contratos de código também é preciosa de uma maneira que, frequentemente, os comentários XML não explicam bem os valores aceitáveis. Quantas vezes eu estava me perguntando se null
ou string.Empty
ou\r\n
é um valor autorizado para um método, e os comentários XML ficaram em silêncio sobre isso!
Em conclusão, sem contratos de código, muitos pedaços de código são assim:
Aceitarei alguns valores, mas não outros, mas você terá que adivinhar ou ler a documentação, se houver. Na verdade, não leia a documentação: está desatualizada. Basta percorrer todos os valores e você verá aqueles que me fazem lançar exceções. Você também precisa adivinhar a faixa de valores que pode ser retornada, porque, mesmo que eu lhe conte um pouco mais sobre isso, pode não ser verdade, dadas as centenas de alterações feitas nos últimos anos.
Com contratos de código, torna-se:
O argumento do título pode ser uma sequência não nula com um comprimento de 0..500. O número inteiro a seguir é um valor positivo, que pode ser zero apenas quando a sequência está vazia. Finalmente, retornarei um IDefinition
objeto, nunca nulo.
Benefício 3: contratos de interfaces
Um terceiro benefício é que os contratos de código capacitam interfaces. Digamos que você tenha algo como:
public interface ICommittable
{
public ICollection<AtomicChange> PendingChanges { get; }
public void CommitChanges();
...
}
Como você, usando apenas declarações e exceções, garante que só CommitChanges
pode ser chamado quando PendingChanges
não está vazio? Como você garantiria que PendingChanges
nuncanull
?
Benefício 4: aplicar os resultados de um método
Finalmente, o quarto benefício é poder obter Contract.Ensure
os resultados. E se, ao escrever um método que retorne um número inteiro, eu quero ter certeza de que o valor nunca é inferior ou igual a zero? Incluindo cinco anos depois, depois de sofrer muitas mudanças de muitos desenvolvedores? Assim que um método tiver vários pontos de retorno, isso Assert
se tornará um pesadelo de manutenção.
Considere os contratos de código não apenas como um meio de correção do seu código, mas uma maneira mais rigorosa de escrever código.De maneira semelhante, uma pessoa que usou linguagens exclusivamente dinâmicas pode perguntar por que você aplicaria tipos no nível da linguagem, enquanto você pode fazer o mesmo em afirmações quando necessário. Você pode, mas a digitação estática é mais fácil de usar, menos propensa a erros em comparação com várias asserções e com a documentação própria.
A diferença entre tipagem dinâmica e tipagem estática é extremamente próxima da diferença entre programação comum e programação por contrato.