Os bugs que entram no código podem ser minimizados, mas não totalmente eliminados como está escrito - os programadores são, embora muitos discordem , apenas humanos.
Quando detectamos um erro em nosso código, o que podemos fazer para eliminá-lo? Como devemos abordá-lo para fazer o uso mais eficaz de nosso tempo valioso e nos permitir gastar menos tempo tentando encontrá-lo e mais tempo codificando? Além disso, o que devemos evitar ao depurar?
Observe aqui que não estamos falando sobre prevenção de bugs; nós estamos falando sobre o que fazer quando os erros não aparecem. Este é um campo amplo, eu sei, e pode ser altamente dependente de linguagem, plataforma e ferramentas. Nesse caso, mantenha respostas abrangentes, como mentalidades e métodos gerais.
Respostas:
A mentalidade e a atitude em relação à depuração é talvez a parte mais importante, porque determina com que eficácia você corrigirá o erro e o que aprenderá com ele - se houver.
Clássicos sobre desenvolvimento de software como The Pragmatic Programmer e Code Complete argumentam basicamente pela mesma abordagem: todo erro é uma oportunidade de aprender, quase sempre sobre você (porque apenas os iniciantes culpam o compilador / computador primeiro).
Então, trate-o como um mistério que será interessante desvendar. E desvendar esse mistério deve ser feito sistematicamente, expressando nossas suposições (para nós mesmos ou para outras pessoas) e testando nossas suposições, uma por uma, se necessário - usando todas as ferramentas à nossa disposição, especialmente depuradores e estruturas de teste automatizadas. Depois que o mistério for resolvido, você poderá se sair ainda melhor examinando todo o seu código em busca de erros semelhantes que você possa ter cometido; e escreva um teste automatizado para garantir que o erro não ocorra novamente sem o saber.
Uma última observação - prefiro chamar erros de "erros" e não de "bugs" - Dijkstra censurou seus colegas por usar o último termo porque é desonesto, apoiando a idéia de que fadas perniciosas e inconstantes plantaram bugs em nossos programas enquanto não estávamos ' procurando, em vez de estar lá por causa de nosso próprio pensamento (desleixado): http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1036.html
fonte
Escreva testes. O teste não é apenas excelente na prevenção de bugs (na minha experiência, o TDD feito corretamente elimina quase todos os bugs triviais e estúpidos), mas também ajuda muito na depuração. O teste força seu design a ser bastante modular, o que facilita muito o isolamento e a replicação do problema. Além disso, você controla o ambiente, para que haja muito menos surpresas. Além disso, depois de obter um caso de teste com falha, você pode estar razoavelmente certo de que acertou a verdadeira razão do comportamento que está incomodando.
Aprenda a usar um depurador.
print
as instruções podem funcionar razoavelmente bem em algum nível, mas um depurador na maioria das vezes é muito útil (e depois que você sabe como usá-las, fica muito mais confortável do que asprint
instruções).Fale sobre alguém sobre o seu problema, mesmo que seja apenas um patinho de borracha . Forçar-se a expressar o problema no qual está trabalhando com palavras realmente faz milagres.
Dê a si mesmo um limite de tempo. Se, por exemplo, depois de 45 minutos você achar que não está indo a lugar algum, basta mudar para outras tarefas por algum tempo. Quando você voltar ao seu bug, esperamos poder ver outras soluções possíveis que você nunca teria considerado antes.
fonte
Eu acho que a reprodução de um bug também é importante. Todos os casos que reproduzem o bug podem ser listados e, em seguida, você pode garantir que a correção do bug cubra todos esses casos.
fonte
Há um excelente livro que li sobre esse assunto chamado Por que os programas falham , que descreve várias estratégias para encontrar bugs, desde a aplicação do método científico para isolar e resolver um bug até a depuração delta. A outra parte interessante deste livro é que ele acaba com o termo 'bug'. A abordagem de Zeller é:
(1) Um programador cria um defeito no código. (2) O defeito causa uma infecção (3) A infecção se propaga (4) A infecção causa uma falha.
Se você deseja aprimorar suas habilidades de depuração, recomendo este livro.
Em minha própria experiência pessoal, encontrei muitos bugs em nosso aplicativo, mas o gerenciamento simplesmente nos pressiona para obter novos recursos. Eu sempre ouvi "Nós encontramos esse bug e o cliente ainda não o percebeu, então deixe-o até que o façam". Eu acho que ser reativo em vez de proativo na correção de bugs é uma péssima idéia, pois quando chega a hora de corrigir, você tem outros problemas que precisam ser resolvidos e mais recursos de gerenciamento querem sair o mais rápido possível, para que você seja pego em um ciclo vicioso que pode levar a uma grande quantidade de estresse e esgotamento e, finalmente, a um sistema dominado por defeitos.
A comunicação também é outro fator quando erros são encontrados. Enviar e-mail ou documentá-lo no rastreador de bugs é ótimo, mas na minha própria experiência, outros desenvolvedores encontram um bug semelhante e, em vez de reutilizar a solução que você colocou para corrigir o código (como eles se esqueceram disso) ), eles adicionam suas próprias versões, então você tem 5 soluções diferentes em seu código e, como resultado, parece mais inchado e confuso. Portanto, quando você corrigir um bug, certifique-se de que algumas pessoas revisem a correção e forneçam feedback caso tenham corrigido algo semelhante e encontrem uma boa estratégia para lidar com ela.
limist mencionou o livro The Pragmatic Programmer, que tem algum material interessante sobre a correção de bugs. Usando o exemplo que eu dei no parágrafo anterior, eu veria o seguinte: Software Entrophy , onde a analogia de uma viúva quebrada é usada. Se duas janelas quebradas aparecerem, sua equipe poderá ficar apática por consertá-la, a menos que você tome uma atitude proativa.
fonte
Bug, erro, problema, defeito - como você quiser chamá-lo, não faz muita diferença. Vou me ater ao problema, pois é com isso que estou acostumado.
Se você estiver familiarizado com o código ou se o problema ou a correção for óbvio, poderá pular algumas dessas etapas.
Eu discordo disso, pois implica que escrever um novo código é valioso para se mover do que ter um programa de trabalho de alta qualidade. Não há nada errado em ser o mais eficaz possível na correção de problemas, mas um programa não melhora necessariamente adicionando mais código a ele.
fonte
Gosto da maioria das outras respostas, mas aqui estão algumas dicas sobre o que fazer antes de fazer qualquer uma dessas perguntas. Irá poupar tempo beaucoup.
Determine se realmente existe um erro. Um bug é SEMPRE uma diferença entre o comportamento e os requisitos do sistema; o testador deve ser capaz de articular o comportamento esperado e real. Se ele não puder fornecer suporte para o comportamento esperado, não há requisitos e não há erros - apenas a opinião de alguém. Mande de volta.
Considere a possibilidade de que o comportamento esperado esteja errado. Isso pode ser devido a uma interpretação incorreta do requisito. Também pode ser devido a um defeito no próprio requisito (um delta entre um requisito detalhado e um requisito de negócios). Você pode enviá-los de volta também.
Isole o problema. Somente a experiência lhe ensinará a maneira mais rápida de fazer isso - algumas pessoas quase conseguem fazê-lo com o estômago. Uma abordagem básica é variar uma coisa, mantendo todas as outras constantes (o problema ocorre em outros ambientes? Com outros navegadores? Em uma região de teste diferente? Em diferentes momentos do dia?). Outra abordagem é observar os despejos de pilha ou mensagens de erro - às vezes você pode dizer apenas pela forma como está formatado qual componente do sistema gerou o erro original (por exemplo, se estiver em alemão, você pode culpar a terceira pessoa com quem trabalha em Berlim).
Se você reduziu para dois sistemas que colaboram, inspecione as mensagens entre os dois sistemas via monitor de tráfego ou arquivos de log e determine qual sistema está se comportando conforme a especificação e qual não é. Se houver mais de dois sistemas no cenário, você poderá executar verificações aos pares e trabalhar "down" na pilha de aplicativos.
A razão pela qual o isolamento do problema é tão crítico é que o problema pode não ser devido a um defeito no código que você controla (por exemplo, sistemas de terceiros ou o ambiente) e você deseja que essa parte assuma o mais rápido possível . Isso serve para poupar o trabalho e colocá-los no ponto imediatamente, para que a resolução possa ser alcançada no menor espaço de tempo possível. Você não deseja trabalhar em um problema por dez dias apenas para descobrir que é realmente um problema com o serviço da web de outra pessoa.
Se você determinou que realmente há um defeito e está realmente no código que você controla, você pode isolar ainda mais o problema procurando o último build "conhecido" bom e inspecionando os logs de controle de origem para alterações que possam ter causado o problema. Isso pode economizar muito tempo.
Se você não conseguir descobrir isso a partir do controle de origem, agora é a hora de anexar seu depurador e percorrer o código para descobrir. As chances são de que você já tenha uma boa idéia do problema.
Depois de saber onde está o erro e pensar em uma correção, eis um bom procedimento para corrigi-lo:
Escreva um teste de unidade que reproduza o problema e falhe.
Sem modificar o teste de unidade, faça-o passar (modificando o código do aplicativo).
Mantenha o teste de unidade em sua suíte de testes para impedir / detectar regressão.
fonte
Aqui está como eu faço:
fonte
Supondo que você esteja em um ambiente de produção, eis o que você precisa fazer:
Descreva o "erro" corretamente e identifique os eventos que causam a ocorrência.
Determine se o "erro" é um erro de código ou erro de especificação. Por exemplo, inserir um nome de 1 letra pode ser considerado um erro para alguns sistemas, mas um comportamento aceitável para outros sistemas. Às vezes, um usuário relata um erro que acha que é um problema, mas a expectativa do usuário pelo comportamento do sistema não fazia parte dos requisitos.
Se você provou que há um erro e o erro é devido ao código, é possível determinar quais partes do código precisam ser corrigidas para evitar o erro. Examine também o efeito do comportamento nos dados atuais e nas operações futuras do sistema (análise de impacto no código e nos dados).
Nesse ponto, você provavelmente teria uma estimativa de quanto recursos serão consumidos para corrigir o erro. Você pode corrigi-lo imediatamente ou agendar uma correção em uma próxima versão do software. Isso depende também se o usuário final está disposto a pagar pela correção. Você também deve avaliar as diferentes opções disponíveis para corrigir o erro. Pode haver mais de uma maneira. Você precisa selecionar a abordagem que melhor se adequa à situação.
Analise os motivos que fizeram com que esse bug aparecesse (requisitos, codificação, teste etc.). Impor processos que impediriam a condição de ocorrer novamente.
Documente o episódio adequadamente.
Solte a correção (ou a nova versão)
fonte