Como gastar menos tempo na depuração? [fechadas]

15

Seguindo a regra de Pareto, um programador gasta apenas 20% de seu tempo em coisas realmente úteis.

Passo 80% do meu tempo depurando, consertando pequenas coisas para fazer tudo funcionar.

Existe uma maneira de gastar menos tempo depurando?

uhbif19
fonte
9
Não tenho certeza de que seria assim que interpretaria o princípio de Pareto.
#maker
6
<meme> Dê uma olhada no TDD. </meme>
StuperUser
1
O que você realmente faz ao depurar?
3
você precisa gastar mais tempo com sua atenção aos detalhes
1
Há muito a ser ganho simplesmente olhando seu código de vez em quando. Melhor ainda, escreva comentários conforme desejar, para que seja mais fácil perceber erros mais tarde.
Joey Adams #

Respostas:

5

Código em Agda ou Coq . Depois que seu código for compilado, ele funcionará. Se for muito grave, escolha um idioma com um sistema do tipo mais fraco, por exemplo, Haskell ou F #.

No entanto, na maioria dos casos, você será muito mais produtivo gastando 20% do seu tempo em codificação e 80% em testes e depuração. 100% de uma semana é muito mais que 20% de uma hora. Se a depuração é o que você precisa para realizar as tarefas, a depuração não é uma perda de tempo e você não deve se preocupar em "melhorar" essa proporção.

SK-logic
fonte
1
Apenas porque algo é executado não significa que não há bugs. Bugs geralmente são o resultado do código fazer a coisa errada.
HLGEM #
3
@HLGEM, antes de votar abaixo, você deveria ter lido mais sobre Agda e Coq. Se o seu código compilar, é garantido e comprovado fazer exatamente o que a especificação diz. É claro que também pode haver um erro na especificação, mas eu não chamaria a correção desse tipo de problema de "depuração".
SK-logic,
2
@HLGEM, então sua noção de "depuração" é bastante criativa e está longe do convencional. E de qualquer maneira, com essa abordagem, uma proporção entre codificação e "depuração" estaria longe de 20/80. Então, por favor, lembre-se de explicar seu voto negativo.
SK-logic,
1
@HLGEM, não estava em uma lista de requisitos de OP. Nada se sabe sobre quantos desenvolvedores existem, quem está no comando, etc. A única questão era "como medir a proporção 20/80", e usar uma linguagem estaticamente verificada é claramente a resposta mais óbvia para ela. Mas, como eu já disse, essa resposta é aplicável apenas em casos muito raros e, em geral, aderir à regra 20/80 é uma opção muito melhor.
SK-logic,
1
@ uhbif19 Knuth queria ser engraçado quando dizia isso. Você sabe o que ele realmente quis dizer?
Phil
44

Teste de unidade.

Depois que comecei a aplicar o teste de unidade, descobri que o código que escrevi ficou mais estruturado. Era então mais fácil evitar e detectar bugs. Passei menos tempo depurando, mas mais tempo escrevendo testes de unidade.

Eu também acho que o tempo investido em testes de unidade tem um retorno de investimento melhor do que a depuração. Após uma sessão de depuração, apenas consertei o código. O mesmo bug pode aparecer semanas depois e eu tenho que depurar novamente. Se eu escrever um teste de unidade, o bug será documentado como um teste de unidade e, posteriormente, atuará como um teste de regressão. Se o bug aparecer novamente, os testes de unidade revelam isso para mim.

Theo Lenndorff
fonte
Eu uso testes de unidade e concordo plenamente com você. Mas não posso testar tudo.
Uhbif19
5
Certamente você pode. Bem, não tudo , mas tudo o que importa. Usando interfaces, injeção de dependência, classes / métodos de falsificação e zombaria, você poderá escrever testes para praticamente todo o seu código.
Fredrik
8
@ Fredrik, você não pode testar adequadamente a unidade, nem mesmo o a + btrecho de código (a menos que seu teste cubra toda a faixa do seu tipo de dados aritméticos).
SK-logic,
"Após uma sessão de depuração, apenas consertei o código." -- Sério? Acho que após uma sessão de depuração, acabei de apresentar mais bugs - simplesmente não sei onde eles estão.
B Seven
35
  • Teste de unidade, para que você saiba se o seu código funciona em primeiro lugar.
  • Pelo menos uma quantidade de design inicial, para que você saiba o que está codificando.
  • Revisões de código, porque duas cabeças são melhores que uma e quatro olhos são melhores que duas. Sem mencionar que mesmo tentar explicar seu código a outra pessoa revela muitos problemas.
  • Controle de versão, para que você possa isolar rapidamente quais alterações podem ter causado o bug.
  • Refatoração, para que você codifique não se transforme em uma bagunça incompreensível horrível.
  • Leia "Código Limpo", de Robert C. Martin, e faça o que ele disser. Você ficará surpreso com os resultados.
Dima
fonte
5
Exatamente - nenhuma prática única (por exemplo, teste de unidade) dará uma ordem de magnitude, mas uma combinação de práticas pode. Em outras palavras ... não há bala de prata.
Michael
Eu adicionaria TDD (sempre que possível).
Tom
1
Na verdade, eu classificaria o código limpo e a refatoração primeiro. Os testes de unidade são bons para encontrar e corrigir bugs mais cedo, mas eles não reduzirão o número deles (eles reduzirão um pouco o tempo, porque você estará corrigindo bugs quando tiver tudo novo na memória, mas ainda assim). Escrever código limpo, por outro lado, reduz o número real de bugs.
Jan Hudec
1
@JanHudec Refatoração + código limpo + testes = TDD
Tom
1
@ Tom: Sim, mas as diferentes partes têm efeitos diferentes. Aprender a escrever código limpo ajudará você a reduzir o tempo de depuração sem nenhum teste. Existem testes para que você possa testar os módulos antes da implementação deles e para verificar se não modificou o comportamento ao refatorar - o que é necessário para limpar o código antigo e desarrumado.
Jan Hudec
8

O teste de unidade ajudará, esperançosamente, se você introduzir bugs, eles serão quebrados antes do código de produção - testes de unidade bem escritos também informarão exatamente o que ocorreu.

Isso fará com que você fique na maior parte do caminho, mas para 99,999% dos projetos, você ainda precisará depurar as coisas com o tempo. A melhor coisa a fazer aqui é encontrar 4 coisas:

  1. use tipos imutáveis ​​sempre que possível - se algo tiver um valor errado, você saberá exatamente onde procurar imediatamente (onde está sendo construído).
  2. aplicar invariantes no código - se você souber que um valor definitivamente não é permitido, verifique-o e lance uma exceção nos pontos de entrada para métodos e construtores. Se você combinar isso com tipos imutáveis, também poderá começar a fazer certas suposições sobre o que é válido ou não.
  3. verifique se você possui um registro adequado - obtenha isso no início e fornecerá muitas informações importantes sobre quando as coisas dão errado. AOP funciona muito bem aqui. Registrar como uma reflexão tardia geralmente é um pouco inútil - obtenha-o no início como parte da configuração do projeto.
  4. se sua base de código for grande / complexa o suficiente, evite usar primitivas - por exemplo, tenha um tipo chamado 'Age' em vez de apenas usar um int. Parece um pouco inútil no começo, mas ser capaz de rastrear todos os usos de algo em um instante é uma grande vitória na depuração.
FinnNk
fonte
6

Meus 80% são depuração. Estou corrigindo bugs simples e tentando fazer com que tudo funcione.

Comece escrevendo testes de unidade e tente ter a cobertura mais alta possível. Alguém mencionou TDD, mas eu iria com o BDD .

No final, você provavelmente gastará 80% na depuração de bugs complexos.

BЈовић
fonte
6

Como gastar menos tempo depurando? Escreva menos código.

Sério, contanto que você escreva o código, será necessário depurá-lo. Testes de unidade etc ajudam imensamente, mas não pense que você removerá completamente a necessidade.

Daniel Roseman
fonte
4

Entenda o que e o porquê antes de começar a escrever o código. Em seguida, use uma metodologia consistentemente. Qual metodologia você escolhe não é tão importante quanto o uso repetido e consistente da metodologia. Se você deseja resultados consistentemente bons, precisa fazer um trabalho consistentemente bom e ter um "método para sua loucura" é o primeiro passo para obter esses resultados. Ao identificar problemas, você pode ajustar sua metodologia conforme necessário e, com o tempo, aprimorará seu processo de desenvolvimento e, com sorte, menos bugs e mais desenvolvimento novo e significativo.

cdkMoose
fonte
3

Dê uma leitura cuidadosa ao seu código antes mesmo de compilá-lo. Uma leitura muito cuidadosa para sintaxe e funcionalidade. Pode ser surpreendentemente informativo e também é um bom indicador se uma seção do código for muito complicada.

anon
fonte
Eu concordo totalmente. A leitura do seu código imediatamente após a sua gravação pode revelar rapidamente alguns erros evidentes, como erros de copiar e colar (que podem ser difíceis de encontrar posteriormente).
precisa saber é o seguinte
3

A maioria das respostas parece focada em como reduzir o número de problemas que você precisa depurar e isso é valioso. No entanto, a depuração sempre será necessária, portanto, é útil procurar maneiras de acelerar a depuração.

  • Saiba como usar seu software de controle de versão.

    • O uso de branches o ajudará a separar áreas de desenvolvimento e você poderá ver qual área de desenvolvimento tem o bug e quais não.
    • Aprenda a usar a bissecção no seu VCS, o Git tem isso embutido. Se você usar um VCS diferente que não tenha a bissecção integrada, procure uma ferramenta que funcione como o git bisect, mas para o seu VCS (eu sei que isso existe para SVN e não deve ser muito difícil criar para outros VCSs). Isso o ajudará a restringir a alteração de código que introduziu o bug, o que ajudará a saber para onde apontar seu depurador. Esse processo de bissecção será mais rápido se você tiver testes para o bug e saber qual confirmação contém a alteração ofensiva será mais útil se você praticar confirmações atômicas.
  • Melhore a sua compreensão da linguagem de programação que você usa.

    • Leia livros, blogs e códigos sobre a linguagem de programação.
    • Toda vez que você corrige um bug, entenda completamente por que o código não funcionou e por que sua correção funciona. Com o tempo, você aprenderá muitas dicas no seu idioma, o que o ajudará a evitar os problemas deles e a detectar os sintomas deles caso ocorram novamente.
  • Seja lógico

    • Não mude mais de uma coisa de uma vez, caso contrário, se o comportamento mudar, você não saberá qual delas causou a mudança de comportamento.
    • Verifique suas suposições.
Stephen Paulger
fonte
2

Adicionando aos comentários do Teste de Unidade, mas só é realmente bom se o seu código tiver sido separado para suportá-lo (por exemplo, MVC). Se você não conseguir implementar o MVC (ou semelhante) (projeto herdado), os testes de unidade não funcionarão na sua interface do usuário. Em seguida, adicionaria o teste automatizado da interface do usuário (Microsoft Coded UI Tests, WaitN), pois isso reduzirá os erros nessa parte do seu código.

Eu também recomendo executar ferramentas de análise estática (por exemplo, FxCop / Microsoft Code Analysis, Resharper, JustCode para o mundo da MS). Eles podem encontrar todos os tipos de problemas de codificação comuns, o que pode reduzir as tarefas de depuração tolas e se concentrar mais na depuração da lógica de negócios.

Scott Wylie
fonte
2

Faça com que funcione, depois faça rápido, depois faça bonito. A maioria dos erros vem de otimizações precoces ou re-fatoração em linhas de código totalmente boas. Se você seguir a orientação a objetos, não se repita, mantenha-o simples e sempre faça verificações de sanidade dos valores, especialmente se seus métodos ainda funcionarem com restrições. Não o ajudará a cometer menos erros, mas provavelmente o ajudará a detectar erros mais rapidamente e, portanto, a depuração leva menos tempo.

kibotu
fonte
1
Sua afirmação "A maioria dos erros vem de ..." parece boa, mas você tem evidências para comprovar isso? Eu acho que soaria igualmente convincente se eu dissesse "a maioria dos erros vem de requisitos mal especificados ou falta de um design claro". Você deve adicionar um link ou citação à pesquisa que apóia sua declaração.
Caleb
2

Recentemente, pensei bastante nesse problema - a resposta simples é: leia O design das coisas cotidianas, de Don Norman; Escreva um código como você projetaria um produto.

Parafraseando, um bom design minimiza os erros. Isso significa algumas coisas, a maioria das quais você já faz (embora você talvez não saiba exatamente por que ).

-Nome funciona intuitivamente. Isso é formalmente conhecido como acessibilidade. Ou seja, um botão pode ser pressionado, uma alavanca pode ser trocada, uma alça a ser puxada, etc.

-Dificuldade em escrever código incorreto. Verifique se há entrada incorreta e gere erros mais cedo ou mais tarde, use aplicativos húngaros quando apropriado etc. Isso é chamado de funções de bloqueio.

-Use abstração quando apropriado. Memória de curto prazo é fraca.

A documentação é obviamente importante, mas é a menos eficaz para garantir que o código seja usado corretamente. Em suma, produtos bem projetados não precisam de documentação. (A maneira mais óbvia de ver isso é observar exemplos ruins: portas com maçanetas que você deve empurrar.)

Testes -Unit. Isso realmente não evita erros, mas torna óbvio onde estão os bugs e fornece sanidade.

Tenho certeza de que estou perdendo muitos princípios, mas o ponto é: leia o projeto para erros.

Ceasar Bautista
fonte
1

A melhor maneira de diminuir a depuração, IMO, é concentrando-se e diminuindo a velocidade ao codificar. Isso força você a ver os erros que você pode ter cometido!

Dinâmico
fonte
1

Embora eu apoie totalmente o teste de unidade sugerido acima, o TDD ou BDD será de grande valor, pois você precisará pensar primeiro no problema e na solução.

Mas, pessoalmente, para mim, dedicar alguns minutos apenas para me sentar em silêncio e pensar sobre o problema e como abordá-lo e quaisquer prós e contras de cada abordagem, faz maravilhas pela minha qualidade de código e ajuda a limpar minha mente de desordem.

Às vezes, um rabisco rápido em um pedaço de papel ajuda a ver as peças maiores do quebra-cabeça conectadas.

Eu escrevo o pior código quando mergulho na cabeça primeiro e bato no teclado. Um pouco de pensamento e contemplação faz um mundo de diferença.

PS. Quero dizer 5 talvez dez minutos, não horas escrevendo uma especificação enorme.

SetiSeeker
fonte
1

Algumas boas respostas já, apenas mais um pouco de comida, além do que os outros disseram.

Aprenda com seus erros. Não continue fazendo os mesmos repetidas vezes.

Certifique-se de cobrir os casos extremos ao programar - esses são locais onde há erros com freqüência.

Preste atenção ao requisito. Mesmo que funcione, mas não faça o que o requisito especificado, isso é um bug.

Os logs de exceção podem ser uma ajuda real quando algo der errado daqui a seis meses. Tenha o hábito de registrar exceções.

HLGEM
fonte
0

Meus dois pensamentos principais são: 1) Escreva um código melhor que falhará quando você fizer algo inesperado. 2) Torne-se melhor na depuração

Meu código está cheio de

if(value!=null) throw new NotImplementedException();
if(obj.v>0) throw new Exception(); //sometimes i dont write NotImplementedException
if(value=="thing") throw ...;

Sempre que executo esse trecho de código, a exceção é lançada, o que faz com que o depurador pare, o que me permite codificar os novos recursos ou evitar as condições, em vez de ficar confuso sobre o que está acontecendo / ter um bug

Para melhorar a depuração da bagunça com a pilha de chamadas, os pontos de interrupção (com condições), a janela imediata (também conhecida como janela de prompt ou repl), as variáveis ​​'watch' e qualquer outra coisa.

user2528
fonte