À travers mes quelques années d'expérience en tant que développeur junior, j'ai fait d'innombrables erreurs. Des erreurs graves, des erreurs bénignes, des erreurs critiques corrigées avant même que quiconque s'en rende compte. Mon constat est unanime: j'ai beaucoup appris et ces erreurs ont forgé le développeur que je suis aujourd'hui. Confronté à mes fautes et à mes raisonnements défectueux ou déficients, je me suis amélioré. L'expérience est la somme de nos réussites et de nos échecs, combinée à nos réflexions face à ceux-ci. Et la conclusion la plus frappante de ma carrière est que la racine de presque tous les maux est auto-infligée et peut être évitée. Il s'agit de l'over-design.

Je vais reprendre l'expression de mon collègue et patron Jean-François: "tu te masturbes intellectuellement!". Il n'a certainement pas tort. Mais pourquoi ce recours à la complexité?

Mon ego

Mon ego a certainement dégonflé au cour des dernières années. Mais reste qu'il a tout de même besoin d'être flatté de temps à autre. Rien de tel pour se remonter le moral que d'architecturer une solution qui résout à la fois la guerre, la famine et la maladie sur Terre comme sur Mars. Le design ultime, se dit-on. Les plus grosses têtes iront peut-être même jusqu'à dire que leur solution est la prochaine révolution informatique. La réalité, c'est que l'on crée un monstre dans la plupart des cas. Une fois ce monstre crée, ce n'est qu'une question de temps avant que ça ne dérape et que la productivité de votre projet soit annihilée. Combien de fois cela vous est-il arrivé? Combien de fois le faudra-t-il avant que votre approche change? Pour moi, ce fut au moins une fois de trop.

Un design trop compliqué apporte de nombreux défis dont l'on pourrait se passer. Ce métier est déjà assez complexe pour en rajouter une couche. Je suis aussi un grand amateur du principe que le code n'appartient à personne. Lorsque l'on over-design, on imprime bien souvent son nom sur une section entière de l'application. Si on peut savoir qui a implémenté une section du code selon son style, c'est que vous avez des membres dans votre équipe qui tentent de s'approprier une section du code. Cela fait en sorte que les autres développeurs auront peur de faire des modifications dans ce code. Rien ne vaut un module facilement compréhensible et accessible à tous, car quand c'est simple, c'est facile à modifier.

Tu te masturbes intellectuellement!

Il ne sert à rien de prévoir une solution à un éventuel problème futur dont nous n'avons même pas encore de gabarit ou d'information tangible. Certains patrons architecturaux adressent d'ailleurs ce problème avec une simplicité étonnante! Je pense surtout au patron KISS, qui signifie Keep It Simple, Stupid!, ou au fameux mantra You ain't gonna need it. La masturbation intellectuelle ne vous rendra probablement pas sourd, mais elle vous rendra certainement la vie compliquée. Gardez votre ego sous contrôle, vous ne le regretterez pas.

Comment s'en sortir?

Maintenant qu'il est évident que l'on ne veut pas de designs inutilement compliqués, comment s'en sort-on? Je vous présente certains conseils que j'aurais souhaité avoir il y a de cela quelques mois à peine; Faites-en ce que vous voulez. Il y a de nombreuses façons de faire, et puisque que chaque projet est différent, choisissez les conseils qui vous conviennent le mieux. Je ne vais qu’effleurer ces conseils, car chacun d'entre eux mérite un article à lui seul.

Éviter les patrons inutiles

Il n'y a probablement rien de plus inutile que d'implémenter un design pattern pour rien. Les design patterns sont effectivement bien utiles et fournissent une solution optimale à un problème bien connu, mais à force de mal utiliser ces concepts, on finit par mélanger tout le monde. Et surtout, on finit par créer nettement plus de classes que nécessaire. Faire le lien entre ces concepts peut devenir rapidement fastidieux quand on ne voit pas le motif d'avoir utilisé un patron en particulier.

Privilégier la composition

N'utilisez pas l'héritage à outrance: Privilégiez la composition. L'héritage est un super modèle de programmation, mais bien souvent, il est superflu et devient lourd. Il devient rapidement difficile de retracer à quel niveau appartient une responsabilité. Avec de la composition, ça devient soudainement beaucoup plus facile. Cela provient généralement du fait qu'une classe devrait ne satisfaire qu'une seule responsabilité, pas plusieurs. Avec une solide nomenclature, retrouver une classe devient un jeu d'enfant, et modifier son comportement devient plus facile. La règle d'or que j'applique est la suivante: Au delà d'un niveau d'héritage, je n'utilise probablement pas la bonne approche. Par exemple, il se pourrait que j'aie une classe de base abstraite et plusieurs implémentations. Par contre, si ces implémentations sont dérivées, ce n'est pas normal. C'est un signal que je dois généralement revoir mon approche initiale.

Au delà d'un niveau d'héritage, je n'utilise probablement pas la bonne approche.

Je conseillerais également d'utiliser l'injection de dépendances, que ce soit ou non à l'aide d'un Service locator tel que Autofac, Castle Windsor ou Ninject si vous utilisez .NET1. L'approche favorise la séparation des responsabilités et la composition à l'héritage. Il est bien entendu toujours possible de se tromper, mais avec de bons tests unitaires, ça devrait vous donner une bonne idée de si vous vous alignez dans la bonne direction.

Planifier son implémentation

Au lieu de commencer à programmer immédiatement, il serait peut-être sage de planifier son implémentation et de mettre ses idées à l'épreuve. N'oubliez pas que les autres membres de l'équipe devront pouvoir travailler dans votre code sans que votre nom y soit imprimé en gras. En leur parlant de vos idées, vous vous forcez à expliquer les motifs qui vous poussent vers une design plutôt qu'un autre. Cela pourrait être vu comme un manque d'autonomie, mais je ne crois pas que ce soit le cas. C'est plutôt de faire preuve d'un fin sens de l'équipe. Cela garde vos collègues au courant de ce qui se passe et vous permet de vous alimenter des expériences positives ou négatives d'autres développeurs. Combien de fois m'ais-je impliqué dans une discussion de design au travail pour finalement mettre en garde un collègue contre l'utilisation d'une technique ou d'une solution, ou pour recevoir une des ces mises en garde? Je crois que l'on ne peut s'améliorer que si l'on confronte ses idées à celle des autres.

Travailler avec des seniors

L'expérience est, comme je l'ai dit plus haut, le fait de s'être pété la gueule à quelques reprises. Un senior est quelqu'un qui s'est planté à répétition et qui a appris de chacune de ses erreurs. Ce sont des gens essentiels dans l'industrie du développement informatique, car le nombre de nouveaux développeurs double aux cinq ans. C'est une croissance énorme, et les seniors agissent en tant que gardiens de la connaissance et de ce qui a été tenté ou réalisé par le passé. Trouvez un senior en qui vous avez confiance, et soumettez-lui vos idées. Vous reviendrez parfois démoli, mais la reconstruction de vos idées promet de mener à quelque chose d'encore mieux.

Appliquez les patterns SOLID

Je reviendrai plus en détail sur ces patrons dans un autre article, car ils sont d'une importance capitale pour tout développeur qui souhaite s'améliorer. Le mot SOLID est en fait un acronyme pour désigner des concepts clefs desquels je retiens surtout les deux premiers et le dernier, bien qu'ils soient tous importants.

  • Single Responsability | Responsabilité unique
  • Open-Closed principle | Principe ouvert-fermé
  • Liskov substitution | Substitution de Liskov
  • Interface segregation principle | Principe de ségrégation des interfaces
  • Dependancy injection principle | Principe d'injection des dépendances

L'ingénieur et conférencier Robert C. Martin (Uncle Bob) a écrit de très bons livres et a donné des nombreuses conférences sur ces principes. Je vous invite fortement à vous informer sur ceux-ci dans le monde magique des internets.

Je pourrais encore vous donner des tonnes et des tonnes de conseils sur comment éviter de se masturber intellectuellement, mais je pense que le plus difficile reste à faire si vous vous sentez concernés par cet article. Il faut que vous puissiez vous rendre compte que vous allez trop loin et que vous caressez votre ego. À partir de ce moment, vous pourrez décider de prendre un autre chemin et d'améliorer les choses. La complexité n'est pas mal en soit. Certains problèmes complexes ne trouvent qu'une réponse complexe. Ça devient malsain lorsqu'une solution facile aurait tout aussi bien pu faire le travail sans entraver la productivité et la compréhension.

Lire ce blogue sur mes erreurs est facile, mais vous, qu'avez-vous réalisé dans les derniers mois ou années? Parlez-m'en dans les commentaires. Je suis curieux d'en entendre plus.


1. Le concept de Service locator existe dans presque tous les languages. Ce n'est pas un concept unique au .NET. On peut facilement le retrouver en Java, Javascript, C++, etc.