Quais abordagens posso adotar para diminuir as chances de introduzir novos bugs em um aplicativo herdado complexo?


10

Onde trabalho, muitas vezes tenho que desenvolver (e corrigir bugs) em um sistema antigo (.NET 1) cujo código é espaguete completo - com pouca atenção aos nomes de variáveis, estrutura do programa ou comentários.

Por causa disso, levo anos para entender quais bits precisam ser alterados e, geralmente, eu "quebro" o software existente porque fiz uma modificação. Eu realmente realmente quer gastar um par de meses (com colegas) passando por isso para refatorar mas existente desenvolvedores ambos não podem ver a necessidade - nem acho que há tempo para isso (o sistema é enorme).

Eu temo ter que trabalhar em seu código, pois leva dias para consertar alguma coisa e descobrir que eu quebrei outra coisa. Obviamente, isso me faz parecer incompetente - então, como posso lidar com isso?


Respostas:


16

Comece a escrever testes para as partes em que está trabalhando. Você pode tentar um fluxo de trabalho mais ou menos assim:

  1. Escreva testes para a parte que você está prestes a alterar. Isso também ajudará você a entender como o código existente se comporta.
    • Refatorar o código para dar suporte aos testes, se necessário, mas você pode escrever testes não unitários se o tempo for curto.
  2. Execute seus testes para garantir que as coisas estejam funcionando conforme o esperado.
  3. Faça as suas alterações. Refatorar, se necessário, com o espírito de melhoria contínua do código, mas não se empolgue.
  4. Execute novamente seus testes para garantir a manutenção da mesma funcionalidade.

Se você não jogar fora seus testes, com o tempo criará um conjunto de testes que deve cobrir as partes mais importantes (e / ou voláteis) do aplicativo, e fazer alterações nele se tornará mais fácil e seguro.

Você também pode achar útil trabalhar com código legado de Michael Feathers.


11
+1 para "... mas você pode escrever testes não unitários se o tempo for curto."!
Marcie

11
Boa resposta. @ m.edmondson Você também pode refazer ao refatorar que certas partes do código são 'enormes' porque há duplicação em todos os lugares e que ao refatorá-lo, ele fica menor e mais simples.
Alb

6

Eu gosto de seguir Uncle Bob Martin 's Boy Regra Escoteiro :

"Quando você tem um monte de bagunçado legado, o que você precisa fazer é ... O que você precisa fazer é parar de fazer as bagunças e começar a limpá-las.

Isso não significa que você chame seus gerentes para uma sala de conferências e diga a eles que não fornecerá recursos pelos próximos três meses enquanto refatora o código. Não faça isso! Pelo contrário, significa que você adotará a “Regra dos escoteiros” e verificará cada módulo com um pouco mais de limpeza do que quando o fez.

De iteração para iteração e de release para release, você limpará esse sistema enquanto continua adicionando novos recursos e funcionalidades a ele. Não há outro caminho."


2

Você pode explicar ao gerente que as correções que devem levar horas acabam levando dias devido à bagunça da base de código. Os outros desenvolvedores não verão necessidade de refatoração se forem os desenvolvedores originais - eles conhecerão o sistema de dentro para fora, mas a gerência deve saber que existe um risco se esses desenvolvedores saírem e levarem seus conhecimentos consigo.

Fazer uma refatoração completa geralmente não é viável, com freqüência você refatora pequenos bits de cada vez - alguns métodos ou um módulo. Heck, se demorar vários dias para fazer uma correção, talvez você possa incluir uma pequena refatoração do módulo problemático ao mesmo tempo.


11
Eu concordo - e no passado eu incluí esses refatores 'pequenos', como eu simplesmente precisava para entender o código - ainda assim, geralmente alguém aparece "você o quebrou completamente" e o reverte para trás como era ...
billy.bob

@ m.edmondson: Ah. Bem, se eles tivessem um conjunto abrangente de testes de unidade, simplesmente executariam para verificar se o refator era bom ou não. Pelo que parece, eles não têm isso, então você terá que escrever os testes de unidade. Eu sei que não é fácil e não há uma resposta definitiva real para esse problema (pelo menos não um que eu encontrei, embora eu esteja assistindo para ver o que as outras pessoas sugerem porque eu também estive lá).
FrustratedWithFormsDesigner

2

Você realmente precisa passar meses refatorando o código? Ou você pode refatorar o código ao fazer alterações. Portanto, por exemplo, se você determinar que o método Foo precisa ser modificado, aproveite a oportunidade para refatorar o método Foo. E se você precisar percorrer uma dúzia de outros métodos para descobrir que Foo é o problema, poderá deixar comentários nesses métodos para que você ou outra pessoa no futuro saiba o que o código deve fazer. Obviamente, isso significa que ainda há uma pilha de código de espaguete, mas você pode pelo menos mover a base de código na direção certa e facilitar a tarefa. Obter vários meses para refatorar o código será uma grande venda, porque isso significa que você não estará entregando o que o usuário final deseja durante todo esse tempo.

E criar testes de unidade (ou, esperançosamente, estender o conjunto de testes existente) deve reduzir a probabilidade de que você inadvertidamente quebre algo.


0

Outra dica. Quando os insetos se manifestam, e depois de aplicar o curativo não para por aí!

Pergunte aos cinco porquês, tome a pílula vermelha e veja a profundidade da toca do coelho, e conserte a causa raiz (e o caminho até lá).

Você aprende muito sobre o sistema. Ajuda a priorizar o que corrigir e refatorar. E depois de algumas dessas viagens, você tem algumas "vigas de suporte" sólidas para fortalecer o monte monolítico de espaguete.


0

Você também pode manter o código antigo no lugar até ter certeza absoluta de que suas modificações são à prova de som. Apenas se for o caso, todas as suas alterações, para que você possa alterná-las no tempo de execução e identificar rapidamente o local do novo bug de regressão:

// old code
...

if (!File.ReadAllText("c:\patch_control.txt").Contains("StrangeUIBugFix=0"))
{
    // new code goes here
    ...
}

// old + new code
int someValue = 
    IsEnabled("StrangeUIBugFix") ? a + b :  // new code
    a * b; // old code

0

Uma Coisa: Never change any existing code if you are not sure what effect change would have on complete application.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.