Quando a correção de bugs se torna excessiva, se alguma vez?

128

Imagine que você está criando um player de vídeo em JavaScript. Esse player de vídeo repete o vídeo do usuário repetidamente usando uma função recursiva e, por causa disso, o navegador acionará um too much recursion RangeError em algum momento.

Provavelmente ninguém usará muito o recurso de loop. Seu aplicativo nunca lançará esse erro, mesmo que o usuário tenha deixado o loop do aplicativo por uma semana, mas ele ainda existe. Resolver o problema exigirá que você redesenhe a maneira como o looping funciona em seu aplicativo, o que levará um tempo considerável. O que você faz? Por quê?

  • Corrigir o erro

  • Deixe o bug

Você não deveria apenas consertar bugs que as pessoas tropeçarão? Quando a correção de bugs se torna um exagero, se isso acontecer?

EDITAR:

Se a abordagem recursiva não causar um bug real é uma preocupação para você, suponha que, para cada vez que o jogador repetir um vídeo, a variável seja aumentada em 1 . Após 2 53 loops, esta variável irá estourar e o seu programa não será capaz de lidar com isso, lançando uma exceção.

    
por Tiago Marinho 17.10.2016 / 07:16
fonte

16 respostas

164

Você tem que ser pragmático.

Se é improvável que o erro seja acionado no mundo real e o custo de correção seja alto, duvido que muitas pessoas considerem isso um bom uso de recursos para corrigir. Com base nisso, eu diria deixar, mas garantir que o hack seja documentado para você ou seu sucessor em alguns meses (veja o último parágrafo).

Dito isso, você deve usar esse problema como uma "experiência de aprendizado" e, na próxima vez que fizer o loop, não usará um loop recursivo desnecessariamente.

Além disso, esteja preparado para esse relatório de bug. Você ficaria espantado com o quanto os usuários finais são bons em atacar as fronteiras e descobrir defeitos. Se isso se tornar um problema para os usuários finais, você terá que corrigi-lo - então você ficará feliz em documentar o hack.

    
por 17.10.2016 / 07:36
fonte
80

Ocorreu um erro semelhante no Windows 95 que causou a queda de computadores após 49,7 dias . Só foi notado alguns anos após o lançamento, uma vez que muito poucos sistemas Win95 ficaram assim por muito tempo. Portanto, há um ponto: os erros podem se tornar irrelevantes por outros bugs mais importantes.

O que você precisa fazer é uma avaliação de risco para o programa como um todo e uma avaliação de impacto para bugs individuais.

E assim por diante. Isso afeta o bug triagem , o processo de decidir quais bugs serão corrigidos. Praticamente todos os softwares de remessa têm listas muito longas de pequenos bugs que ainda não foram considerados importantes o suficiente para corrigir.

    
por 17.10.2016 / 17:40
fonte
33

As outras respostas já são muito boas e sei que seu exemplo é apenas um exemplo, mas quero destacar uma grande parte desse processo que ainda não foi discutido:

Você precisa identificar suas suposições e, em seguida, testar essas suposições em relação a casos específicos.

Olhando para o seu exemplo, vejo algumas suposições:

  • A abordagem recursiva acabará causando um erro.
  • Ninguém verá esse erro porque os vídeos demoram muito para serem reproduzidos para atingir o limite de pilha.

Outras pessoas discutiram a primeira suposição, mas olhe a segunda suposição: e se meu vídeo tiver apenas uma fração de segundo?

E claro, talvez esse não seja um caso de uso muito comum. Mas você está realmente certo de que ninguém fará upload de um vídeo muito curto? Você está assumindo que os vídeos têm duração mínima, e você provavelmente nem percebeu que estava assumindo alguma coisa! Esta suposição poderia causar algum outro erro em outros lugares em sua aplicação?

Os pressupostos não identificados são uma enorme fonte de erros.

Como eu disse, sei que o seu exemplo é apenas um exemplo, mas esse processo de identificar suas suposições (que geralmente é mais difícil do que parece) e depois pensar em exceções a essas suposições é um grande fator para decidir onde gastar seu tempo.

Então, se você se achar pensando "Eu não deveria ter que programar em torno disso, já que isso nunca vai acontecer", então você deve levar algum tempo para realmente examinar essa suposição. Muitas vezes você pensa em casos que podem ser mais comuns do que você imaginava.

Dito isto, há um ponto em que isso se torna um exercício de futilidade. Você provavelmente não se importa se o seu aplicativo JavaScript funciona perfeitamente em uma calculadora TI-89, então gastar qualquer quantidade de tempo com isso é apenas um desperdício.

As outras respostas já cobriram isso, mas chegar a essa linha entre "isso é importante" e "isso é uma perda de tempo" não é uma ciência exata, e depende de muitos fatores que podem ser completamente diferente de uma pessoa ou empresa para outra.

Mas uma grande parte desse processo é primeiro identificar suas suposições e, em seguida, tentar reconhecer exceções a essas suposições.

    
por 17.10.2016 / 17:32
fonte
13

Eu recomendo que você leia o seguinte artigo:

Confiabilidade e suas ameaças: uma taxonomia

Entre outras coisas, descreve vários tipos de falhas que podem ocorrer no seu programa. O que você descreveu é chamado de uma falha latente e, neste trabalho, é descrito assim:

A fault is active when it produces an error, otherwise it is dormant. An active fault is either a) an internal fault that was previously dormant and that has been activated by the computation process or environmental conditions, or b) an external fault. Fault activation is the application of an input (the activation pattern) to a component that causes a dormant fault to become active. Most internal faults cycle between their dormant and active states

Tendo descrito isso, tudo se resume a uma relação custo-benefício. O custo consistiria em três parâmetros:

  • Com que frequência o problema se apresentaria?
  • Quais seriam as consequências?
  • O quanto te incomoda pessoalmente?

Os dois primeiros são cruciais. Se é algum bug que se manifestaria uma vez em uma lua azul e / ou ninguém cuida dele, ou tem uma solução perfeitamente boa e prática, então você pode documentá-lo com segurança como um problema conhecido e passar para algo mais desafiador e mais tarefas importantes. No entanto, se o bug fizer com que alguma transação monetária falhe, ou interromper um longo processo de registro, frustrando o usuário final, você deverá agir de acordo. O terceiro parâmetro é algo contra o qual eu aconselho strongmente. Nas palavras de Vito Corleone:

It's not personal. It's business.

Se você é um profissional, deixe as emoções de lado e aja de maneira ideal. No entanto, se o aplicativo que você está escrevendo é um hobby seu, então você está emocionalmente envolvido, e o terceiro parâmetro é tão válido quanto qualquer outro em termos de decidir se deve corrigir um bug ou não.

    
por 17.10.2016 / 09:10
fonte
12

Esse bug só permanece desconhecido até o dia em que alguém colocar o seu jogador em uma tela do saguão com uma apresentação da empresa 24 horas por dia, 7 dias por semana. Então ainda é um bug.

A resposta para O que você faz? é realmente uma decisão de negócios, não de engenharia:

  • Se o bug impactar apenas 1% de seus usuários e seu player não tiver suporte para um recurso exigido por outros 20%, a escolha é óbvia. Documente o erro e, em seguida, continue.
  • Se o bugfix estiver na sua lista de tarefas, geralmente é melhor corrigi-lo antes de começar a adicionar novos recursos. Você obterá os benefícios do processo de desenvolvimento de software sem defeitos e não perderá muito tempo, pois está na sua lista de qualquer maneira.
por 17.10.2016 / 16:34
fonte
5

Especialmente em grandes empresas (ou grandes projetos), há uma maneira muito pragmática de estabelecer o que fazer.

Se o custo da correção for maior que o retorno que a correção trará, mantenha o bug. Viceversa se a correção irá retornar mais do que seu custo, então conserte o bug.

No seu cenário de amostra, depende de quantos usuários você espera perder versus quanto usuário você ganhará se desenvolver novos recursos em vez de corrigir esse bug caro.

    
por 17.10.2016 / 13:58
fonte
5

tl; dr É por isso que RESOLVED/WONTFIX é uma coisa. Apenas não exagere - a dívida técnica pode se acumular se você não for cuidadoso. Este é um problema fundamental em seu projeto, provavelmente causando outros problemas no futuro? Então conserte. De outra forma? Deixe até que se torne uma prioridade (se isso acontecer).

    
por 17.10.2016 / 18:26
fonte
5

Na verdade, existem três erros na situação que você descreve:

  1. A falta de um processo para avaliar todos os erros registrados (você registrou o erro no seu ticket / backlog / qualquer sistema que você tenha instalado, certo?) para determinar se ele deve ser corrigido ou não. Esta é uma decisão de gerenciamento.

  2. A falta de habilidades em sua equipe que leva ao uso de soluções defeituosas como essa. É urgente que isso seja endereçado para evitar problemas futuros. (Comece aprendendo com seus erros.)

  3. O problema que o vídeo pode deixar de exibir depois de muito tempo.

Dos três erros somente (3) podem não precisar ser corrigidos.

    
por 17.10.2016 / 11:56
fonte
4

Há muitas respostas aqui discutindo a avaliação do custo do bug sendo corrigido em vez de deixá-lo. Todos eles contêm bons conselhos, mas eu gostaria de acrescentar que o custo de um bug é frequentemente subestimado, possivelmente subestimado. A razão é que os insetos existentes atrapalham as águas para um desenvolvimento e manutenção contínuos. Fazer com que seus testadores acompanhem vários erros "não consertará" enquanto navega em seu software tentando encontrar novos bugs, tornando o trabalho mais lento e mais propenso a erros. Alguns "não consertar" bugs que provavelmente não afetarão os usuários finais ainda farão o desenvolvimento contínuo mais lento e o resultado será mais problemático.

    
por 17.10.2016 / 22:14
fonte
2

Uma coisa que aprendi nos meus anos de codificação é que um bug retornará. O usuário final sempre descobrirá e reportará. Se você vai consertar o bug ou não é "meramente" uma questão de prioridade e prazo.

Tivemos erros importantes (na minha opinião, major) que foram decididos contra a correção em um lançamento, apenas para se tornar um stopper para o próximo lançamento, porque o usuário final tropeçou nele repetidas vezes. O mesmo vice-versa - fomos obrigados a consertar um bug em um recurso que ninguém usa, mas era útil para o gerenciamento ver.

    
por 18.10.2016 / 09:39
fonte
1

Um post-it na mesa de um desenvolvedor sênior no meu local de trabalho diz

Does it help anyone?

Eu acho que esse é frequentemente um bom ponto de partida para o processo de pensamento. Há sempre muitas coisas para corrigir e melhorar - mas quanto valor você realmente está adicionando? ... seja em usabilidade, confiabilidade, manutenibilidade, legibilidade, desempenho ... ou qualquer outro aspecto.

    
por 18.10.2016 / 00:46
fonte
1

Existem três coisas aqui:

Princípios

Este é um lado da moeda. Até certo ponto, eu sinto que é bom insistir em corrigir bugs (ou implementações ruins, mesmo que eles "trabalhem"), mesmo que ninguém esteja percebendo isso.

Olhe desta maneira: o problema real não é necessariamente o bug, no seu exemplo, mas o fato de que um programador achou que era uma boa idéia implementar o loop dessa maneira, em primeiro lugar. Era óbvio desde o primeiro momento que essa não era uma boa solução. Agora existem duas possibilidades:

  • O programador simplesmente não percebeu. Bem ... um programador deve desenvolver uma intuição de como seu código é executado. Não é como recursão é um conceito muito difícil. Ao consertar o bug (e suando durante todo o trabalho adicional), ele talvez aprenda algo e lembre-se, apenas para evitar o trabalho adicional no futuro. Se a razão era que ele simplesmente não tinha tempo suficiente, o gerenciamento poderia aprender que os programadores fazem precisam de mais tempo para criar um código de maior qualidade.

  • O programador notou, mas considerou "não um problema". Se isso for deixado em pé, então é desenvolvida uma cultura de laissez-faire que, em última análise, levará a falhas onde realmente dói. Neste caso particular, quem se importa. Mas e se esse programador estiver desenvolvendo um aplicativo bancário na próxima vez e decidir que uma certa constelação nunca acontecerá? Então isso acontece. Maus momentos.

Pragmatismo

Este é o outro lado. De curso você provavelmente, neste caso particular, não corrigirá o erro. Mas cuidado - existe o pragmatismo e depois há o pragmatismo. Um bom pragmatismo é se você encontrar uma solução rápida, mas sólida e bem fundamentada para um problema. Ou seja, você evita projetar coisas demais, mas as coisas que você realmente implementa ainda são bem pensadas. Mau pragmatismo é quando você acaba de hackear algo que funciona "só assim" e vai quebrar na primeira oportunidade.

Falha rápida, fail hard

Em caso de dúvida, falhe rápido e falhe duramente.

Isso significa, entre outros, que seu código percebe a condição de erro, não o ambiente.

Neste exemplo, o mínimo que você pode fazer é fazer com que o erro de tempo de execução difícil ("profundidade da pilha excedida" ou algo parecido) não ocorra, substituindo-o por uma exceção rígida da sua própria. Você poderia, por exemplo, ter um contador global e decidir arbitrariamente que salvaria depois de 1000 vídeos (ou qualquer número que seja alto o suficiente para nunca ocorrer em uso normal, e baixo o suficiente para ainda funcionar na maioria dos navegadores). Em seguida, forneça a exceção (que pode ser uma exceção genérica, por exemplo, uma RuntimeException em Java ou uma sequência simples em JavaScript ou Ruby) uma mensagem significativa. Você não precisa ir ao ponto de criar um novo tipo de exceções ou o que você fizer em sua linguagem de programação específica.

Dessa forma, você tem

  • ... documentou o problema dentro do código.
  • ... tornou um problema determinista. Você sabe que sua exceção acontecerá. Você não está à mercê de mudanças na tecnologia de navegador subjacente (pense não apenas no navegador do PC, mas também em smartphones, tablets ou tecnologia do futuro).
  • ... facilitou a correção quando você eventualmente precisa consertá-lo. A origem do problema é apontada pela sua mensagem, você terá um retorno significativo e tudo isso.
  • ... ainda não perdeu tempo fazendo tratamento de erros "real" (lembre-se, você nunca espera que o erro ocorra).

Minha convenção é prefixar tais mensagens de erro com a palavra "Paranoia:". Este é um sinal claro para mim e para todos os outros que nunca esperam que o erro seja disparado. Eu posso claramente separá-los das exceções "reais". Se eu vejo um assim em uma GUI ou em um arquivo de log, eu sei com certeza que tenho um problema sério - eu nunca esperei que eles ocorressem, afinal de contas. No esse ponto eu entro no modo crunch (com uma boa chance de resolvê-lo rapidamente e com bastante facilidade, pois sei exatamente onde o problema ocorreu, me salvando de muita depuração espúria).

    
por 19.10.2016 / 15:08
fonte
0

Três coisas vêm à mente:

Primeiro , o impacto de um bug identificado precisa ser completamente investigado antes que a decisão de deixar o bug no código possa ser feita de maneira responsável. (No seu exemplo, pensei imediatamente no vazamento de memória que a pilha sempre crescente representa e que pode tornar seu navegador mais lento e lento a cada recursão.) Essa investigação completa geralmente leva mais tempo do que consertar o bug. , então eu prefiro corrigir o bug na maioria dos casos.

Segundo , os bugs tendem a ter mais impacto do que se pensa no início. Estamos todos muito familiarizados com o código de trabalho porque este é o caso "normal". Bugs, por outro lado, são uma "exceção". Claro, todos nós vimos muitos bugs, mas vimos muito mais código de trabalho em geral. Portanto, temos mais experiência com o funcionamento do código do que com o comportamento do código com bugs. Existem zilhões de livros sobre o código de trabalho e o que ele fará em quais situações. Não há quase nada sobre o comportamento do código de bugs.

A razão para isto é simples: Bugs não são ordem mas caos . Eles geralmente têm um traço de ordem deixado neles (ou o contrário: eles não destroem a ordem completamente), mas sua natureza de buggy é uma destruição da ordem que o programador queria. O próprio caos tende a desafiar a estimativa correta. É muito mais difícil dizer o que um programa com um bug fará do que o que um programa correto fará apenas porque ele não se encaixa mais em nossos padrões mentais.

Terceiro , seu exemplo continha o aspecto de que consertar o bug significaria reformular o programa. (Se você despir este aspecto, a resposta é simples: Corrigir o bug, não deve demorar muito, porque não é necessário reprojetar. Caso contrário :) Nesse caso eu perderia a confiança no programa da maneira como ele é projetado atualmente. O redesenho seria uma maneira de restaurar essa confiança.

Tudo o que foi dito , programas são coisas que as pessoas usam, e um recurso faltante ou um segundo, um bug realmente pesado em outro lugar pode ter prioridade sobre a correção do seu bug. Claro, então pegue o caminho pragmático e faça outras coisas primeiro. Mas nunca se esqueça que uma primeira estimativa rápida do impacto de um bug pode ser totalmente errada.

    
por 19.10.2016 / 15:04
fonte
0

Probabiliddade baixa / Consequências leves = Correção de baixa prioridade

  • Se a probabilidade de ocorrência é muito baixa
  • Se as conseqüências da ocorrência são leves
  • Então o bug não representa uma ameaça, então não é uma correção de prioridade.

Mas isso não pode se tornar uma muleta para desenvolvedores preguiçosos ...

  • O que "ocorrência muito baixa" significa mesmo?
  • Quais "conseqüências leves" significam mesmo?

Para afirmar que a probabilidade de ocorrência é muito baixa e as conseqüências são moderadas, a equipe de desenvolvimento deve entender o código, os padrões de uso e a segurança.

A maioria dos desenvolvedores fica surpreso que as coisas que eles originalmente pensavam nunca aconteceriam, na verdade acontecem muito

Nosso sistema educacional não ensina a probabilidade e a lógica muito bem. A maioria das pessoas, incluindo a maioria dos engenheiros de software, tem uma lógica quebrada e uma intuição de proatividade quebrada. Experiência com problemas do mundo real e experiência com simulações extensas são a única maneira que eu sei para consertar isso.

Enfrente sua intuição com dados do mundo real

É importante fazer vários logs para poder seguir os padrões de uso. Preencha o código com afirmações de coisas que você acha que não deveriam acontecer. Você ficará surpreso com o que eles fazem. Dessa forma, você será capaz de confrontar sua intuição com dados concretos e refiná-la.

Meu exemplo de um problema leve e uma medida de controle

Em um site de comércio eletrônico em que trabalhei há muito tempo, outro programador cometeu um erro: em algumas condições obscuras, o sistema debitava o cliente um centavo a menos do que o registrado nos registros. Eu descobri o bug porque fiz relatórios para identificar as diferenças entre os logs e os saldos das contas para tornar o sistema contábil mais resiliente. Eu nunca consertei esse bug porque a diferença era muito pequena. A diferença foi calculada diariamente e foi inferior a US $ 2,00 mensais. Acontece que estávamos desenvolvendo um sistema totalmente novo que em um ano deveria substituir o atual. Não faz sentido desviar recursos de projetos potencialmente lucrativos para consertar algo que custa US $ 2,00 mensais e foi submetido a uma medida apropriada de controle.

Conclusão

Sim, há bugs que não precisam ser corrigidos imediatamente, que não são importantes o suficiente para atrasar o desenvolvimento de novos recursos. No entanto, o sistema deve ter controle da ocorrência desse bug para garantir que ele seja pequeno, porque não podemos confiar em nossa própria intuição.

    
por 02.11.2016 / 10:08
fonte
-1

Acho que isso está fazendo a pergunta errada desde o começo.

A questão não é "devo corrigir este bug ou não devo corrigir este bug". Qualquer desenvolvedor tem um tempo limitado. Então a questão é "qual é a coisa mais útil que eu posso fazer em uma hora, ou quatro horas, ou uma semana".

Se consertar esse bug é a coisa mais útil, porque ele melhora o software em maior quantidade para a maioria das pessoas, então corrija o bug. Se você pudesse fazer melhorias maiores em outro lugar, adicionando recursos que faltam às pessoas ou corrigindo um bug mais importante, faça essas outras coisas. E bônus extras para qualquer coisa que torne seu desenvolvimento futuro mais eficiente.

    
por 20.10.2016 / 23:50
fonte
-2

A correção de erros é sempre um exagero

Vamos classificar primeiro a parte bug .

É um erro honesto , por ex. um erro único ou um sombreamento variável que escapou dos testes? Neste caso, espero que, além de "consertar" o problema, você também tenha escrito novos testes de unidade, aproveitando a oportunidade para refatorar o código próximo, onde todo o último é trabalho útil .

Se, no entanto, for realmente uma falha de design como no seu caso, você deve reavaliar o design ou, no pior dos casos, desativar este recurso.

Então, por favor, não tente corrigir apenas .

Você poderia fazer pior, claro, --- você poderia tentar hack-upon-hack metodologia. O loop de vídeo é um hack (arquitetura ruim e há uma quebra conhecida). Você pode adicionar um limite de loop , de modo que após N iterações (que você testou está abaixo do limite do navegador) o loop termina.

As ramificações são óbvias, agora você tem que suportar tanto o código quebrado quanto o novo limite de loop.

P.S. desculpas pela visão extrema.

P.P.S. Uma nota sobre a terminologia: você não pode "consertar" um bug. Bem, um veterinário talvez, mas não vamos lá ;-). Os problemas são resolvidos ou "corrigidos", enquanto os erros são removidos ou resolvidos.

    
por 19.10.2016 / 13:46
fonte