O Caso Contra a Verificação Formal, 50 Anos Depois
A verificação formal de software é revisitadda à luz de uma famosa crítica de 1979, com muitos argumentando que, embora provas completas de ponta a ponta ainda sejam impraticáveis para sistemas reais e desorganizados, a verificação direcionada de componentes críticos (por exemplo, datastores distribuídos, compiladores, mecanismos de políticas) é tanto viável quanto valiosa. Os comentários destacam que especificar comportamento rigorosamente costuma ser mais difícil do que escrever código, que a lacuna entre modelo e código e a evolução dos requisitos limitam o alcance das provas, e que a maioria das falhas reais decorre de especificações defeituosas ou inconsistentes, e não de bugs de implementação. Há um otimismo cauteloso de que sistemas de tipos mais poderosos, ferramentas melhores e assistência por IA possam tornar os métodos formais mais acessíveis, mas também preocupação de que provas cristalizem maus projetos e de que os incentivos econômicos ainda favoreçam software “bom o suficiente” em vez de correção matematicamente garantida.
Escopo e praticidade da verificação formal
- Muitos veem a verificação de sistemas completos como intratável para produtos bagunçados e em evolução (por exemplo, redes sociais, GUIs), mas concordam que verificar subsistemas e propriedades específicas é valioso.
- GUIs são vistas como especialmente difíceis de especificar; alguns mencionam abordagens de GUI baseadas em restrições como mais próximas de especificações, principalmente para evitar bugs óbvios de interface.
- Vários comentários enfatizam que não há necessidade de “tudo ou nada”: verificar permissões, idempotência de APIs, consistência distribuída e propriedades de ausência de perda de dados já é extremamente útil.
Verificação formal vs testes
- A verificação é apresentada como garantia de propriedades para todas as execuções, enquanto os testes amostram execuções.
- Testes baseados em propriedades e testes de mutação são discutidos como técnicas intermediárias; fuzzing e testes aleatórios se beneficiam de especificações claras.
- Alguns argumentam que deveríamos pensar em métodos formais como “testes com esteroides”, não como substitutos.
Especificações: benefícios, dificuldade e correção
- Há discordância sobre se especificações são mais fáceis de entender do que código: alguns acham especificações formais mais concisas e próximas da intenção; outros as consideram mais difíceis do que implementações.
- Exemplos históricos (operações de ponto flutuante, compressão, sistemas de arquivos, bancos de dados, redes) são citados como casos em que as especificações são simples e as implementações são complexas.
- Um longo subthread sobre “ordenação” ilustra como especificações aparentemente triviais são fáceis de errar sutilmente, reforçando que escrever especificações corretas também é difícil.
- Surge a հարցao: por que assumir que a especificação é mais correta do que o programa? Respostas: verificar muitas vezes é mais fácil do que construir; especificações podem ser mais simples; mas erros de especificação são reais e devem ser tratados como bugs.
Economia, incentivos e regulação
- Economias no estilo de hardware (bugs custam milhões) justificam verificação pesada; software normalmente depende de correções baratas posteriormente.
- Alguns argumentam que software robusto já existe onde os compradores pagam por isso (bancos, aviação); outros observam que o software de consumo típico continua com bugs.
- Há preocupação de que “selos” regulatórios de verificação possam virar carimbos burocráticos sem ganhos reais de qualidade.
IA, ferramentas e a lacuna modelo–código
- Limitações passadas incluíam notações ruins e poder de computação insuficiente; solucionadores modernos SAT/SMT, assistentes de provas e LLMs aliviam parte do peso.
- A IA atualmente é mais eficaz nas mãos de especialistas; há esperança de que agentes eventualmente gerem especificações e provas para módulos profundos com invariantes simples.
- A lacuna modelo–código (por exemplo, especificação em TLA+ vs código em Rust) é vista como um problema central; mitigations sugeridas incluem:
- Assistentes de prova que geram código executável.
- Linguagens e ecossistemas (por exemplo, SPARK/Ada, sistemas de tipos mais ricos, motores de políticas verificados) em que especificações e código sejam fortemente integrados.
- Alguns temem que provas e testes de granularidade fina congelem abstrações ruins e dificultem refatorações.
Requisitos vs implementação
- Vários participantes argumentam que, em muitos projetos reais, as principais falhas são requisitos inconsistentes ou impossíveis, não código incorreto.
- Eles sugerem que a maior necessidade é de ferramentas que ajudem a formalizar e verificar requisitos contra restrições técnicas e de negócio, e não apenas implementações.