Building Maintainable Software

Publié le 12/09/2016

En profitant d'une petite promo de -50% chez O'Reilly, je me suis offert l'ebook Building Maintainable Software, édition C-Tartine. Le livre propose de suivre une série de préceptes permettant d'améliorer la qualité du code produit. Bien que le contenu ressemble parfois plus à une grosse page marketing pour le Software Improvment Group, il reste intéressant et vaut le coup d'être lu. Deux petits problèmes par contre:

  1. On part parfois d'un cas concret (qui ressemble parfois à ce que j'ai pu commettre de code foireux), en prenant une méthode dans laquelle on trouve plusieurs concepts différents (appel à la db, cast vers une classe type DTO, validation d'input). Juste après, on passe directement sur un autre exemple, beaucoup plus simple à résoudre.
  2. J'ai l'impression que cela parle plus de théorie, sans proposer de solution automatique, ce qui rejoint un peu ce que je disais au niveau marketing: "si vous voulez vous améliorer, signez chez nous!".

Les principaux conseils sont les suivants (pour les d√©tails, il vous faudra acheter le bouquin ūüėõ):

Au niveau des méthodes

  • 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, c'est dur √† tenir, mais faisable.
  • Conserver une complexit√© de McCabe en dessous de 5, c'est-√†-dire avec quatre branches au maximum. A nouveau, si on a une m√©thode avec 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 qu'une seule fois: √©vitez les duplications, copie, etc., c'est juste mal: imaginez qu'un bug soit d√©couvert dans une fonction; il devra alors √™tre corrig√© dans toutes les fonctions qui auront √©t√© copi√©es/coll√©es. C'est aussi une forme de r√©gression.
  • Conservez de petites interfaces. Quatre param√®tres, pas plus. Au besoin, refactorisez certains param√®tres dans une classe, plus facile √† tester.

Au niveau des classes

  • Privil√©giez un couplage faible entre vos classes. Ceci n'est pas toujours possible, mais dans la mesure du possible, √©clatez vos classes en fonction de leur domaine de comp√©tences. L'impl√©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 d'ajouter une couche d'abstraction. La classe appellante n'aura alors que les m√©thodes offertes par l'interface comme points d'entr√©e.

Au niveau des composants

  • Tout comme pour les classes, il faut conserver un couplage faible au niveau des composants √©galement. Une mani√®re d'arriver √† ce r√©sultat est de conserver un nombre de points d'entr√©e restreint, et d'√©viter qu'on ne puisse contacter trop facilement des couches s√©par√©es de l'architecture. Pour une architecture n-tiers par exemple, la couche d'abstraction √† la base de donn√©es ne peut √™tre connue que des services; sans cela, au bout de quelques semaines, n'importe quelle couche de pr√©sentation risque de contacter directement la base de donn√©es, "juste parce qu'elle en a la possibilit√©". Vous pourrez √©galement passer par des interfaces, afin de r√©duire le nombre de points d'entr√©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 d'impl√©mentation complet d'une classe FtpFileTransfer ou SshFileTransfer).
  • Conserver un bon balancement au niveau des composants: √©vitez qu'un composant A ne soit un √©norme mastodonte, alors que le composant juste √† c√īt√© n'est capable que d'une action. De cette mani√®re, les nouvelles fonctionnalit√©s seront mieux r√©parties parmi les diff√©rents syst√®mes, et les responsabilit√©s plus faciles √† g√©rer. Un conseil est d'avoir un nombre de composants compris entre 6 et 12 (id√©alement, 12), et que ces composants soit approximativement de m√™me taille.

Et de manière plus générale

  • Conserver une densit√© de code faible: il n'est √©videmment pas possible d'impl√©menter n'importe quelle nouvelle fonctionnalit√© en moins de 20 lignes de code; l'id√©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 d'int√©gration continue d√®s le d√©but du projet et v√©rifier par des outils les points ci-dessus.

Ceci est sans doute un des points les plus ennuyants de ce livre: il n'y a finalement que très peu d'exemples concrets, notamment pour la mise en place d'un tel environnement. Ok, ça parle de Jenkins du début à la fin, mais plus comme un exemple à suivre (ou parfois à ne pas suivre) que comme un outil à utiliser. De manière plus générale, j'ai l'impression que le code .Net reste extrêmement fermé à des outils open source permettant d'augmenter la qualité du code. Il existe des linters pratiquement pour tous les langages, mais si vous voulez quelque chose de fonctionnel pour C#, il va falloir passer par la caisse. Une stratégie MS classique en sommme: "on vous offre les outils pour pas grand chose, et pour aller plus loin, vous douillez".

Pour aller plus loin

En regardant un peu à droite-à gauche, pour du code .Net, les outils suivants ont l'air sympa, comme:

  • SonarLint (en cli, int√©gr√© dans un IDE ou en mode CI) (dont je ne peux plus me passer :-) )
  • StyleCop
  • Refactoring Essentials
  • CodeMaid, pour un code propre et soyeux. En zieutant la description, on trouve que CodeMaid is an open source Visual Studio extension to cleanup, dig through and simplify our C#, C++, F#, VB, PHP, JSON, XAML, XML, ASP, HTML, CSS, LESS, SCSS, JavaScript and TypeScript coding.