Pergunta

Você usa Design by Contract profissionalmente?É algo que você precisa fazer desde o início de um projeto ou você pode mudar de rumo e começar a incorporá-lo ao seu ciclo de vida de desenvolvimento de software?Quais você descobriu serem os prós/contras da abordagem de design?

Me deparei com Projeto por contrato abordagem em um curso de pós-graduação.No ambiente acadêmico, parecia ser uma técnica bastante útil.Mas atualmente não uso o Design by Contract profissionalmente e não conheço nenhum outro desenvolvedor que o esteja usando.Seria bom ouvir sobre seu uso real do pessoal do SO.

Foi útil?

Solução

Eu não posso recomendar o suficiente.É particularmente bom se você tiver um pacote que receba especificações de contrato de documentação inline, como:

// @returns null iff x = 0
public foo(int x) {
  ...
}

e os transforma em testes unitários gerados, assim:

public test_foo_returns_null_iff_x_equals_0() {
  assertNull foo(0);
}

Dessa forma, você pode ver os testes que está executando, mas eles são gerados automaticamente.A propósito, os testes gerados não devem ser verificados no controle de origem.

Outras dicas

Você realmente aprecia o design por contrato quando tem uma interface entre aplicativos que precisam se comunicar entre si.

Sem contratos esta situação rapidamente se transforma num jogo de culpabilização.As equipes continuam trocando acusações e uma enorme quantidade de tempo é desperdiçada.

Com um contrato, a culpa é clara.

O chamador satisfez as pré-condições?Caso contrário, a equipe do cliente precisará consertar.

Dada uma solicitação válida, o destinatário satisfez as pós-condições?Caso contrário, a equipe do servidor precisará consertar isso.

Ambas as partes aderiram ao contrato, mas o resultado é insatisfatório?O contrato é insuficiente e o problema precisa ser escalado.

Para isso não é necessário que os contratos sejam implementados na forma de afirmações, basta apenas garantir que estejam documentados e acordados por todas as partes.

Se você olhar para STL, boost, MFC, ATL e muitos projetos de código aberto, verá que há muitas declarações ASSERTION e isso torna o projeto mais seguro.

Design por contrato!Realmente funciona em produtos reais.

Frank Krueger escreve:

Caio:Uma exceção Null Pointer é lançada automaticamente pelo tempo de execução; não há benefício em testar esse material no prólogo da função.

Tenho duas respostas para isso:

  1. Nulo foi apenas um exemplo.Para square(x), gostaria de testar se a raiz quadrada do resultado é (aproximadamente) o valor do parâmetro.Para setters, gostaria de testar se o valor realmente mudou.Para operações atômicas, eu gostaria de verificar se todas as operações de componentes foram bem-sucedidas ou falharam (na verdade, um teste para sucesso en testes para falha).Para métodos de fábrica em linguagens de tipo fraco, quero verificar se o tipo correto de objeto foi retornado.A lista continua e continua.Basicamente, qualquer coisa que possa ser testada em uma linha de código é um bom candidato para um contrato de código em um comentário prólogo.

  2. Discordo que você não deva testar as coisas porque elas geram exceções de tempo de execução.Na verdade, você deve testar coisas que possam gerar exceções de tempo de execução.Gosto de exceções de tempo de execução porque elas tornam o sistema falhar rápido, o que ajuda na depuração.Mas o null no exemplo havia um valor de resultado para alguma entrada possível.Há um argumento a ser feito para nunca mais voltar null, mas se quiser, você deve testá-lo.

É absolutamente tolo não projetar por contrato ao fazer qualquer coisa em um domínio SOA, e é sempre útil se você estiver trabalhando em qualquer tipo de trabalho modular, onde partes e peças podem ser trocadas mais tarde, especialmente se alguma caixa preta estiver envolvida .

Em vez de sistemas de tipos mais expressivos, eu usaria absolutamente o design por contrato em projetos de nível militar.

Para linguagens de tipo fraco ou com escopo dinâmico (PHP, JavaScript), contratos funcionais também são muito úteis.

Para todo o resto, eu deixaria isso de lado e confiaria em testadores beta e testes de unidade.

Caio:Uma exceção Null Pointer é lançada automaticamente pelo tempo de execução; não há benefício em testar esse material no prólogo da função.Se você estiver mais interessado em documentação, eu usaria anotações que podem ser usadas com analisadores estáticos e similares (para garantir que o código não esteja quebrando suas anotações, por exemplo).

Um sistema de tipos mais forte aliado ao Design by Contract parece ser o caminho a seguir.Dê uma olhada Especificação# Por exemplo:

A linguagem de programação Spec#.Spec# é uma extensão da linguagem orientada a objetos C#.Ele estende o sistema de tipos para incluir tipos não nulos e exceções verificadas.Ele fornece contratos de método na forma de pré e pós-condicionas, bem como invariantes de objetos.

Tanto os testes unitários quanto o Design by Contract são abordagens de teste valiosas em minha experiência.

Eu tentei usar Design by Contract em uma estrutura de teste automático de sistema e minha experiência é que isso oferece flexibilidade e possibilidades que não são facilmente obtidas por testes unitários.Por exemplo, é possível executar uma sequência mais longa e verificar se os tempos de resposta estão dentro dos limites toda vez que uma ação é executada.

Olhando as apresentações no InfoQ parece que o Design by Contract é uma adição valiosa aos testes unitários convencionais na fase de integração de componentes.Por exemplo, é possível criar uma interface simulada primeiro e depois usar o componente após ou quando uma nova versão de um componente é lançada.

Não encontrei um kit de ferramentas cobrindo todo o meu requisito de design para projetar por teste de contrato na plataforma .NET/Microsoft.

Na verdade, não uso o Design by Contract diariamente.No entanto, sei que foi incorporado no D língua, como parte da língua.

Sim!Na verdade, há alguns anos, projetei uma pequena estrutura para validação de argumentos.Eu estava fazendo um projeto SOA, no qual os diferentes sistemas back-end faziam todo tipo de validação e verificação.Mas para aumentar os tempos de resposta (nos casos em que a entrada era inválida, e para reduzir a carga desses sistemas back-end), começamos a validar os parâmetros de entrada dos serviços prestados.Não apenas para Not Null, mas também para padrões String.Ou valores de dentro de conjuntos.E também os casos em que os parâmetros tinham dependências entre eles.

Agora percebo que implementamos naquela época um pequeno projeto por estrutura de contrato :)

Aqui está o link para quem está interessado no pequeno Validação de argumento Java estrutura.Que é implementado como uma solução Java simples.

Acho revelador que a linguagem de programação Go não tenha construções que tornem possível o design por contrato.pânico/adiar/recuperar não são exatamente isso, pois a lógica de adiar e recuperar torna possível ignorar o pânico, IOW para ignorar o contrato quebrado.O que é necessário, no mínimo, é alguma forma de pânico irrecuperável, que seja realmente afirmado.Ou, na melhor das hipóteses, suporte direto à linguagem de design por construções contratuais (pré e pós-condições, implementação e invariantes de classe).Mas dada a teimosia dos puristas da linguagem no comando do Go Ship, dou poucas mudanças em relação a tudo isso.

Pode-se implementar um comportamento semelhante ao de afirmação verificando se há erro de afirmação especial na última função defer na função de pânico e chamando runtime.Breakpoint() para despejar a pilha durante a recuperação.Para ser afirmativo, esse comportamento precisa ser condicional.É claro que essa abordagem desmorona quando uma nova função defer é adicionada após aquela que faz assert.O que acontecerá em projetos grandes exatamente na hora errada, resultando em bugs perdidos.

O que quero dizer é que assert é útil de tantas maneiras que ter que dançar em torno dele pode ser uma dor de cabeça.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top