Como evitar as armadilhas da análise estática


17

Estou trabalhando em uma empresa com 11 pontos no Joel Test - pelo menos no papel.

Na prática, no entanto, nada funciona tão bem quanto o esperado, e o projeto está no DEFCON 1 há meio ano. Agora, a maioria dos meus colegas fica feliz se eles podem voltar para casa às 18h - no domingo.

Uma das práticas aparentemente boas que me pareceu não funcionar é o uso de ferramentas de análise estática. O projeto rastreia os avisos do gcc -Wall e uma ferramenta proprietária e muito cara "C / C ++" .

Os avisos do Gcc geralmente apontam para erros reais (se na maioria das vezes inofensivos).

As ferramentas proprietárias, no entanto, listam itens como projeções implícitas e tamanho de uma string literal. Elencos implícitos também estão na lista negra de seus livros de estilo.

A prática padrão é que as pessoas sejam pressionadas a calar todos os avisos. Observe que isso exclui avisos que são predominantemente falsos positivos, esse não é o problema.

O resultado é:

  1. As pessoas adicionam conversões de tipo a cada valor e a todos os argumentos, ocultando incompatibilidades de tipo problemáticas reais no processo.
  2. As pessoas se apresentam por um erro ou usam um recurso diferente de linguagem problemática (strlen em vez de sizeof, strncpy em vez de strcpy, etc.)
  3. Os avisos são silenciados.
  4. Os relatórios de erros começam a aparecer.

O ponto principal é que o código original estava funcionando e escrito por pessoas que estavam jogando com segurança dentro de suas habilidades de linguagem, enquanto as correções não estavam.

Agora, eu realmente não acho que essa empresa possa ser salva. No entanto, gostaria de saber se existe uma maneira melhor, de preferência funcionando, de usar as ferramentas "profissionais" ou se devo evitá-las por completo caso eu seja quem tome a decisão no futuro.

Uma solução que não assume que todos os programadores são gênios que não podem errar. Porque bem, se forem, não há necessidade de usar as ferramentas em primeiro lugar.


1
Nota lateral: o GCC, além de «-Wall», também possui a opção «-Wextra» e ainda mais avisos que não estão incluídos por algum motivo nas duas metaopções. Veja os documentos para mais informações. Em geral, todas as opções são mencionadas se ativadas por uma metaopção. Portanto, para encontrar tudo o que não está ativado, você pode destacar em todo o documento as palavras «-Wall» e «-Wextra» e veria o que ainda não foi usado.
Hi-Angel

Eu também acrescentaria que me pergunto que o GCC não incluiu muito de «Wextra» em «-Wall». Acredite, algumas dessas bandeiras são extremamente úteis ; pelo menos esses avisos me libertam de uma hora de depuração.
Hi-Angel

1
Estou surpreso que ninguém tenha mencionado revisões de código nas respostas. Para mim, as pessoas que tentam esgueirar-se em alguns hacks ruins teria sido bloqueado por revisões de código ...
dyesdyes

Respostas:


16

Na prática, no entanto, nada funciona tão bem quanto o esperado, e o projeto está no DEFCON 1 há meio ano. Agora, a maioria dos meus colegas fica feliz se eles podem voltar para casa às 18h - no domingo.

Este é certamente um bom pedaço do seu problema. Um engenheiro de software não pode trabalhar produtivamente por mais de 40 horas / semana. Se você ultrapassar isso, causa sérios danos à sua capacidade de trabalhar - a ponto de trabalhar 80 horas / semana trazer muito pouco valor ao projeto e, às vezes, os projetos podem até regredir porque a equipe introduz mais erros do que eles podem consertar. Se você trabalha 60 horas / semana ou mais há meio ano, toda a sua equipe precisa de uma boa pausa e voltar a 40 horas / semana. Você não pode resolver nada com uma força de trabalho que dificilmente pode se basear no teclado, porque eles estão sobrecarregados.

As ferramentas proprietárias, no entanto, listam itens como projeções implícitas e tamanho de uma string literal. Elencos implícitos também estão na lista negra de seus livros de estilo.

Você realmente precisa simplesmente largar a ferramenta completamente ou reconfigurá-la / substituí-la. Advertir sobre todo elenco implícito é demais para qualquer um lidar.


Você poderia fornecer uma referência a uma pesquisa com limite de 40 horas por semana?

11
aqui e aqui , apenas para iniciantes. Está extremamente bem documentado que você não pode fazer mais de 40 horas por semana de trabalho produtivo. Um simples Google encontrará várias resmas de artigos.
28412 DeadMG

5
Duas correções pequenas, mas importantes da IMHO: o limite de 40 horas / semana é um valor médio aproximado e a regra se aplica apenas a períodos prolongados. Não há problema em uma equipe dedicar horas extras antes de um prazo importante e depois se recuperar (talvez tirando alguns dias de folga). Além disso, o limite varia entre as pessoas e ao longo do tempo - algumas podem trabalhar 43 horas por semana sem problemas, outras apenas 35, e uma é mais produtiva em algumas semanas do que outras. No entanto, fazer horas extras significativas por mais de algumas semanas seguidas causará sérios problemas.
Péter Török

13

Estou trabalhando em uma empresa com 11 pontos no Joel Test - pelo menos no papel.

Esse teste é levemente relevante para empresas de software. Eu não entendo o hype sobre isso. Você pode marcar 12 e ainda ter 100% de programadores de merda. As pessoas importam muito mais do que ferramentas.

As ferramentas proprietárias, no entanto, listam itens como projeções implícitas e tamanho de uma string literal. Elencos implícitos também estão na lista negra de seus livros de estilo. A prática padrão é que as pessoas sejam pressionadas a calar todos os avisos. Observe que isso exclui avisos que são predominantemente falsos positivos, esse não é o problema.

Esse é o maior problema de todos os analisadores estáticos: muitos falsos positivos. A única maneira de lidar com isso é aprender em detalhes por que a ferramenta foi configurada para emitir um aviso para um determinado problema. Somente então você pode fazer suposições qualificadas sobre se um aviso é falso ou não.

Para o elenco específico de previsões implícitas, existe por causa de alguns erros muito comuns, sutis e perigosos na linguagem C, causados ​​pelas duas regras de promoção implícita (idiota) em C. Elas são formalmente conhecidas como regras de promoção inteira e as conversões aritméticas usuais . Acho que menos de um em cada dez programadores profissionais em C pode explicar o que essas duas regras fazem e o que não fazem. E, no entanto, essas regras são extremamente fundamentais e aplicadas milhares de vezes nas entrelinhas de qualquer programa C normal.

O padrão MISRA-C dedicou um capítulo inteiro para explicar essas regras perigosas de conversão implícita e, em seguida, adicionou várias regras bastante complexas sobre como evitar erros causados ​​pela conversão implícita. Isso teve algum impacto em todos os analisadores estáticos do mercado.

Eu recomendaria a qualquer programador de C que leia o capítulo MISRA-C ou, no mínimo, Google as duas regras de promoção que mencionei e leia o máximo possível sobre elas. Você só pode ignorar o analisador estático quando souber tudo o que há para saber sobre essas regras.

Agora, eu realmente não acho que essa empresa possa ser salva. No entanto, gostaria de saber se existe uma maneira melhor, de preferência funcionando, de usar as ferramentas "profissionais" ou se devo evitá-las por completo caso seja eu quem tome a decisão no futuro.

Uma solução que não assume que todos os programadores são gênios que não podem errar. Porque bem, se forem, não há necessidade de usar as ferramentas em primeiro lugar.

Não há uma maneira fácil de contornar isso. O verdadeiro problema não é realmente a ferramenta, mas a obscura linguagem C. Pode parecer uma linguagem fácil à primeira vista, mas existem muitos mecanismos ilógicos e estranhos acontecendo nas entrelinhas. E também existem centenas de casos de comportamento indefinido / não especificado / impl.específico no idioma. A maioria deles você deve aprender e evitar.

Portanto, você deve se tornar um programador veterano de C que entende todos esses avisos obscuros ou deve estar em uma equipe com pelo menos uma dessas pessoas. As empresas que contratam apenas um monte de programadores juniores sem veterano na equipe não devem usar essas ferramentas, nem devem trabalhar com desenvolvimento de software de alta integridade.


Fiz o teste com uma pitada de sal desde o início, mas não é uma ferramenta para testar programadores, mas uma ferramenta para testar os empregadores. Eu acho que você pode incluir colegas de trabalho como "as melhores ferramentas que o dinheiro pode pagar". E eu tomo sua resposta para jogar fora as ferramentas do SA e contratar e / ou treinar melhor. O primeiro ponto parece ser o denominador comum.

@qpr Também não testa o empregador, apenas a disposição do empregador em gastar dinheiro no desenvolvimento de software. Coisas como procedimento de recrutamento, objetivos corporativos, conhecimento de mercado, etc, etc. não são mencionados. Acho que a maioria das empresas de "bolha de TI" obteria 12 pontos nesse teste, com um gerenciamento que nem sequer sabe quais produtos estão sendo desenvolvidos ou se existe algum mercado para eles.

4

Não está claro se você está perguntando como corrigir o problema, ou como você poderia evitá-lo em primeiro lugar. Estou assumindo o último.

Parece que você confiou na análise estática como principal meio de detectar e evitar bugs. Talvez você estivesse melhor se concentrando mais em testes de unidade e ferramentas dinâmicas ... como verificadores de memória.

É uma má idéia confiar em uma ferramenta que gera muitos falsos positivos, especialmente se você não pode suprimir esses falsos positivos. Ele encoraja programadores cansados ​​/ sobrecarregados (ou preguiçosos) a fazer "correções" para fazer os avisos desaparecerem. Se você não pode suprimir seletivamente falsos positivos (por exemplo, com comentários) ou adaptar o conjunto de regras, precisará de uma ferramenta melhor. Ou pelo menos, você deve usá-lo apenas com moderação.

Parece que você tem um problema com pessoas descuidadas e / ou cometer erros devido ao excesso de trabalho. Talvez você devesse ter gasto mais tempo / esforço nas revisões de código. Isso aborda diretamente sua observação de que os programadores não são gênios.

Finalmente, parece que você pode estar sofrendo sob prazos irrealistas, recursos para pessoas pobres e / ou requisitos de mudança. Esse é um problema de gerenciamento e deve ser tratado nesse nível ... ou então existe um risco significativamente elevado de falha do projeto e danos a longo prazo à produtividade e ao moral da equipe.


3

Além da excelente resposta de user29079, gostaria de acrescentar mais uma deficiência da linguagem C que aumenta o problema. Eu não estava ciente dessa deficiência até mudar para o Java.

O objetivo de um aviso é chamar a atenção do escritor e dos futuros leitores do código para o fato de que algo está acontecendo. Isso, como conceito, está perfeitamente correto: quanto mais avisos você ativar, mais coisas suspeitas você descobrirá.

O que está absolutamente errado , é a noção de que todo pequeno peixe deve ser corrigido a todo custo, alterando o código . Foi isso que causou o problema que o OP está descrevendo: as tentativas frustradas de fazer os avisos desaparecerem às pressas, alterando o código que está funcionando bem.

Ao mesmo tempo, não queremos que nosso código libere centenas de avisos toda vez que compilamos, porque logo os avisos se tornam sem sentido e ninguém mais presta atenção a novos avisos.

Então, esse parece ser um caso de objetivos conflitantes; uma contradição.

Uma solução muito boa para esse dilema aparentemente impossível é ser capaz de suprimir seletivamente um determinado aviso, declaração por declaração, para que possamos suprimi-lo exatamente lá onde queremos indicar que realmente sabemos o que estamos fazendo, sem tendo que alterar qualquer código.

Java tem uma boa solução para isso, com a @SuppressWarnings( "" )anotação. Se você está fazendo, por exemplo, uma chamada conversão não verificada em java, o compilador emite um aviso para chamar sua atenção, você o examina e determina que esse é mais um daqueles casos em que você sabe o que está fazendo, portanto, você precede a declaração ofensiva com uma @SuppressWarnings( "unchecked" )anotação que afeta apenas a declaração que a segue imediatamente e prossegue com sua vida.

Portanto, o aviso desaparece, o código permanece inalterado e a anotação de supressão fica lá, colorida em verde pelo realce da sintaxe, para documentar o fato de que uma conversão duvidosa está ocorrendo, mas o autor promete que é bom. (*) Todo mundo está feliz.

No java, você pode até prefixar parâmetros individuais para as funções @SuppressWarnings(), para desativar um aviso específico que pode ser emitido apenas nesse parâmetro específico.

No entanto, até onde eu sei, C nunca deu suporte a nenhum mecanismo padrão para suprimir seletivamente avisos sobre instruções, e alguns compiladores que implementaram seus próprios mecanismos proprietários o fizeram de maneira perspicaz, por exemplo, as #pragma warning (nnn:N)diretivas da Microsoft C. O problema com essas diretivas é que você precisa de duas linhas de diretivas para suprimir um aviso para uma única instrução e deixar esse aviso ativado para as instruções a seguir. Portanto, é improvável que os programadores C adquiram o hábito de suprimir um aviso com base em declarações individuais, mesmo quando sabem que esse aviso específico nessa declaração específica está correto.


(*) alguém pode argumentar que, se você permitir, todos os programadores da casa suprimirão os avisos sem pensar neles; a resposta para isso é que você pode fazer tudo o que estiver ao seu alcance para ajudar os programadores a fazer seu trabalho melhor, mas não há nada que você possa fazer se eles decidirem sabotá-lo ativamente.


Em outras palavras, ao alterar a fonte para remover todos os avisos de última hora é fundamental para as boas práticas, alterar o código compilável não é, pois elimina o código direto que é simplesmente correto sem uma boa razão. Boa distinção.
Nathan Tuggy

2

Eu diria (sem saber os detalhes) que sua empresa cometeu erros mais significativos e este é apenas o sintoma: não conseguiu determinar adequadamente o domínio do software produzido, gerenciar a equipe adequadamente e definir metas razoáveis.

Se o software que sua equipe está escrevendo é algo crítico do qual a vida humana depende, as ferramentas de análise estática são importantes e úteis. Como o "custo" de um bug, medido em dinheiro (ignorando o quão cínico é), é alto, existem ferramentas especiais necessárias para o trabalho. Existem diretrizes para C e C ++ para o uso seguro dos recursos da linguagem (leia o que evitar e até que ponto evitá-lo).
No entanto, em uma situação em que os funcionários trabalham no domingo é uma péssima idéia, além do contexto que você forneceu, extrapolo que o trabalho malfeito não é pouco frequente. Então, se for esse o caso, o problema é muito, muitogrande e sua gerência está tentando resolvê-lo usando ferramentas "melhores". Infelizmente, não é assim que as coisas funcionam. Se eu estiver quase certo, eu sugeriria que você começasse a procurar um emprego diferente. Software de missão crítica mal feito é algo que pode assombrá-lo e arruinar sua reputação profissional, sem mencionar as perspectivas de um processo.

Se, por outro lado, sua equipe estiver escrevendo algo que é muito menos crítico, as ferramentas de 'análise estática' com uma alta taxa de falsos positivos apenas o atrasarão e, como você observou, as pessoas geralmente reagem a isso encontrando o máximo local em sua eficácia, neste caso, simplesmente enganando os avisos, em vez de tentar corrigir o motivo subjacente. Portanto, na sua situação, o uso dessas ferramentas pode realmente deteriorar a qualidade do código fonte, e elas geralmente devem ser evitadas.

Se você precisar gerenciar uma equipe de software que esteja escrevendo algum código C ou C ++, eu diria primeiro, quais são os principais objetivos do projeto. Se escrever código sem bugs é de extrema importância (por exemplo, o novo aplicativo social super impressionante para iOS e Android não se encaixa nisso), use a análise estática, talvez vá até a especificação formal e a verificação formal. Mas, se esse for o caso, escolher bons programadores e fazê-los trabalhar em um ambiente sadio, com carga de trabalho adequada e 40 horas semanais adequadas, é muito mais importante.

As pessoas não podem trabalhar com responsabilidade se forem tratadas como escravas (e alguém que ocupa minhas férias é exatamente isso) e bons programadores simplesmente se recusam a fazer isso regularmente, a menos que não saibam melhor (e se forem bons, as chances são de que eles fazem).

Ponto principal: calcule seus objetivos, determine as ferramentas e o processo que você usa, não deixe que as ferramentas disponíveis definam o processo (ergue os objetivos), pois o gerenciamento (ruim) pode forçar você.


1

Conforme indicado na resposta de k.steff, as ferramentas de análise estática para 'C' são úteis se você estiver construindo software em situações críticas (software de avião) e devem ser usadas desde o primeiro dia (não após meses de desenvolvimento quando ocorrer um erro não reproduzível) )

O uso desses tipos de ferramentas no final do processo de desenvolvimento geralmente é um sinal de más escolhas de design no início do processo.

No software não crítico, esses tipos de ferramentas são úteis para: -
garantir o gerenciamento, fazer com que se sintam úteis (fizemos algo, gastamos muito dinheiro para consertar o software). Ele fornece ações fáceis de serem executadas em seus relatórios em powerpoint).
-Manter os desenvolvedores 'tóxicos' ocupados. Deixe-os configurar a ferramenta e analisar os resultados da ferramenta, para que você possa ter tempo para corrigir seus erros desagradáveis.
regras de codificação. Nesse caso, ele deve ser usado desde o primeiro dia. Mas uma boa ferramenta de revisão de código pode ser a melhor escolha.

Portanto, minha opinião é que você deve evitar esses tipos de ferramentas caras e demoradas ou usá-las para manter as pessoas 'tóxicas' ocupadas.


1

Estou trabalhando em uma empresa com 11 pontos no Joel Test - pelo menos no papel.

A validação pelo teste Joel não é uma medida de boas práticas; A invalidação pelo teste de Joel é uma medida de práticas ruins / ausentes. Em outras palavras, pode ser visto como necessário, mas não suficiente.

Agora, a maioria dos meus colegas fica feliz se eles podem voltar para casa às 18h - no domingo.

Parece que você tem um problema de gerenciamento. Horas extras sistemáticas não são uma solução para fazer as coisas; se alguma coisa, é uma solução para fazer com que as coisas pareçam estar funcionando e acumulando dívida técnica.

Agora, eu realmente não acho que essa empresa possa ser salva. No entanto, gostaria de saber se existe uma maneira melhor, de preferência funcionando, de usar as ferramentas "profissionais" ou se devo evitá-las por completo caso seja eu quem tome a decisão no futuro.

Sim, existe uma maneira de usar a análise de código estático de uma maneira sã.

Eles podem, e geralmente fornecem muito valor. Você só precisa se lembrar que, (como avisos do compilador), uma ferramenta de análise estática pode (no máximo) fornecer dicas de que algo está errado - não relatórios de bugs e nenhuma certeza.

Parece que seus tomadores de decisão confundem sinalizadores de análise estática com defeitos de aplicativo.

Elencos implícitos também estão na lista negra de seus livros de estilo.

Isso soa como um problema de competência de gerenciamento, não um problema de análise estática.

O resultado é:

As pessoas adicionam conversões de tipo a cada valor e a todos os argumentos, ocultando incompatibilidades de tipo problemáticas reais no processo.

As pessoas se apresentam por um erro ou usam um recurso diferente de linguagem problemática (strlen em vez de sizeof, strncpy em vez de strcpy, etc.)

Os avisos são silenciados.

Os relatórios de erros começam a aparecer.

Todas essas são maneiras de fazer com que os relatórios periódicos pareçam bons, não maneiras de corrigir os problemas no código (parece que você tem um problema de competência de gerenciamento novamente).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.