Ninguém é perfeito, e não importa o que façamos, produziremos código que possui bugs de tempos em tempos. Quais são alguns métodos / técnicas para reduzir o número de erros que você produz, tanto ao escrever um novo software quanto ao alterar / manter o código existente?
30
Respostas:
Evite codificação sofisticada. Quanto mais complicado o código, maior a probabilidade de haver erros. Geralmente em sistemas modernos, o código claramente escrito será rápido e pequeno o suficiente.
Use bibliotecas disponíveis. A maneira mais fácil de não ter erros ao escrever uma rotina de utilidade é não escrevê-la.
Aprenda algumas técnicas formais para as coisas mais complicadas. Se houver condições complicadas, pregue-as com caneta e papel. Idealmente, conheça algumas técnicas de prova. Se eu puder provar que o código está correto, é quase sempre bom, exceto por erros grandes, burros e óbvios, fáceis de corrigir. Obviamente, isso só vai tão longe, mas às vezes você pode argumentar formalmente sobre coisas pequenas, mas complicadas.
Para o código existente, aprenda a refatorar: como fazer pequenas alterações no código, geralmente usando uma ferramenta automatizada, que torna o código mais legível sem alterar o comportamento.
Não faça nada muito rapidamente. Levar um pouco de tempo para fazer as coisas direito, verificar o que você fez e pensar no que está fazendo pode render muito tempo depois.
Depois de escrever o código, use o que for necessário para torná-lo bom. Os testes de unidade são ótimos. Geralmente, você pode escrever testes com antecedência, o que pode ser um ótimo feedback (se feito de forma consistente, esse é um desenvolvimento orientado a testes). Compile com as opções de aviso e preste atenção aos avisos.
Peça a alguém para olhar o código. Revisões de código formais são boas, mas podem não ser em um momento conveniente. Solicitações pull, ou similares, se o seu scm não suportá-las, permitir revisões assíncronas. A verificação de amigos pode ser uma revisão menos formal. A programação em pares garante que dois pares de olhos olhem para tudo.
fonte
Os testes de unidade permitem reduzir o número de erros que aparecem pela segunda vez. Se você encontrar um bug no seu código, escrever um teste de unidade garantirá que ele não volte mais tarde. (Além disso, às vezes é difícil pensar em todos os casos e escrever milhares de testes de unidade antecipadamente)
fonte
+1 nos dois comentários do teste de unidade.
Além disso, defina o nível de aviso mais alto que seu compilador oferece e verifique se os avisos são tratados como erros. Os erros geralmente se escondem nesses erros "errôneos".
Da mesma forma, invista em ferramentas de análise estática que são executadas em tempo de compilação (eu as vejo como um nível extra de avisos do compilador).
fonte
Além do que foi mencionado:
Estou esquecendo muitas outras coisas no momento, mas as outras certamente pensarão nelas. :)
fonte
Eu desenvolvi um estilo de programação bastante funcional, apesar de minhas principais linguagens serem C ++ e Python. Descobri que, se eu passar todo o contexto para uma função (ou método), essa função precisa fazer seu trabalho e retornar os dados significativos que estou procurando, meu código se tornará muito mais robusto.
O estado implícito é o inimigo e, na minha experiência, é a fonte número 1 de bugs. Esse estado pode ser variável global ou membro, mas se os resultados dependem de algo que não é passado para a função, você está solicitando problemas. Claramente, não é possível eliminar o estado, mas minimizá-lo tem enormes efeitos positivos na confiabilidade do programa.
Também gosto de dizer aos meus colegas de trabalho que todo ramo (se, por enquanto,? :) é um bug provável. Não sei dizer qual será a manifestação do bug, mas quanto menos comportamento condicional o seu código tiver, maior a probabilidade de ele estar livre de erros simplesmente devido ao fato de que a cobertura do código durante a execução será mais consistente.
Entenda, todas essas coisas também têm efeitos positivos no desempenho. Ganhar!
fonte
fonte
Uma resposta um pouco menos técnica: não programe quando estiver cansado (9h / dia é suficiente), bêbado ou assado. Quando estou cansado, não tenho a paciência necessária para escrever um código limpo.
fonte
Escreva testes de unidade e testes de integração .
fonte
Algumas ótimas respostas aqui sobre ferramentas e testes de unidade. A única coisa que posso adicionar a eles é esta:
Envolva seus testadores o mais cedo possível
Se você tem uma equipe de teste, não caia na armadilha de tratá-los como guardiões da qualidade do código e de detectar seus defeitos. Em vez disso, trabalhe com eles e envolva-os o mais cedo possível (em projetos ágeis, será desde o início do projeto, mas sempre podemos encontrar maneiras de envolvê-los mais cedo, se realmente tentarmos).
Ter um bom relacionamento de trabalho com seus testadores significa que você pode detectar preconceitos e defeitos ruins muito cedo, antes que eles possam causar algum dano. Isso também significa que os testadores se sentem capacitados para ajudar no design do produto e detectar problemas de usabilidade quando houver tempo para corrigi-los.
fonte
Ferramentas de análise estática
Plugins e aplicativos como o FindBugs rastreiam seu código e encontram lugares onde há possíveis erros. Locais onde as variáveis não são inicializadas e usadas ou apenas coisas loucas que 9 vezes em 10, facilitam a ocorrência de erros. Ferramentas como essa me ajudam a impedir que minha cabeça de osso se mova pela estrada, mesmo que ainda não seja um bug.
PS: Lembre-se de sempre pesquisar por que uma ferramenta diz que algo está ruim. Nunca é demais aprender (e nem tudo está certo em todas as situações).
fonte
Inspeção de código ou outras formas de revisão por pares, como programação em pares.
Revisões de código estruturado, como a inspeção de Fagan, podem ser pelo menos tão eficazes e eficientes quanto os testes de unidade e até provaram ser melhores do que os testes de unidade em alguns casos. As inspeções também podem ser usadas anteriormente no ciclo de vida do software e com artefatos diferentes do código.
Revisões por pares em software de Karl Wiegers é um ótimo livro sobre esse assunto.
fonte
Além de todas as outras sugestões aqui, ative todos os avisos possíveis para o mais alto nível de sensibilidade e trate-os como erros. Use também todas as ferramentas de fiapos que o idioma possui.
Você ficaria surpreso com quantos erros simples podem ser detectados por avisos e quantas dessas coisas simples se traduzem em erros reais no seu código.
fonte
Muitas boas respostas aqui, mas gostaria de acrescentar algumas coisas. Certifique-se de realmente entender o requisito. Eu já vi muitos bugs quando o usuário pensou que o requisito significava X e o programador achou que significa Y. Retorne para esclarecer sobre requisitos ruins ou ambíguos. Eu sei que todos nós gostamos de entrar e codificar, mas quanto mais tempo gastamos para garantir a compreensão, menos retrabalho e correção de erros haverá.
Conheça o negócio que você está apoiando, você verá muitas coisas nos requisitos que estão faltando ou que precisam de mais explicações. Saiba que se você executar a tarefa Y conforme indicado, ela interromperá o recurso Z.
Entenda sua estrutura de banco de dados. Muitos bugs são resultado de uma consulta sintaticamente correta, mas retorna os resultados incorretos. Aprenda a reconhecer quando seus resultados parecem engraçados. Se estou escrevendo uma consulta de relatório complexa, sempre solicito a um especialista técnico para revisar meus resultados antes de marcá-la como pronta para o trabalho, pois eles inevitavelmente verão algo nos dados que perdi. Depois, anote o que eles captaram e não se esqueça de que na próxima vez que fizer algo semelhante.
fonte
Eu acho que a técnica mais importante é levar o seu tempo . Se você acha que precisa de dois dias para codificar um novo módulo, mas o seu chefe o força a codificar apenas em um dia ... seu código provavelmente será mais problemático.
Um dos livros que li há algum tempo atrás dizia que você não deveria viver com janelas quebradas , porque as pessoas não se importariam se alguém quebrasse ... A codificação é a mesma, todos se importam em ser os primeiros a fazer algo ruim mas rápido , mas ninguém se importa com um código infernal , com muitos bugs e design e estilo muito ruins.
fonte
Sigo a prática do teste-código-teste em vez do código-teste-código-teste. Isso me ajuda a pensar em casos de uso e a enquadrar adequadamente a lógica
fonte
Use ferramentas de inspeção de código como ReSharper ou IDEs como IntelliJ IDEA que alertam sobre muitos bugs de copiar e colar e outros, por exemplo, apontando variáveis que "são gravadas, mas nunca lidas". Me salvou muito tempo.
fonte
Surpreendentemente, os três pontos muito importantes a seguir ainda não foram mencionados:
Use afirmações liberalmente. A pergunta que você deve sempre se perguntar não é "devo afirmar isso?" mas "há algo que eu esqueci de afirmar?"
Opte pela imutabilidade. (Use final / somente leitura liberalmente.) Quanto menos estado mutável você tiver, menos coisas poderão dar errado.
Não otimize prematuramente. Muitos programadores são desviados das preocupações com o desempenho, fazendo com que eles involuntariamente desnecessariamente seu código e bastardize seus projetos, sem sequer saber de antemão se o desempenho será um problema. Primeiro, construa seu produto de software da maneira acadêmica, desconsiderando o desempenho; depois, veja se o desempenho é ruim; (Provavelmente não.) Se houver algum problema de desempenho, encontre um ou dois lugares onde você pode fornecer otimizações algorítmicas legais e formais que farão com que seu produto atenda aos requisitos de desempenho, em vez de ajustar e hackear toda a sua base de códigos para aperte ciclos de relógio aqui e ali.
fonte