Eu nem tenho certeza de como definir essa dificuldade. Isso me lembra o teste que alguns funcionários em potencial fizeram comigo antes de eu conseguir um emprego. Eles escolhem um objeto na sala e então eu tenho permissão para fazer perguntas para me ajudar a determinar o que é esse objeto (bem como 20 perguntas). Eu era ridiculamente bom nisso (não, nunca consegui pontos altos por humildade), então assumi que seria realmente bom na solução de bugs ...
Mas aqui está a coisa que descobri recentemente. Sou muito bom nessa situação, porque é muito fácil ver tudo o que há na sala, para que eu possa abordar meu problema com algum conceito de suas partes componentes. Em essência, "sei o que não sei". Mas com a programação, encontro muitas situações em que o problema é totalmente desconhecido para mim. Sei que está quebrado, mas não tenho noção de como pode estar quebrado. Eu segui todas as instruções, conheço a tecnologia bastante bem ...
Se eu for honesto, sinto que estou tendo dificuldade em imaginar coisas que podem estar erradas, para que eu possa testá-las e, espero, encontrar uma solução.
Como desenvolvo essa habilidade? O que preciso fazer para ajudar minha imaginação, aparentemente limitada, a encontrar maneiras de quebrar meu projeto? Existem exercícios (talvez quebra-cabeças?) Que podem me fazer melhorar nisso? Estou ciente de que provavelmente a maior cura é apenas a experiência ... mas espero ajudar a acelerar o processo, se puder. Olhar fixamente para a tela do computador por algumas horas não é nem divertido ...
printf
ou oprintln
que você usa em todas as linhas de código para ter 100% de certeza de que tudo funciona como você deseja que funcione haha. Em seguida, execute o aplicativo do console e, emApp > out.txt
seguida, vem a parte mais difícil de visualizar o arquivo enorme. Às vezes, meus arquivos de log têm mais de alguns milhões de linhas e pode levar algum tempo, haha. Obviamente, o caminho certo seria usar um depurador e pontos de interrupção, mas às vezes não é possível fazer isso.Respostas:
Todo defeito no software é devido, em última instância, a uma discrepância entre suposições e realidade. Erros insidiosos são simplesmente discrepâncias entre suposições profundamente arraigadas e a realidade. A capacidade de diagnosticar bugs depende da sua capacidade de questionar suas próprias suposições, e isso realmente exige uma conscientização de que você não sabe certas coisas, apenas as assumiu e costumava estar certa até agora.
Obviamente, as ferramentas do comércio, arquivos de log, depuradores etc. são úteis para descobrir essas suposições e realinhar seu modelo mundial com o sistema real. Mas até que você esteja pronto para questionar a suposição crucial, por exemplo, "Não pode ser uma entrada ruim porque temos uma verificação abrangente de entradas", você passará o tempo todo verificando as partes erradas do sistema ou simplesmente não saber para onde procurar. em primeiro lugar.
fonte
Na maioria dos casos, eu diria absolutamente nada. Você não deve tentar inventar coisas que possam estar causando a falha do programa. Você deve determinar sistematicamente o que está causando a quebra.
Você deve entrar no processo de depuração com as seguintes informações:
Se houver uma mensagem de erro, obtenha todas as informações possíveis. Se a mensagem de erro em si não estiver clara e você não souber o que significa na prática (algumas mensagens de erro nem sempre são particularmente úteis), use o Google, StackOverflow ou qualquer outro recurso on-line para encontrar informações sobre ela. .
Se não houver uma mensagem de erro exibida no front-end, verifique os logs nos quais o aplicativo grava para obter mensagens de erro durante o período em que você reproduziu o erro. O código pode ter sido executado até a conclusão, mas encontrou uma exceção que está sendo manipulada ao longo do caminho, que está descartando o resultado final e produzindo uma entrada nos logs. Procure por eles, faça o mesmo acima e identifique exatamente o que eles significam.
Se houver rastreamentos de pilha fornecidos com exceções lançadas pelo seu código (e deve haver), observe as linhas de código mencionadas. A linha em si pode não ser a que está realmente produzindo o problema. Se você receber uma NullPointerException em um pedaço de código Java, o stacktrace lhe dirá onde você tentou usar algo que era nulo quando você esperava que não estivesse. Isso não indica exatamente a linha que está causando o problema, mas geralmente informa qual variável não possui o valor esperado, para que você possa consultar as referências / atribuições a essa variável para determinar se o valor não está sendo definido ou que o valor está sendo definido incorretamente.
Se nada disso ajudou, inicie o depurador. Se você o reduziu a uma seção do código que você sabe que está causando o problema - mas você não sabe exatamente quais linhas -, passe por isso. Caso contrário, basta percorrer a coisa toda. É aqui que você precisa saber exatamente o que o programa deve fazer com as entradas fornecidas, porque você precisa examinar cada valor após cada linha e determinar exatamente onde ele está se desviando do que você espera que ele faça.
Ainda não tem idéia de qual é o problema? Peça ajuda a alguém . Um colega de trabalho, um amigo, uma comunidade online. Mostre a eles todo o trabalho que você acabou de fazer. Mostre a eles as mensagens de erro, os rastreamentos de pilha, expliquem o que o programa faz em termos gerais (se eles ainda não sabem), o que deve estar fazendo nesse caso específico (por exemplo, retornando o valor 4), o que está realmente fazendo (por exemplo, retornando o valor 5). Se você o reduziu a algumas linhas de código no depurador, diga "Eu sei que o problema é causado por essas linhas no código, ele está definindo o valor para X quando deveria ser Y, mas não consigo ver por que isso está acontecendo ".
Passar algumas horas olhando fixamente para a tela definitivamente não é divertido, mas não há motivo para você fazer isso. Se houver um problema com seu código, você precisará ler ou percorrer o código.
fonte
Até certo ponto, é como investigar um caso criminal ou um quebra-cabeça incompreensível.
Primeiro, você pegou a vítima. Depois de investigar um pouco o caso, você identificou alguns suspeitos e também desenvolveu uma hipótese de trabalho de como exatamente a vítima poderia ser assassinada. Você continua investigando, procurando informações mais úteis, aproximando-o cada vez mais da fonte real do problema.
Ocorre que, de tempos em tempos, você entra em um beco sem saída (trocadilho intencional). Isso faz parte, e não há nada de errado nisso, desde que você consiga voltar à pista o mais rápido possível. A chave é, sempre pensar em quais informações você precisa a seguir, que fornece sua hipótese (e fornece mais informações) ou prova que estão erradas. Em seguida, encontre uma maneira de obter essas informações de maneira eficiente, tire suas conclusões e siga em frente, até que você finalmente consiga condenar os culpados.
E às vezes você percebe que todos os fatos e indicações necessárias para identificar o culpado já estavam esperando na sua frente meia hora atrás. Embora irritante, essa é uma das partes mais interessantes, porque se você fizer uma revisão crítica de suas ações e erros, poderá aprender e melhorar . Faça a si mesmo perguntas como:
Isso treinará suas habilidades. Ele também desenvolverá seu instinto , de modo que, com o tempo, você aprenderá a perceber automaticamente todas as coisas minoritárias que são facilmente ignoradas, levando você mais rapidamente à resposta certa. No final, trata-se de prática deliberada .
Por último, lembre-se sempre do que Sherlock Holmes nos ensinou: Quando você elimina o impossível, tudo o que resta, por mais improvável que seja, deve ser a verdade.
fonte
Deixe a história ser seu guia. Se seu projeto for bem gerenciado, você deverá ter um banco de dados de todos os erros que já foram corrigidos no produto, juntamente com uma análise de como o erro foi encontrado, como foi reproduzido, como foi analisado e como foi corrigido. Esse não é um banco de dados somente gravação. Leia o banco de dados e muito em breve taxonomias de bugs começarão a ocorrer para você.
Isso lhe dará uma boa visão geral dos tipos de coisas que dão errado no seu produto. Se você está interessado de maneira mais geral no que dá errado em todos os tipos de software, particularmente com ênfase em defeitos que afetam a segurança, sugiro que você leia a lista do CWE: http://cwe.mitre.org/data/index.html
fonte
Portanto, em vez de tentar reproduzir e corrigir um defeito específico, acredito que você esteja perguntando sobre novos testes que você poderia usar para investigar o produto e verificar se o produto funciona nessas circunstâncias, por exemplo: o que acontece se eu inserir caracteres especiais em nosso a senha da página de inscrição foi arquivada ou o que acontece se eu fechar o programa com força enquanto ele estiver gravando no banco de dados. Esses casos são realmente difíceis de pensar.
O desenvolvimento de software nos últimos 10 anos (Agile / XP / TDD etc.) chegou ao valor de atender somente aos requisitos explícitos e depois declarar o recurso concluído, e não encontrar todas as formas possíveis de quebrar algo (existem possíveis exceções, se você estiver trabalhando para a NASA ou fazendo segurança com chapéu branco, mas mesmo assim é possível argumentar sobre essas coisas nos critérios de aceitação da história do usuário).
Portanto, se seus recursos listarem explicitamente como critérios de aceitação o que os sistemas precisam fazer, como lidar com entradas, suas características de desempenho, ações do fluxo de trabalho do usuário etc., você terá uma lista completa do que os testes precisam verificar. Os testes devem ser feitos para validar se os requisitos foram atendidos, e a melhor maneira de fazer isso é listar explicitamente todos os seus requisitos. Dê uma olhada nos quadrantes de teste ágil .
Algumas pessoas defendem que esses testes sejam a declaração explícita dos requisitos, que precisam ser escritos antes do código, ou seja, Teste Primeiro (ou Desenvolvimento Orientado a Testes).
No entanto, aprecio que você não pareça estar pensando em um novo projeto, no qual pode definir suas próprias práticas recomendadas de desenvolvimento antes de começar e, em vez disso, voltará depois que o software foi escrito e está sendo solicitado a testá-lo. Isso é realmente mais desafiador, mas os mesmos princípios se aplicam, você só pode testá-lo quando souber o que deveria fazer. Se não houver uma lista abrangente de requisitos que foram atendidos pela equipe de desenvolvimento para você trabalhar a partir de então, fazer perguntas é o melhor caminho a seguir. Dependendo da sua equipe, isso pode precisar ser feito delicadamente, pois as pessoas que não listaram explicitamente seus requisitos antes da criação de um sistema de software não gostam de ser lembradas do que perderam, mas é essencial para executar bem esta tarefa.
Depois de encontrar um requisito - ele deve ser robusto / deve ser seguro, tente se aprofundar e descobrir como deve ser seguro ou quanta falha é aceitável - sempre há um limite; muitas pessoas não têm uma prova da NSA nível de segurança como requisito para a sua aplicação ou queiram pagar por isso. Quanto mais você explora, mais claro deve ser quanto a quais tipos de ataques de segurança você precisa se defender ou que é fácil usá-lo. Algum conhecimento de domínio é útil, em segurança, design, desempenho etc., onde você faz ainda mais perguntas aos especialistas que pode encontrar em sua equipe, ou aqui no SE, ou no google / books.
fonte