Como engenheiro de software, escrevo muitos códigos para produtos industriais. Coisas relativamente complicadas com classes, threads, alguns esforços de design, mas também alguns compromissos de desempenho. Eu faço muitos testes e estou cansado de testar, então fiquei interessado em ferramentas formais de prova, como Coq, Isabelle ... Posso usar uma delas para provar formalmente que meu código está livre de erros e está pronto com isso? - mas cada vez que verifico uma dessas ferramentas, deixo de me convencer de que elas são utilizáveis na engenharia de software cotidiana. Agora, isso poderia ser apenas eu, e estou procurando dicas / opiniões / idéias sobre isso :-)
Especificamente, tenho a impressão de que fazer com que uma dessas ferramentas funcione para mim exigiria um grande investimento para definir adequadamente para o provador os objetos, métodos ... do programa em consideração. Então eu me pergunto se o provador não ficaria sem força, dado o tamanho de tudo o que teria que lidar. Ou talvez eu tivesse que me livrar dos efeitos colaterais (essas ferramentas de teste parecem se sair muito bem com linguagens declarativas) e me pergunto se isso resultaria em "código comprovado" que não poderia ser usado porque não seria rápido ou pequeno o suficiente. Além disso, não tenho o luxo de alterar a linguagem com a qual trabalho, ela precisa ser Java ou C ++: não posso dizer ao meu chefe que vou codificar no OXXXml a partir de agora, porque é a única linguagem em que posso provar a correção do código ...
Alguém com mais experiência em ferramentas formais de prova pode comentar? Mais uma vez - eu AMO usar uma ferramenta formal, provador, eu acho que eles são grandes, mas tenho a impressão de que eles estão em uma torre de marfim que eu não posso chegar da vala humilde de Java / C ++ ... (PS: I Também AMO Haskell, OCaml ... não entendi errado: sou fã de linguagens declarativas e provas formais, só estou tentando ver como eu poderia realisticamente tornar isso útil para a engenharia de software)
Atualização: Como isso é bastante amplo, vamos tentar as seguintes perguntas mais específicas: 1) existem exemplos de uso de provadores para provar a exatidão de programas industriais Java / C ++? 2) Coq seria adequado para essa tarefa? 3) Se Coq for adequado, devo escrever o programa em Coq primeiro e gerar C ++ / Java a partir de Coq? 4) Essa abordagem poderia lidar com otimizações de encadeamento e desempenho?
Respostas:
Tentarei dar uma resposta sucinta a algumas de suas perguntas. Lembre-se de que este não é estritamente meu campo de pesquisa; portanto, algumas das minhas informações podem estar desatualizadas / incorretas.
Existem muitas ferramentas projetadas especificamente para provar formalmente propriedades de Java e C ++.
No entanto, preciso fazer uma pequena digressão aqui: o que significa provar a correção de um programa? O verificador de tipo Java prova uma propriedade formal de um programa Java, ou seja, que certos erros, como adicionar um
float
e umint
, nunca podem ocorrer! Eu imagino que você esteja interessado em propriedades muito mais fortes, a saber: seu programa nunca pode entrar em um estado indesejado ou que a saída de uma determinada função esteja em conformidade com uma determinada especificação matemática. Em resumo, existe um amplo gradiente do que "provar um programa correto" pode significar, desde simples propriedades de segurança até uma prova completa de que o programa atende a uma especificação detalhada.Agora vou assumir que você está interessado em provar propriedades fortes sobre seus programas. Se você estiver interessado em propriedades de segurança (seu programa não pode atingir um determinado estado), em geral, parece que a melhor abordagem é a verificação de modelo . No entanto, se você deseja especificar completamente o comportamento de um programa Java, sua melhor aposta é usar uma linguagem de especificação para essa linguagem, por exemplo, JML . Existem linguagens para especificar o comportamento de programas em C, por exemplo ACSL , mas não sei sobre C ++.
Depois de ter suas especificações, você precisa provar que o programa está em conformidade com essa especificação.
Para isso, você precisa de uma ferramenta que tenha um entendimento formal da sua especificação e da semântica operacional da sua linguagem (Java ou C ++), a fim de expressar o teorema da adequação , ou seja, que a execução do programa respeite a especificação.
Essa ferramenta também deve permitir que você formule ou gere a prova desse teorema. Agora, essas duas tarefas (especificar e provar) são bastante difíceis, portanto são frequentemente separadas em duas:
Uma ferramenta que analisa o código, a especificação e gera o teorema da adequação. Como Frank mencionou, Krakatoa é um exemplo dessa ferramenta.
Uma ferramenta que comprova o (s) teorema (s), automática ou interativamente. A Coq interage com o Krakatoa dessa maneira, e existem algumas ferramentas automatizadas poderosas como o Z3 que também podem ser usadas.
Um ponto (menor): existem alguns teoremas muito difíceis de serem provados com métodos automatizados, e sabe-se que os provadores automáticos de teoremas ocasionalmente têm bugs de sonoridade que os tornam menos confiáveis. Esta é uma área em que a Coq brilha em comparação (mas não é automática!).
Se você deseja gerar o código Ocaml, escreva definitivamente em Coq (Gallina) primeiro e depois extraia o código. No entanto, Coq é péssimo na geração de C ++ ou Java, se for possível.
As ferramentas acima podem lidar com problemas de encadeamento e desempenho? Provavelmente não, as preocupações de desempenho e segmentação são melhor tratadas por ferramentas projetadas especificamente, pois são problemas particularmente difíceis. Não tenho certeza se tenho alguma ferramenta para recomendar aqui, embora o projeto PolyNI de Martin Hofmann pareça interessante.
Concluindo: a verificação formal dos programas Java e C ++ do "mundo real" é um campo amplo e bem desenvolvido, e o Coq é adequado para partes dessa tarefa. Você pode encontrar uma visão geral de alto nível aqui, por exemplo.
fonte
Eu gostaria de mencionar três aplicações notáveis de métodos formais / ferramentas de verificação formais na indústria ou em sistemas reais não triviais. Note que tenho pouca experiência neste tópico e só os aprendo lendo jornais.
A ferramenta de código aberto Java Pathfinder (JPF, abreviada) lançada pela NASA em 2005 é um sistema para verificar programas executáveis de bytecode Java (consulte Java Pathfinder @ wiki ). Ele foi usado para detectar inconsistências no software executivo do K9 Rover da NASA Ames.
Este documento: Usando a Verificação de Modelo para Encontrar Erros Graves no Sistema de Arquivos @ OSDI'04 mostra como usar a verificação de modelo para encontrar erros graves nos sistemas de arquivos. Um sistema chamado FiSC é aplicado a três sistemas de arquivos amplamente utilizados e altamente testados: ext3, JFS e ReiserFS e 32 bugs graves. Ele ganhou o prêmio de melhor artigo.
Este documento: Como o Amazon Web Services usa métodos formais @ CACM'15 descreve como a AWS aplica métodos formais a seus produtos, como S3, DynamoDB, EBS e Internal Distributed Lock Manager. Ele se concentra na ferramenta TLA + da Lamport . A propósito, Lamport usou intensivamente sua própria caixa de ferramentas TLA. Ele geralmente dá uma verificação formal (bastante completa) no TLA dos algoritmos / teoremas propostos por ele (e também pelos co-autores) em apêndices aos artigos.
fonte
Uma especificação formal de um programa é (mais ou menos) um programa escrito em outra linguagem de programação. Como resultado, a especificação certamente incluirá seus próprios erros.
A vantagem da verificação formal é que, como o programa e a especificação são duas implementações separadas, seus erros serão diferentes. Mas nem sempre: uma fonte comum de bugs, casos negligenciados, geralmente corresponde. Assim, a verificação formal não é uma panacéia: ainda pode perder um número não trivial de bugs.
Uma desvantagem da verificação formal é que ela pode impor algo como o dobro do custo de implementação, provavelmente mais (você precisa de um especialista em especificação formal e precisa usar as ferramentas mais ou menos experimentais que a acompanham; isso não sai barato )
Eu acho que configurar casos de teste e andaimes para executá-los automaticamente seria uma melhor utilização do seu tempo.
fonte
A verificação formal agora é possível para programas gravados em um subconjunto de C ++ projetado para sistemas embarcados críticos para a segurança. Veja http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.ppt para uma breve apresentação e http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.pdf para o artigo completo.
fonte
Você faz algumas perguntas diferentes. Concordo que parece que os métodos formais de verificação para aplicações industriais / comerciais não são tão comuns. No entanto, deve-se perceber que muitos princípios de "verificação formal" são incorporados aos compiladores para determinar a correção do programa! de certa forma, se você usa um compilador moderno, está usando grande parte do estado da arte na verificação formal.
Você diz "Estou cansado de testar", mas a verificação formal não é realmente um substituto para o teste. de certa forma, é uma variação nos testes.
Você menciona Java. existem muitos métodos formais avançados de verificação incorporados a um programa de verificação java chamado FindBugs, que de fato podem ser executados em grandes bases de código. Observe que ele exibirá "falsos positivos e falsos negativos" e os resultados precisam ser revisados / analisados por um desenvolvedor humano. Mas observe que, mesmo que não esteja aparecendo defeitos funcionais reais, geralmente aparecem "antipatterns" que devem ser evitados no código de qualquer maneira.
Você não menciona mais sua aplicação específica, exceto "industrial". A verificação formal na prática tende a depender da aplicação específica.
As técnicas formais de verificação parecem ser amplamente usadas no EE para provar a correção do circuito, por exemplo, no projeto do microprocessador.
Aqui está um exemplo de uma pesquisa de ferramentas formais de verificação no campo EE por Lars Philipson .
fonte
Talvez um verificador de modelos possa ser útil.
http://alloytools.org/documentation.html Alloy é um verificador de modelos.
Uma boa apresentação explicando o conceito de verificação de modelo usando o Alloy: https://www.youtube.com/watch?v=FvNRlE4E9QQ
Na mesma família de ferramentas, vem os 'testes baseados em propriedades', todos tentam encontrar um contra-exemplo para o modelo de especificação fornecido pelo seu software.
fonte