Quelles approches puis-je adopter pour réduire les chances d'introduire de nouveaux bogues dans une application héritée complexe?


10

Là où je travaille, je dois souvent développer (et corriger des bogues) dans un ancien système (.NET 1) dont le code est un spaghetti complet - sans trop penser aux noms de variables, à la structure du programme ni aux commentaires.

À cause de cela, il me faut beaucoup de temps pour comprendre quels bits doivent être modifiés, et je «casse» souvent le logiciel existant parce que j'ai apporté une modification. Je veux vraiment vraiment passer quelques mois (avec des collègues) à le refactoriser, mais les développeurs existants ne peuvent pas voir le besoin - ni penser qu'il est temps pour cela (le système est énorme).

Je redoute de devoir travailler sur son code car il faut des jours pour réparer quelque chose seulement pour découvrir que j'ai cassé autre chose. Cela me rend évidemment incompétent - alors comment puis-je faire face à cela?


Réponses:


16

Commencez à écrire des tests pour les pièces sur lesquelles vous travaillez. Vous pouvez essayer un flux de travail qui ressemble à ceci:

  1. Écrivez des tests pour la partie que vous êtes sur le point de changer. Cela vous aidera également à comprendre le comportement du code existant.
    • Refactorisez le code pour prendre en charge les tests si nécessaire, mais vous souhaiterez peut-être écrire des tests non unitaires si le temps est court.
  2. Exécutez vos tests pour vous assurer que les choses fonctionnent comme prévu.
  3. Apportez vos modifications. Refactorisez si nécessaire dans un esprit d'amélioration continue du code, mais ne vous laissez pas emporter.
  4. Relancez vos tests pour vous assurer que vous avez conservé les mêmes fonctionnalités.

Si vous ne jetez pas vos tests, vous allez au fil du temps créer une suite de tests qui devrait couvrir les parties les plus importantes (et / ou volatiles) de l'application et y apporter des modifications deviendra plus facile et plus sûr.

Vous pourriez également trouver utile de travailler efficacement avec le code hérité de Michael Feathers.


1
+1 pour "... mais vous voudrez peut-être écrire des tests non unitaires si le temps est court."!
Marcie

1
Bonne réponse. @ m.edmondson Vous pouvez également constater en refactorisant que certaines parties du code sont «énormes» car il y a duplication partout et que lorsque vous refactorisez cela devient à la fois plus petit et plus simple.
Alb

6

J'aime suivre l' oncle Bob Martin « s Boy Scout Règle :

"Lorsque vous avez une grosse liasse héritée en désordre, ce que vous devez faire est ... Ce que vous devez faire est d'arrêter de faire les dégâts et de commencer à les nettoyer.

Cela ne signifie pas que vous appelez vos responsables dans une salle de conférence et que vous leur dites que vous n'allez pas proposer de fonctionnalités pour les trois prochains mois pendant que vous refactorisez le code. Ne faites pas cela! Au contraire, cela signifie que vous allez adopter la «règle du boy-scout» et vérifier chaque module dans un peu plus propre que lorsque vous l'avez vérifié.

D'itération en itération et de version en version, vous allez nettoyer ce système tout en continuant à lui ajouter de nouvelles fonctionnalités et fonctionnalités. Il n'y a pas d'autre moyen."


2

Vous pourriez expliquer au gestionnaire que les correctifs qui devraient prendre des heures finissent par prendre des jours en raison du désordre de la base de code. Les autres développeurs ne verront aucun besoin de refactoring s'ils sont les développeurs d'origine - ils connaîtront le système à fond, mais la direction devrait savoir qu'il y a un risque si ces développeurs partent et emportent leurs connaissances avec eux.

Faire un refactoring complet n'est généralement pas possible, donc souvent vous refactorisez de petits morceaux à la fois - quelques méthodes ou un module. Heck, si cela prend plusieurs jours pour faire un correctif, vous pouvez peut-être inclure une petite refactorisation du module problématique en même temps.


1
Je suis d'accord - et dans le passé, j'ai inclus ces «petits» refacteurs comme je n'en avais besoin que pour comprendre le code - mais quelqu'un arrive généralement «vous l'avez complètement cassé» et le retourne ...
billy.bob

@ m.edmondson: Ah. Eh bien, s'ils avaient une suite complète de tests unitaires, ils pouvaient simplement vérifier si le refactor était bon ou non. D'après ce que cela ressemble, ils n'ont pas cela, vous devrez donc écrire les tests unitaires vous-même. Je sais que ce n'est pas facile et il n'y a pas de vraie réponse définitive à ce problème (du moins pas que j'ai trouvé, bien que je regarde pour voir ce que les autres suggèrent car j'y suis allé aussi).
FrustratedWithFormsDesigner

2

Avez-vous vraiment besoin de passer des mois à refactoriser le code? Ou pourriez-vous refactoriser le code lorsque vous apportez des modifications. Ainsi, par exemple, si vous déterminez que la méthode Foo doit être modifiée, vous pouvez en profiter pour refactoriser la méthode Foo. Et si vous devez parcourir une douzaine d'autres méthodes pour comprendre que Foo est le problème, vous pouvez laisser des commentaires dans ces méthodes afin que vous ou quelqu'un d'autre à l'avenir sache ce que le code est censé faire. Bien sûr, cela signifie qu'il y a encore une pile de code spaghetti, mais vous pouvez au moins déplacer la base de code dans la bonne direction et vous faciliter la tâche sur toute la ligne. Obtenir plusieurs mois de temps pour refactoriser le code va être une grande vente, car cela signifie que vous ne fournissez pas tout ce que l'utilisateur final veut pendant tout ce temps.

Et la création de tests unitaires (ou, espérons-le, l'extension de la suite de tests existante) devrait rendre moins probable que vous cassiez quelque chose par inadvertance.


0

Un autre conseil. Lorsque les insectes se manifestent et après avoir appliqué le bandage, ne vous arrêtez pas là!

Demandez aux cinq pourquoi, prenez la pilule rouge et voyez à quelle profondeur va le trou du lapin, et corrigez la cause profonde (et le chemin vers le bas).

Vous en apprendrez beaucoup sur le système. Il aide à prioriser ce qu'il faut réparer et refactoriser. Et après quelques voyages de ce genre, vous avez de solides "poutres de support" pour renforcer le tas monolithique de spaghettis.


0

Vous pouvez également conserver l'ancien code en place jusqu'à ce que vous soyez absolument certain que vos modifications sont insonorisées. Juste au cas où toutes vos modifications, vous pouvez les basculer au moment de l'exécution et localiser rapidement l'emplacement du nouveau bogue de régression:

// 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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.