Corrigir bugs ou esperar o cliente encontrá-los?

35

Outras pessoas corrigem bugs quando os veem ou esperam até que ocorram falhas / perda de dados / pessoas morrem antes de corrigi-lo?

Exemplo 1

 Customer customer = null;
 ...
 customer.Save();

O código está claramente errado, e não há como contornar - ele está chamando um método em uma referência nula. Acontece que não trava porque Savenão acessa nenhum dado da instância; então é como chamar uma função estática. Mas qualquer pequena alteração em qualquer lugar pode causar repentinamente código quebrado que não falha: começar a falhar.

Mas também não é inconcebível que a correção do código:

Customer customer = null;
...
customer = new Customer();
try
   ...
   customer.Save();
   ...
finally
   customer.Free();
end;

pode apresentar uma falha; um não descoberto através de testes de unidade com cobertura completa e teste manual do usuário.

Exemplo 2

float speed = 0.5 * ((G * mass1 * mass2) / R) * Pow(time, 2);

As pessoas saberem física vai reconhecer que é suposto ser de R 2 no denominador.

O código está errado, está absolutamente errado. E superestimar a velocidade fará com que os retro-foguetes disparem muito cedo, matando todos os ocupantes da espaçonave.

Mas também é possível, talvez, superestimar a velocidade, mascarando outro problema: os airbags não podem ser acionados enquanto o ônibus espacial se move muito rápido. Se repentinamente corrigirmos o código:

float speed = 0.5 * ((G * mass1 * mass2) / Pow(R, 2)) * Pow(time, 2);

Agora a velocidade é precisa e, de repente, os airbags estão sendo acionados quando não deveriam.

Exemplo 3

Aqui está um exemplo que eu tive recentemente, verificando se uma string contém caracteres inválidos:

if (StrPos(Address, "PO BOX") >= 0)
{
   //Do something
}

E se houver um erro no Do somethingramo? Corrigindo o código obviamente incorreto:

if (StrPos("PO BOX", Address) >= 0)
{
   //Do something
}

Corrige o código, mas introduz um erro.


A meu ver, existem duas possibilidades:

  • corrigir o código e ser responsabilizado por quebrá-lo
  • aguarde o código travar e seja responsabilizado por ter um bug

O que você faz politicamente?


Exemplo 4 - Bug do mundo real de hoje

Estou construindo um objeto, mas chamando o construtor errado:

Customer customer = new Customer();

Acontece que o construtor "sem parâmetros" é na verdade um construtor parametrizado mais adiante na cadeia de herança:

public Customer(SomeObjectThatNobodyShouldBeUsingDirectly thingy = null)
public Customer(InjectedDependancy depends)

Chamar isso é um erro, pois ignora todos os construtores subseqüentes.

Eu poderia alterar a linhagem do objeto para não expor um construtor tão perigoso, mas agora tenho que alterar o código para:

Customer customer = new Customer(depends);

Mas não posso garantir que essa mudança não vá quebrar nada. Como no meu Exemplo 1 acima, talvez alguém, em algum lugar, de alguma forma, sob algumas condições esotéricas, dependa que o construído Customerseja inválido e cheio de lixo.

Talvez o Customerobjeto, agora que ele esteja corretamente construído, permita a execução de algum código que nunca funcionou anteriormente, e agora eu possa travar.

Não posso apostar na vida da sua esposa.

E posso testar daqui até terça-feira, não posso jurar pela vida de sua filha que não introduzi uma regressão.

Eu:

  • Corrigir o código e ser responsabilizado por quebrá-lo? ou
  • Deixe o bug e seja responsabilizado quando o cliente o encontrar?
Ian Boyd
fonte
33
Se você não está disposto a mudar nada, porque isso pode quebrar alguma coisa e se considera não qualificado para examinar o que pode acontecer em outras partes do código, o que está fazendo aqui? Você está paralisado com o teclado porque a linha de código que você está prestes a escrever pode estar errada?
David Thornley
3
certamente uma pergunta bem pesquisada
Muhammad Alkarouri 28/10/10
2
"Fazer alguma coisa" geralmente é uma chamada para outras funções que você escreveu ou funciona de bibliotecas; em ambos os casos, o código deveria ter sido testado em unidade. O procedimento em si também é testado em unidade, deixando as chances de novos bugs serem introduzidos quando você corrige um muito baixo ... Se eu construir uma ponte, testarei primeiro em uma escala menor, em vez de deixar as pessoas que andam sobre a ponte morrerem. . Se você não está fazendo testes de unidade quando está preocupado com bugs, está fazendo errado. Seja como for, você é o culpado; portanto, em vez de corrigi-lo, você pode evitá-lo e não ser responsabilizado.
Tamara Wijsman
2
'espere até que as pessoas morram antes de consertá-lo'! Santo vaca, eu espero seriamente há apenas uma resposta a esta ...
Chris Knight
3
Como um comentário específico sobre uma coisa que você disse: você não sabe se, em algum outro lugar do código, eles se baseiam no comportamento esotérico: e daí? Se alguém está abusando de uma regra de escopo claramente incorreta como um hack no código, o código está errado. Uma boa OOP teria evitado esse bug, mas você não consertar, porque eles usaram uma prática ruim está agravando o problema, deixando-o aberto para novos abusos e tornando o sistema mais instável o tempo todo. Corrija o erro, espere que o teste encontre problemas, corrija mais erros, se não houver. A estabilidade a longo prazo do produto é uma métrica vital.
CodexArcanum

Respostas:

34

Isso depende muito da situação, do bug, do cliente e da empresa. Há sempre uma troca a considerar entre corrigir a implementação e potencialmente introduzir novos bugs.

Se eu desse uma orientação geral para determinar o que fazer, acho que seria algo assim:

  1. Registre o defeito no sistema de rastreamento de sua escolha. Discuta com a gerência / colegas de trabalho, se necessário.
  2. Se for um defeito com conseqüências potencialmente terríveis (por exemplo, seu exemplo nº 2), corra, grite, pule para cima e para baixo até alguém com autoridade notar e determine um curso de ação apropriado que atenue os riscos associados à correção do bug. Isso pode atrasar sua data de lançamento, salvar vidas, lavar suas janelas etc.
  3. Se for um defeito ininterrupto ou existir uma solução alternativa, avalie se o risco de corrigi-lo supera os benefícios da correção. Em algumas situações, será melhor esperar que o cliente o exiba, pois você sabe que não está gastando tempo consertando / testando novamente as coisas quando não é 100% necessário.

Lembre-se, isso só se aplica quando você está perto de um lançamento. Se você estiver no modo de desenvolvimento completo, basta registrar o defeito para que ele possa ser rastreado, corrigido e finalizado. Se for algo que demora mais do que, digamos, meia hora para consertar e verificar, eu procuraria o líder / gerente da equipe e veria se o defeito deve ou não se encaixar no ciclo de lançamento atual ou agendado para mais tarde.

Adam Lear
fonte
Muito verdadeiro. É por isso que (algumas) empresas têm gerentes técnicos, rastreamento de bugs e assim por diante: para priorizar as coisas. Não estou dizendo que não tome iniciativa - de maneira alguma - mas você precisa usar o bom senso. Tomar a iniciativa errada na hora errada é chamado "ser um canhão solto" e pode matar uma empresa. Além disso, a importância de um bug específico varia de empresa para empresa. Para alguns programas, um erro de digitação em uma caixa de diálogo é um bug cosmético de baixa prioridade a ser corrigido em uma versão futura e, em outros, é uma emergência de parada imediata.
Bob Murphy
6
+1 para registrar o defeito. Outros defeitos podem ter prioridade ...
Enviado
35

Os clientes sempre encontrarão bugs . Nunca há erros ocultos dos clientes. No final, os erros que você apresentar sempre voltarão para você. Não consertá-los é simplesmente uma má prática profissional. Profissionais não fazem isso.

Quando os clientes encontram bugs, a empresa parece ruim, não um desenvolvedor individual. Isso é muito pior para a empresa, então é o seu caso para fazer a alteração. Se você realmente não tiver certeza de fazer essa alteração com medo de introduzir outros erros, converse com um desenvolvedor mais sênior, com o líder técnico do projeto ou com quem estiver em posição de tomar uma decisão sobre essa alteração e, posteriormente, lidar com as consequências.

ysolik
fonte
2
Essa é uma triste verdade. Tivemos que entregar um projeto que testamos como louco, e ainda assim o cliente conseguiu travá-lo em 3 minutos.
Oliver Weiler
4
@ Método Helper: Talvez se você tivesse testado como pessoas sãs, teria sido melhor.
Vinko Vrsalovic 28/10/10
Método @ Helper: Embora, mais sério, se fossem realmente três minutos, parece que os testadores não sabiam quais eram os casos de uso reais esperados pelo cliente.
Vinko Vrsalovic 28/10/10
8
Método @Helper: envolva o cliente nos testes (assumindo o cliente == cliente). Os desenvolvedores que escrevem e testam código são problemas que os desenvolvedores não usam software da mesma maneira. Os desenvolvedores são gentis. É o trabalho deles - a arte deles: os clientes batem nele como um macaco em um panio. Quando possível, compartilhe o esforço de teste e compartilhe a responsabilidade. Isso não se encaixa em todos os ambientes, mas, trabalhando com os clientes em equipe, os consultores não podem oferecer um software melhor.
brian Chandley
Er, pior? (filler)
Hello71
24

Corrigir o erro

Somos profissionais aqui. Se você encontrar um caminho com falha no código que causará uma falha ou comportamento incorreto, será necessário corrigi-lo. Dependendo dos procedimentos de sua equipe, você provavelmente precisará registrar um defeito, talvez escrever um teste de regressão e verificar a correção no momento certo do ciclo de envio. Se for um bug de baixa prioridade, verificar a correção perto do início de um marco é sempre um bom momento, porque se você fizer uma regressão, não afetará o ciclo de lançamento do marco.

Não confunda isso com refatoração ou aprimoramentos de desempenho que não estão relacionados a um bug de desempenho.

Um sistema de controle de fonte distribuído onde você pode manter um repositório separado de 'pequenas correções de bugs' e depois mesclar facilmente no início de um marco é uma grande ajuda aqui.

Jay Beavers
fonte
4
+1. Consertá-lo. Se a correção quebrar outra coisa, então outra coisa foi quebrada - conserte-a também. Se o seu teste não detectar essas interrupções, ele será interrompido - corrija-o também. Você não pode ter medo de mudar o código com medo de quebrar alguma coisa - esse caminho leva apenas à ruína total.
Tom Anderson
21

O que o cliente diria?

Aqui está como eu imagino isso acontecendo:

Cliente: falha quando eu faço x.

Programador: Ah, sim! Lembro que vi isso há um tempo. Achei que ainda não era grande coisa, então deixei lá.

Cliente: [alcança o objeto sem corte]

Sim. Corrija o erro. Você salvará o cliente de uma experiência agravante e poderá corrigi-lo antes que se torne uma emergência.

E se você acha que sua correção pode realmente causar uma falha, ainda não a encontrou.


fonte
8

Todos os exemplos que você deu parecem ter um encadeamento comum. Você parece querer corrigir um erro que não entende completamente. Eu digo isso porque você observa a possibilidade de consequências indesejadas em cada uma delas.

Eu diria que provavelmente é um grande erro e, como Ben Laurie escreve , não corrige um bug que você não entende . Neste exemplo famoso, a equipe do Debian quebrou a criptografia do OpenSSL para Debian e derivados como o Ubuntu quando seguiu os resultados de uma ferramenta de análise.

Se você acredita que há um defeito observando o código, certifique-se de reproduzir o defeito da maneira que o cliente possa ver. Se você não pode, por que não gastar seus recursos consertando outra coisa?

Conrad Frix
fonte
7

Comece a reduzir sua dívida técnica o mais rápido possível .

Seus exemplos definitivamente parecem código legado , com muita dívida técnica e sinto que há medo de mudar (BTW, isso não é uma crítica ou um julgamento). Toda a sua equipe precisa reconhecer que você tem essa dívida técnica (para que você não seja o único culpado por isso) e, em seguida, pode decidir como vai lidar com isso.

No Exemplo 1, se Save()não acessar nenhum dado da instância, quais dados do cliente são salvos exatamente? Comece consertando e testando isso.

No Exemplo 2, é fácil cobrir a calculadora de velocidade com testes e garantir que ela calcule o resultado correto em todos os principais exemplos.

No exemplo 3, há o risco de trazer o código morto de volta à vida. Esse código deve ser eliminado por completo? Qual é a intenção da condição booleana nesse caso? É para garantir que a sequência não contenha caracteres inválidos? Ou para garantir que tenha "PO BOX"? Quanto mais cedo você começar a abordar essas questões, melhor.

Depois de corrigir vários desses problemas, faça uma espécie de retrospectiva / post mortem com sua equipe. É importante aprender com a experiência para poder reduzir sua taxa de injeção de defeitos no futuro.

azheglov
fonte
5

Você já tem boas respostas. Vou apenas acrescentar algo sobre a questão de ter medo de que algo trava.

Primeiro, na situação ideal, o software é modular, é arquitetado corretamente e há uma boa separação de preocupações. Nesse caso, é muito improvável que as alterações feitas quebrem qualquer coisa, pois você controlará todo o código relacionado e não haverá surpresas ocultas.

Infelizmente, a situação ideal é fictícia. Independentemente da extensão em que o acoplamento esteja frouxo, haverá acoplamento e, portanto, a possibilidade de quebrar outra coisa.

A solução para isso é dupla:

  1. Torne o código o mais estruturado possível.
  2. Quando o código estiver isolado o suficiente para que você saiba que nada mais irá quebrar, corrija-o.

Tornar o código bem estruturado não é feito reescrevendo o código inteiro em um novo design de arquitetura. Em vez disso, a refatoração guiada por testes é sua amiga aqui. Nesta etapa, você não altera a funcionalidade.

O segundo passo é que você conserta o bug.

Alguns pontos são relevantes:

  1. O controle de versão é absolutamente necessário para esse processo.
  2. A etapa de refatoração e a etapa de correção de erros são mais comprometidas com o controle de versão como confirmações separadas, para que cada uma tenha uma funcionalidade histórica bem definida.
  3. Não se fixe na possibilidade de cometer outro erro, pois você não fará nada. Em vez disso, pense em melhorar seu código. Em outras palavras, a menos que você saiba que está aumentando os erros em vez de diminuí-los, deve fazê-lo.
  4. Relacionado ao último ponto: não tente prever o futuro. Os seres humanos são tendenciosos ao pensar que são muito bons em prever. Na realidade, nossos poderes de previsão são de curto prazo. Portanto, não se preocupe com um bug futuro indefinido vago. Este também é o princípio por trás do YAGNI .
  5. A ferramenta correspondente ao controle de versão no mundo dos bugs é o rastreador de bugs . Você precisará disso também.
  6. Você precisa corrigir os erros por dois motivos: para satisfazer o cliente; e para poder progredir no seu desenvolvimento. Para usar o exemplo 3 (o da física): se o programa satisfizer o cliente com uma equação tão quebrada, existem muitas outras partes do software que foram desenvolvidas incorretamente para mitigar esse bug (por exemplo, a implantação do airbag). Se uma versão 2 (ou 1.1) for necessária para este software, será cada vez mais difícil desenvolver o código correto com base nesse código defeituoso. Você está indo para a grande reescrita ou para o grande fracasso. Ambos os quais você deve evitar.

Já são mais do que alguns pontos, então acho que vou parar por aqui.

Muhammad Alkarouri
fonte
3

Você primeiro precisa considerar a definição de um bug:

  1. O código lido não corresponde ao que você percebe estar certo
  2. O software não executa corretamente suas tarefas

Parece que você está focado no número 1, onde o número 2 é o melhor lugar para se sentar. Certamente, nós programadores queremos que nosso código esteja correto (nº 1), mas as pessoas nos pagam para que ele funcione (nº 2).

O que você pode ou não fazer com a base de código que pode acidentalmente introduzir novos bugs é irrelevante para a visão nº 2 do software atual. No entanto, o nº 1 é importante para você ou para o programador de manutenção a seguir. Às vezes é difícil decidir, mas quando o segundo e o primeiro estão em conflito, você precisa saber que o segundo é claramente mais importante.

John Fisher
fonte
2

Nem. Existe uma terceira maneira: encontre uma maneira de provar que "o código problemático" está realmente causando problemas do ponto de vista comercial. Confirme o que encontrou com BA / QA ou pelo menos com seu gerente. Em seguida, planeje a correção quando todos estiverem cientes do problema.

Existem outros cenários possíveis além de um bug válido nos casos mencionados:

  1. O código que você está vendo é algum código morto. É possivelmente porque, como disse ysolik: os clientes sempre encontram bugs. Caso contrário, talvez o código nunca seja executado.
  2. Havia uma situação da WTF em que o erro óbvio tinha seu objetivo. (Estamos falando de código de produção, tudo poderia ter acontecido, certo?)
  3. Os negócios / clientes já sabiam do problema, mas não sentem necessidade da correção.
  4. Talvez mais...

Nos dois casos acima, se eu sou gerente, não quero que os desenvolvedores usem seu julgamento e corrijam o "erro". A correção do erro no local pode ajudar na maior parte do tempo, mas quando ocorre um erro, pode causar mais problemas do que sua boa intenção.

Codism
fonte
11
Se você deseja contratar apenas desenvolvedores que não usam seu próprio julgamento, existem muitos realmente medíocres por aí. Você terá problemas para contratar bons profissionais, que confiam em sua capacidade.
David Thornley
11
@ David: não estenda minha opinião a um grau inadequado. Os desenvolvedores definitivamente precisam de seu julgamento, mas deve haver um limite. Nesse caso, os desenvolvedores usam seu julgamento para detectar um bug em potencial e tomam outras medidas para resolvê-lo.
Codism 28/10/10
2

Eu:

  • corrigir o código e ser responsabilizado por quebrá-lo? ou
  • deixar o erro e ser responsabilizado quando o cliente o encontrar?

Você corrige o erro, inicia os testes de unidade e, quando obtêm êxito, verifica sua correção.

(Ou, se seus testes de unidade levarem muito tempo, verifique sua correção primeiro e aguarde se a ferramenta de CI envia um email a você porque sua confirmação quebrou alguma coisa.)

sbi
fonte
11
Ou, se você usa um check-in fechado, configure-o para não fazer o check-in de código quebrado.
Adam Lear
3
Levar muito tempo não é desculpa para cometer códigos de má qualidade.
Toby
@ Toby: Quem estava falando de desculpas? Atualmente, estou trabalhando em uma equipe pequena, nem mesmo em meia dúzia de desenvolvedores. Os testes de unidade para o projeto levam 1 hora. Nossa política é executar os testes que parecem relacionados ao que você faz e, em seguida, fazer check-in e deixar a CI descobrir se você quebrou algo aparentemente não relacionado. Isso não funcionaria em uma equipe grande, mas em uma equipe pequena economiza muito tempo.
SBI
1

Corrija-os se forem erros de falha / perda de dados. O envio de um programa com um bug conhecido de perda de dados é absolutamente malicioso e indesculpável.

Se o bug for estético ou não crítico (pode ser evitado), ele deve ser documentado e uma solução alternativa deve ser fornecida. Idealmente, ele deve ser corrigido, mas às vezes é muito caro corrigi-lo para a versão atual.

Observe como todo projeto de software maior tem uma seção 'Problemas conhecidos' no Leia-me, que geralmente lista exatamente isso: Bugs conhecidos.

Conhecer Bugs e NÃO comunicá-los é IMHO aceitável apenas para bugs realmente menores / cosméticos.

Michael Stum
fonte
1

Corrija e faça o teste. Se você decidir manter os bugs conhecidos apenas porque tem medo de encontrar mais bugs, seu programa se tornará um campo minado de bombas-relógio tão rápidas que se tornará irreparável mais cedo do que você pensa.

Como você é o mestre e o código é o subordinado, talvez você não tenha medo de alterá-lo quando perceber que está errado. O medo do código ("pode ​​retaliar quebrando em outro lugar") é simplesmente inaceitável.

user281377
fonte
0

Se houver claramente um triturador, ou algo errado , você deve corrigi-lo. Se houver uma ambiguidade na especificação, ou seja, se você estiver pensando "bem, o cliente pode esperar isso, mas parece que pode ser um bug" ou um problema na especificação, como "fomos solicitados a fazer isso" mas é péssimo ", então você precisa descobrir o que fazer. Jogar o código por cima do muro e aguardar o feedback do cliente é ruim - você pode perguntar a um gerente de produto se possui um ou pedir ao cliente antes de implantar o produto.

Lembre-se de que "conhecemos esse problema e o corrigiremos em uma versão futura" é sinônimo de "conhecemos esse problema, mas não nos importamos com você o suficiente para evitar que você lide com ele".


fonte
0

O curso de ação correto não é ignorar o bug, nem "consertá-lo" no local; pelas mesmas razões que você identificou na sua pergunta.

Eu acho que você deve tentar entender o código primeiro. Se o código que você está vendo tem alguma idade e ninguém percebeu o "bug" ainda, provavelmente há uma razão para isso. Tente encontrar esse motivo. Aqui está o que eu gostaria de analisar antes de tomar uma decisão:

  • Histórico : use o software de controle de versão para responder às perguntas: Quem tocou no código? O que eles mudaram? E com quais mensagens de confirmação eles fizeram check-in? Você pode deduzir um motivo pelo qual o código parece?

  • Uso : Qual código usa o código defeituoso? E como? O código está morto? Existe outro código que se baseia no comportamento defeituoso?

  • Autor : Se você não conseguir chegar rapidamente a uma conclusão usando as informações acima, pergunte ao autor do código (pelo menos se isso for possível) por que o código tem a aparência que ele tem. Normalmente, você receberá um "Oups, isso deve ser corrigido!" ou um "Não! Não mude !!! É necessário assim!" Imediatamente.

cmaster
fonte