gwift-book/source/part-1-workspace/maintainable-applications/maintainable-applications.adoc

4.5 KiB
Raw Blame History

Bonnes pratiques

The primary cost of maintenance is in spelunking and risk
-- Robert C. Martin, Clean Architecture, page 139

Pour cette section, nous nous basons sur un résumé de lebook Building Maintenable Software disponible chez OReilly.

Ce livre répartit un ensemble de conseils parmi quatre niveaux de composants:

  • Les méthodes et fonctions

  • Les classes

  • Les composants

  • Et des conseils plus généraux.

Ces conseils sont valables pour nimporte quel langage.

Au niveau des méthodes et fonctions

  • Gardez vos méthodes/fonctions courtes. Pas plus de 15 lignes, en comptant les commentaires. Des exceptions sont possibles, mais dans une certaine mesure uniquement (pas plus de 6.9% de plus de 60 lignes; pas plus de 22.3% de plus de 30 lignes, au plus 43.7% de plus de 15 lignes et au moins 56.3% en dessous de 15 lignes). Oui, cest dur à tenir, mais faisable.

  • Conserver une complexité de McCabe en dessous de 5, cest-à-dire avec quatre branches au maximum. A nouveau, si une méthode présente une complexité cyclomatique de 15, la séparer en 3 fonctions avec une complexité de 5 conservera globalement le nombre 15, mais rendra le code de chacune de ces méthodes plus lisible, plus maintenable.

  • Nécrivez votre code quune seule fois: évitez les duplications, copie, etc., cest juste mal: imaginez quun bug soit découvert dans une fonction; il devra alors être corrigé dans toutes les fonctions qui auront été copiées/collées. Cest aussi une forme de régression.

  • Conservez de petites interfaces. Quatre paramètres, pas plus. Au besoin, refactorisez certains paramètres dans une classe, qui sera plus facile à tester.

Au niveau des classes

  • Privilégiez un couplage faible entre vos classes. Ceci nest pas toujours possible, mais dans la mesure du possible, éclatez vos classes en fonction de leur domaine de compétences respectif. Limplémentation du service UserNotificationsService ne doit pas forcément se trouver embarqué dans une classe UserService. De même, pensez à passer par une interface (commune à plusieurs classes), afin dajouter une couche dabstraction. La classe appellante naura alors que les méthodes offertes par linterface comme points dentrée.

Au niveau des composants

  • Tout comme pour les classes, il faut conserver un couplage faible au niveau des composants également. Une manière darriver à ce résultat est de conserver un nombre de points dentrée restreint, et déviter quil ne soit possible de contacter trop facilement des couches séparées de larchitecture. Pour une architecture n-tiers par exemple, la couche dabstraction à la base de données ne peut être connue que des services; sans cela, au bout de quelques semaines, nimporte quelle couche de présentation risque de contacter directement la base de données, "juste parce quelle en a la possibilité". Vous pourriez également passer par des interfaces, afin de réduire le nombre de points dentrée connus par un composant externe (qui ne connaîtra par exemple que IFileTransfer avec ses méthodes put et get, et non pas les détails dimplémentation complet dune classe FtpFileTransfer ou SshFileTransfer).

  • Conserver un bon balancement au niveau des composants: évitez quun composant A ne soit un énorme mastodonte, alors que le composant juste à côté ne soit capable que dune action. De cette manière, les nouvelles fonctionnalités seront mieux réparties parmi les différents systèmes, et les responsabilités seront plus faciles à gérer. Un conseil est davoir un nombre de composants compris entre 6 et 12 (idéalement, 12), et que chacun de ces composants soit approximativement de même taille.

De manière plus générale

  • Conserver une densité de code faible: il nest évidemment pas possible dimplémenter nimporte quelle nouvelle fonctionnalité en moins de 20 lignes de code; lidée ici est que la réécriture du projet ne prenne pas plus de 20 hommes/mois. Pour cela, il faut (activement) passer du temps à réduire la taille du code existant: soit en faisant du refactoring (intensif?), soit en utilisant des librairies existantes, soit en explosant un système existant en plusieurs sous-systèmes communiquant entre eux. Mais surtout, en évitant de copier/coller bêtement du code existant.

  • Automatiser les tests, ajouter un environnement dintégration continue dès le début du projet et vérifier par des outils les points ci-dessus.