Tester du "Legacy Code", mission impossible ? - Karl Métivier

150 vues

Publié le

Tester du "Legacy Code", mission impossible?
Certaines organisations tentent d'ajouter des tests unitaires automatisés au code existant pour stabiliser un système en production. Les développeurs se frappent rapidement à plusieurs problèmes, le système n’ayant pas été conçu au départ pour accepter ces tests. Nous verrons des exemples typiques de problèmes rencontrés et leurs solutions, ainsi que les causes produisant code patrimonial.

À propos de Karl Métivier
Monsieur Métivier détient un baccalauréat en informatique de génie, obtenu en 1997, à l'Université Laval. Il possède plus de dix-neuf (19) années d'expérience en développement de systèmes informatiques dans diverses technologies, dont le Microsoft.NET.
Passionné de code, d’architecture et des approches Agiles, M. Métivier a toujours le souci d’écrire le code de manière lisible, simple et bien organisée. Il applique les principes de « Clean Code » et « SOLID » autant que possible.
L’expérience de Monsieur Métivier couvre plusieurs domaines de l’informatique et en particulier l'architecture logicielle, la programmation et les méthodes Agiles. Il connait d’ailleurs très bien SCRUM, XP Programming, Kanban et Lean Software Development. Il est de plus un ScrumMaster certifié (CSM) depuis 2008 et Professionnal Scrum Master (PSM I) depuis 2014. Il occupe aussi parfois le rôle de Coach Agile pour expliquer des concepts, faire des présentations et guider les équipes dans leur transition Agile.

Publié dans : Technologie
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
150
Sur SlideShare
0
Issues des intégrations
0
Intégrations
0
Actions
Partages
0
Téléchargements
14
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Tester du "Legacy Code", mission impossible ? - Karl Métivier

  1. 1. Tester du Legacy Code, mission impossible ?
  2. 2. Bon après-midi, Ethan. • Votre mission, si vous l’acceptez, consiste à vous occuper d’un système informatique qui n’est pas nouveau ni trop vieux, mais qui n’a aucun tests automatisé. • Par contre, il est au cœur de plusieurs traitements d’affaires critiques. Vous allez avoir à ajouter de nouvelles fonctionnalités et a en faire l’entretien. • Nous avons observés les choses suivantes: – Classes de la logique d’affaire qui fait 32 000 lignes. – Une interface de 2000 lignes (incluant une ligne de commentaire par méthode) été créé récemment pour vous permettre d’introduire des tests. • Ce message s’auto-détruira dans 5 secondes …..
  3. 3. Bon après-midi, Ethan. • Votre mission, si vous l’acceptez, consiste à vous occuper d’un système informatique qui n’est pas nouveau ni trop vieux, mais qui n’a aucun tests automatisé. • Par contre, il est au cœur de plusieurs traitements d’affaires critiques. Vous allez avoir à ajouter de nouvelles fonctionnalités et a en faire l’entretien. • Nous avons observés les choses suivantes: – Classes de la logique d’affaire qui fait 32 000 lignes. – Une interface de 2000 lignes (incluant une ligne de commentaire par méthode) été créé récemment pour vous permettre d’introduire des tests. • Ce message s’auto-détruira dans 5 secondes ….. MISSION
  4. 4. Qui sommes-nous ? • Karl Métivier – Architecte Logiciel – Développeur – Coach Agile – Formateur • Yves St-Hilaire – Soutien au développement – Accompagnement, mentorat – Développement BI
  5. 5. Histoire d’un système • On change notre processus, on passe à Scrum. • On nous demande d’ajouter des tests unitaires automatisés au code existant. – Oups, le système n’a pas été prévu pour cela… • Comment avoir le temps pour cela ? – Réunion pour discuter des bogues courants. – Documentation à mettre à jour. • Au final, problème de dette technique.
  6. 6. Code Legacy C’est quoi pour vous ?
  7. 7. Définitions pour le Legacy Code • Du code Legacy, c’est du code: – sans tests unitaires - Michael Feathers – plus vieux que ceux qui y travaillent – modifications en mode « patchage » – nécessitant un guide du marais pour s’y retrouver! • Enfreint constamment les principes SOLID • On n’ose pas y toucher. • Et les Legacy Systems ?
  8. 8. Code « Legacy » Quand vous avez à travailler avec ça, c’est quoi votre feeling ?
  9. 9. Pourquoi est-on pognés avec ça ? • Délais courts de développement • Plusieurs personnes y sont passées • Conception Legacy? –Architecture identique au dossier fonctionnel • Peu d’efforts alloués pour l’amélioration –Le système fonctionne, on n’y investit rien
  10. 10. Quel est le problème au juste ?
  11. 11. Architecture incohérente
  12. 12. La conception n’est pas conçue pour les tests
  13. 13. Dépendances cachées
  14. 14. Code «pas propre» et bien d’autres
  15. 15. Le dilemme du refactoring • Pour faire du refactoring, on doit avoir des tests • Pour mettre en place des tests, on doit refactoriser.
  16. 16. Tester le Legacy Code: 1 - Comment le faire ?
  17. 17. Cas 1 – Classe sans injection de dépendances • Pas de possibilité d’injecter un mock • Plusieurs appelants l’utilisent, souvent on ne peut les modifier
  18. 18. Cas 1 – Classe sans injection de dépendances Comment ? • Pour la classe qu’on veut mocker : – Ajout d’une interface • À la classe à tester : – Ajout d’un constructeur permettant l’injection – On lui injectera l’instance à utiliser, ou une Factory • Les appelants ne sont pas impactés • On permet l’injection, mais les appelants existants ne l’utilisent pas
  19. 19. Cas 1 – Ajout d’injection – Comment public class MyClass { private IFileReader reader; public MyClass(string fileName) { // original code // ... reader = new MyFileReader(fileName); } public MyClass(IFileReader injectedReader) { // original code // ... reader = injectedReader; } }
  20. 20. Cas 1b – Classe sans injection de dépendances Comment ? • Autre technique : Patron « Test Specific Subclass » • Classe à mocker : ajout d’une interface à la classe • Classe à tester : – Ajout d’une méthode virtuelle « ObtenirInstanceClasseAppelee » • Dans le projet de test : – Hériter de la classe à tester – Implémenter notre propre « ObtenirInstanceClasseAppelee »
  21. 21. Cas 1b – Test specific subclass – Comment? public class MyClass { protected int someProtectedInfo = 42; private IFileReader reader; public MyClass(string fileName) { reader = GetReader(fileName); } protected virtual IFileReader GetReader(string fileName) { return new MyFileReader(fileName); }} public class MyClassSpecificSubclass : MyClass { public IFileReader InsertMockHere; public MyClassSpecificSubclass(IFileReader aReader) { InsertMockHere = aReader; } protected override IFileReader GetReader(string fileName) { return InsertMockHere; } public int GetInternalInfo() { return someProtectedInfo; }}
  22. 22. Cas 2 – La classe iceberg • Reconnaissable facilement – Grosse • Milliers, dizaines de milliers de lignes – Peu de méthodes publiques • Comptées sur une seule main • C’est quoi le problème? – Grande complexité cyclomatique – Interdépendances entre les méthodes – Donc difficile à tester
  23. 23. Cas 2– La classe iceberg – Comment? • Identifier les différentes responsabilités – Noms de méthodes – #Region ou zones de commentaires • Refactoriser en plusieurs classes • Si impossible : – Identifiez les méthodes qui seraient publiques avec un refactoring – Changer la visibilité et testez ces méthodes
  24. 24. Cas 2– La classe iceberg – Exemple (classe simplifiée!)
  25. 25. Cas 3 – Méthode statique • Une méthode statique, l’équivalent d’un singleton • Une seule version possible pour tout le système – Donc pas mockable • Pas un problème pour la tester • Mais un véritable problème pour tester les méthodes qui l’appellent
  26. 26. Cas 3 – Méthode statique – Comment? • Ajout d’une interface à la classe • Ajout de méthodes d’instance correspondant aux méthodes statiques – DRY : la méthode d’instance peut appeler la méthode statique! – Les appelants ne sont pas affectés • Éventuellement on pourra enlever complètement les méthodes statiques
  27. 27. Cas 3 – Méthode statique – Code public class ClassUnderTest { public void MethodUnderTest() { // ... var number = AnotherClass.GetNumber(); if (number > 0) { } else { } // ... } } public class AnotherClass { public static int GetNumber() { return 4; } }
  28. 28. Cas 3 – Méthode statique – Code public class ClassUnderTest { private IAnotherClass _anotherClass; public ClassUnderTest() { _anotherClass = new AnotherClass(); } public ClassUnderTest(IAnotherClass anotherClass) { _anotherClass = anotherClass; } public void MethodUnderTest() { // ... var number = _anotherClass.GetNumber(); if (number > 0) { } else { } // ... } } public class AnotherClass: IAnotherClass { public static int GetNumber() { return 4; } int IAnotherClass.GetNumber() { return AnotherClass.GetNumber(); } }
  29. 29. Mais en avez-vous vraiment besoin ? • Parfois, l’ajout de tests unitaires demande beaucoup d’efforts pour peu de gains • Évaluer d’autres opportunités – CodedUI / Selenium – Tests intégrés, mocker uniquement les données – Tests comparatifs • Pas toujours les meilleures pratiques, mais faut s’adapter au contexte!
  30. 30. Comment le BDD m'a aidé dans mon débogage • Partir d’un cas d’utilisation (déjà implémenté) et le descendre en étape BDD du début (contrôleur UI), passer par le service et aboutir dans une BD en mémoire • C’est long • On vérifie toutes les dépendances et on traverse toutes les couches • C’est long, mais après coup notre compréhension du code s’est vraiment améliorée • En plus, le test BDD reste et peut être rejoué !
  31. 31. État d’esprit pour déboguer de Legacy Code • Voir le code comme une scène de crime • Faire un profil de l’agresseur (ou de ce qui cause le problème) • Analyser les hot-spots • Calculer la complexité • Faire la dissection de l’architecture • Cartographier une carte de connaissances de votre système • Impact sur l’existant
  32. 32. Tester le Legacy Code: 2 - Comment avoir le droit ?
  33. 33. Versus la résistance
  34. 34. C’est impossible d’en faire chez nous car… • Nous autres, c'est différent • On a un système de mission critique à l'entreprise • Nos utilisateurs ont le contrôle et le budget • Notre système est très complexe • On a des données nominatives • …
  35. 35. C’est notre devoir d’être professionnel Du code propre n’apparaît pas de lui-même: • Vous avez à le produire • Vous avez à le maintenir • Vous en faites un engagement professionnel
  36. 36. Combattre le résistance en discutant • La plupart des gestionnaires défendent leurs échéanciers et les requis avec passion. – Cela fait partie de leurs responsabilités. • Votre responsabilité : – Défendre également le code avec passion. • Ayez le courage de dire la vérité et de travailler pour arriver à un terrain d’entente. • Discuter avec votre PO ou votre chef d’équipe. Il devrait être sensible à la qualité produite. Donc de supporter l’équipe quand il sent qu’un refactoring est nécessaire.
  37. 37. Il faut alors être stratégique • Cela ne donne pas grand chose de travailler sur du code qui va bien et qui n’a pas de problème régulièrement. Don’t fix it, if it’s not broken. • Trouver les points chauds de votre système: – Bogues réguliers – Difficiles à travailler – Modification à faire prochainement – Logique d’affaires importante • Progresser par la technique des petits pas.
  38. 38. Bien évaluer Valeur de cet investissement : • Potentiel • Bloquant actuel • Criticité du système • Nombre de personnes impactées • Durée de vie du système • Refonte prévue?
  39. 39. La résistance peut donc être combattue • C’est souvent le premier pas le plus difficile. • Ne pas oublier : – Être stratégique – Évaluer le tout • Y aller un test à la fois: – Et son Refactoring de code qui le suit.
  40. 40. En fait, on en revient à la transparence Le premier pilier de l’agilité!
  41. 41. 3. Comment tester du Legacy Code au jour le jour et s’en prémunir?
  42. 42. Comprendre le code • Les tests nous apportent une façon de comprendre le code. • D’une certaine manière, les tests nous font travailler dur pour arriver à cette compréhension. • Il est facile de faire des tests en présence d’une bonne conception.
  43. 43. Ne pas hésiter à utiliser des outils modernes • Legacy != outils désuets • Exemples : – Intégration continue – Dernière version de l’IDE – Dernières versions des librairies et frameworks – Système Legacy dans Docker
  44. 44. Ne pas oublier les bases • OOP • Clean Code • Maîtrisez et appliquez les principes SOLID • Boy Scout Rule • Agile Modeling (Scott Ambler)
  45. 45. Se prémunir contre le Legacy Code à la base • Les développeurs doivent demander Quoi, Pourquoi et pour Qui avant de trouver le Comment. • Ce n’est pas aux analystes et utilisateurs de leur dire le Comment. • On veut savoir du client/PO qu’est-ce qu’ils veulent, pourquoi ils le veulent et pour qui cela va être utile.
  46. 46. Faire la conception en équipe • Les meilleures conceptions sont effectuées en équipe, et non par une seule personne. • La compréhension de l’architecture ainsi que son adoption est répandue dans toute l’équipe. • Pourquoi s’en passer ?
  47. 47. Ou du Mob Programming ! • Approche où l’équipe complète (client, analyste et PO aussi) travaille sur la même chose : – Au même endroit – En même temps – Sur le même ordinateur • Un peu similaire au pair programming
  48. 48. En résumé, nous avons vu… • C’est quoi du Legacy Code • Comment faire pour le tester • Comment affronter la résistance • Comment s’en prémunir au jour le jour
  49. 49. Alors, tester du du Legacy Code, • Met à l’épreuve et renforce nos habilités en: – Programmation Orientée-Objet – Conception & Architecture • Offre un challenge qui peut donc être instructif et amusant ! • Nous rend plus professionnel en bout de ligne.
  50. 50. Comment vous en sortez-vous avec le Legacy Code ?
  51. 51. Références 1/2 • Podcast Hanselminutes 2016-08-05 « Learning to love Legacy Code with Andrea Goulet from CorgiByte » – http://hanselminutes.com/539/learning-to-love-legacy-code- with-andrea-goulet-from-corgibytes • Patron « Test Specific Subclass » – http://xunitpatterns.com/Test-Specific%20Subclass.html • XKCD Goto – https://xkcd.com/292/
  52. 52. Autres références • Lectures suggérées • Beaucoup de connaissances et d’information sur le ‘net
  53. 53. Pour nous rejoindre • Karl Métivier – Courriel: kmetivier@facilite.com – LinkedIn: https://www.linkedin.com/in/karlmetivier/fr – Twitter: @karlmet – Blogue: https://excellenceagile.com/ • Yves St-Hilaire – Courriel: yves.sthilaire@gmail.com – LinkedIn: www.linkedin.com/in/yves-st-hilaire – Twitter: @sthiy

×