Por que há suporte limitado para Design by Contract na maioria das linguagens de programação modernas?

39

Eu descobri recentemente o Design by Contract (DbC) e acho que é uma maneira extremamente interessante de escrever código. Entre outras coisas, parece oferecer:

  • Melhor documentação. Como o contrato é a documentação, é impossível que alguém esteja desatualizado. Além disso, como o contrato especifica exatamente o que uma rotina faz, ajuda a suportar a reutilização.
  • Depuração mais simples. Como a execução do programa para no momento em que um contrato falha, os erros não podem se propagar, e a asserção específica violada provavelmente será destacada. Isso oferece suporte durante o desenvolvimento e durante a manutenção.
  • Melhor análise estática. O DbC é basicamente apenas uma implementação da lógica Hoare, e os mesmos princípios devem ser aplicados.

Os custos, em comparação, parecem ser bem pequenos:

  • digitação extra. Desde que os contratos têm que ser soletrados para fora.
  • Leva um pouco de treinamento para se sentir confortável com contratos de redação.

Agora, estando familiarizado com o Python principalmente, percebo que é de fato possível escrever pré-condições (apenas lançando exceções para entradas inadequadas) e até mesmo é possível usar asserções para testar novamente certas pós-condições. Mas não é possível simular certas características como "antigo" ou "resultado" sem alguma mágica extra que seria considerada não-Pythonica. (Além disso, existem algumas bibliotecas que oferecem suporte, mas no final das contas eu recebo a vibe que seria errado usá-las, como a maioria dos desenvolvedores não faz.) Eu assumo que é um problema similar para todas as outras linguagens (exceto claro , Eiffel).

Minha intuição me diz que a falta de apoio deve ser resultado de algum tipo de rejeição à prática, mas a pesquisa on-line não foi proveitosa. Eu estou querendo saber se alguém pode esclarecer por que a maioria das linguagens modernas parece oferecer tão pouco suporte? DbC é falho ou excessivamente caro? Ou é apenas obsoleto devido à Extreme Programming e outras metodologias?

    
por Ceasar Bautista 06.01.2012 / 01:01
fonte

9 respostas

8

Indiscutivelmente, eles são suportados em praticamente todas as linguagens de programação.

O que você precisa é de "afirmações".

Eles são facilmente codificados como declarações "if":

if (!assertion) then AssertionFailure();

Com isso, você pode escrever contratos colocando essas asserções no topo do seu código para restrições de entrada; aqueles nos pontos de retorno são restrições de saída. Você pode até adicionar invariantes em todo o seu código (embora não façam parte de "design por contrato").

Então, eu argumento que eles não são muito difundidos porque os programadores têm preguiça de codificá-los, não porque você não pode fazer isso.

Você pode torná-los um pouco mais eficientes na maioria das linguagens definindo uma constante booleana em tempo de compilação, "verificando" e revisando as declarações um pouco:

if (checking & !Assertion) then AssertionFailure();

Se você não gosta da sintaxe, pode recorrer a várias técnicas de abstração de linguagem, como macros.

Algumas linguagens modernas oferecem uma ótima sintaxe para isso, e é isso que eu acho que você quer dizer com "suporte moderno a idiomas". Isso é apoio, mas é bem fino.

O que a maioria das linguagens modernas não lhe dá é asserções "temporais" (sobre estados arbitrários anteriores ou seguintes [operador temporal "eventualmente"], o que você precisa se quiser escrever contratos realmente interessantes. te ajude aqui.

    
por 16.01.2012 / 04:34
fonte
15

Como você diz, Design by Contract é um recurso em Eiffel, que tem sido uma daquelas linguagens de programação que é bem respeitada na comunidade, mas que nunca pegou.

O DbC não está em nenhuma das linguagens mais populares, porque é relativamente recente que a comunidade de programação mainstream chegou a aceitar que adicionar restrições / expectativas ao seu código é uma coisa "razoável" para esperar dos programadores. Agora é comum os programadores entenderem o quão valioso é o teste unitário, e isso é percorrido até que os programadores tenham mais aceitação de colocar código para validar seus argumentos e ver os benefícios. Mas uma década atrás, provavelmente a maioria dos programadores diria "isso é apenas um trabalho extra para coisas que você sabe que sempre vai ficar bem".

Eu acho que se você fosse para o desenvolvedor médio hoje e falasse sobre pós-condições, eles acenariam entusiasticamente e diriam "OK, isso é como testes unitários". E se você falar sobre pré-condições, eles dirão "OK, é como validação de parâmetro, o que nem sempre fazemos, mas, sabe, eu acho que está tudo bem ..." E então se você fala sobre invariantes , eles começariam a dizer "Nossa, quanta sobrecarga é essa? Quantos mais insetos vamos pegar?" etc

Então, acho que ainda há um longo caminho a percorrer antes que o DbC seja amplamente adotado.

    
por 06.01.2012 / 02:25
fonte
7

My intuition tells me that the lack of support must be a result of some kind of rejection of the practice,...

Falso.

É uma prática design . Ele pode ser incorporado explicitamente em código (estilo Eiffel) ou implicitamente em código (na maioria das linguagens) ou em testes de unidade. A prática de design existe e funciona bem. O suporte ao idioma está em todo o mapa. Está, no entanto, presente em muitas línguas na estrutura de teste de unidade.

I'm wondering if someone can clarify why most modern languages seem to offer so little support? Is DbC flawed or overly expensive?

É caro. E. Mais importante, existem algumas coisas que não podem ser provadas em uma determinada língua. A terminação de loop, por exemplo, não pode ser comprovada em uma linguagem de programação, requer uma capacidade de prova de "ordem superior". Assim, alguns tipos de contratos são tecnicamente inexprimíveis.

Or is it just obsolete due to Extreme Programming and other methodologies?

Não.

Utilizamos principalmente testes unitários para demonstrar que o DbC é cumprido.

Para o Python, como você observou, o DbC vai em vários lugares.

  1. Os resultados do teste docstring e docstring.

  2. Afirmações para validar entradas e saídas.

  3. Testes de unidade.

Além disso.

Você pode adotar ferramentas de estilo de programação literárias para que você escreva um documento que inclua as informações do DbC e que gere scripts limpos de teste de unidade do Python. A abordagem de programação letrada permite que você escreva uma boa parte da literatura que inclui os contratos e a fonte completa.

    
por 06.01.2012 / 11:54
fonte
5

Apenas adivinhando. Talvez parte da razão pela qual não é tão popular é porque "Design by Contract" é uma marca registrada de Eiffel.

    
por 06.01.2012 / 08:29
fonte
3
Uma hipótese é que, para um programa complexo suficientemente grande, especialmente aqueles com um alvo em movimento, a massa de contratos em si pode se tornar tão problemática e difícil de depurar, ou mais, do que o código do programa sozinho. Como acontece com qualquer padrão, pode haver um uso de retornos decrescentes do passado, bem como vantagens claras quando usados de maneira mais objetiva.

Outra conclusão possível é que a popularidade das "linguagens gerenciadas" é a prova atual do suporte de projeto por contrato para os recursos gerenciados selecionados (limites de matriz por contrato, etc.)

    
por 06.01.2012 / 03:00
fonte
2

A razão pela qual a maioria dos idiomas tradicionais não tem recursos de DbC na linguagem é a relação custo-benefício da implementação é alta para o implementador de idiomas.

um lado disso já foi examinado em outras respostas, testes de unidade e outros mecanismos de tempo de execução (ou até mesmo alguns mecanismos de tempo de compilação com metaprogramação de modelo) podem dar a você boa parte da bondade do DbC. Portanto, embora haja um benefício, é provavelmente visto como bastante modesto.

O outro lado é o custo, encaixar retroativamente o DbC em uma linguagem existente é provavelmente uma mudança muito grande e muito complexa. Introduzir nova sintaxe em um idioma sem quebrar o código antigo é difícil. Atualizar sua biblioteca padrão existente para usar uma mudança tão abrangente seria caro. Portanto, podemos concluir que a implementação de recursos do DbC em um idioma existente tem um alto custo.

Eu também observaria os conceitos que são contratos para modelos e, portanto, um pouco relacionados para DbC, foram retirados do mais recente padrão C ++, já que, mesmo após anos de trabalho sobre eles, estimava-se que ainda precisavam de anos de trabalho. Esse tipo de mudanças grandes e amplas nas linguagens é muito difícil de ser implementado.

    
por 16.01.2012 / 14:39
fonte
2

O DbC seria usado mais extensivamente se os contratos pudessem ser verificados em tempo de compilação, para que não fosse possível executar um programa que violasse qualquer contrato.

Sem suporte ao compilador, "DbC" é apenas um nome para "verificar invariantes / suposições e lançar uma exceção se violada".

    
por 16.01.2012 / 16:18
fonte
0

Eu tenho uma explicação simples, a maioria das pessoas (incluindo programadores) não quer trabalho extra a menos que seja necessário. A programação aviônica, em que a segurança é considerada muito importante, não vi a maioria dos projetos sem ela.

Mas se você estiver pensando em programação para sites, estações de trabalho ou dispositivos móveis - falhas e comportamentos inesperados às vezes não são considerados tão ruins e programadores simplesmente evitam trabalho extra ao relatar bugs e depois consertá-los é considerado suficiente.

Esta é provavelmente a razão pela qual Ada nunca aprendeu fora da indústria de programação de aviação porque é preciso mais trabalho de codificação, embora Ada seja uma linguagem incrível e se você quer construir um sistema confiável, é a melhor linguagem para o trabalho (excluindo SPARK qual linguagem proprietária baseada em Ada).

O design por bibliotecas de contrato para C # foi experimental pela Microsoft, e eles são muito úteis para construir softwares confiáveis, mas eles nunca ganharam impulso no mercado, caso contrário você os teria visto como parte da linguagem C #.

As asserções não são iguais ao suporte totalmente funcional para condições pré / pós e invariantes. Embora possa tentar emulá-los, mas uma linguagem / compilador com suporte apropriado faz a análise da 'árvore de sintaxe abstrata' e verifica erros de lógica que simplesmente afirmações não podem.

Editar: Eu fiz uma pesquisa e seguir é uma discussão relacionada que pode ser útil: link

    
por 08.08.2017 / 03:41
fonte
-2

Principalmente as razões são as seguintes:

  1. Só está disponível em idiomas que não são populares
  2. É desnecessário já que o mesmo material pode ser feito de maneira diferente nas linguagens de programação existentes por qualquer um que realmente queira fazer isso
  3. É difícil de entender e usar - requer conhecimento especializado para fazer isso corretamente, então há um pequeno número de pessoas fazendo isso
  4. requer grandes quantidades de código para fazê-lo - os programadores preferem minimizar a quantidade de caracteres que escrevem - se precisar de um longo pedaço de código, algo deve estar errado com ele
  5. as vantagens não estão lá - simplesmente não é possível encontrar bugs suficientes para fazer valer a pena
por 06.01.2012 / 02:35
fonte