Design Patterns : 30 ans déjà !

Publié le Mis à jour le Par

Cette année 2024 sera le 30e anniversaire de la publication du livre « Design Patterns: Elements of Reusable Object-Oriented Software », le fameux livre du Gof, c’est-à-dire du Gang of Four, désignant ses quatre auteurs : Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides.

Impossible de passer à côté, même encore aujourd’hui, les Design Patterns font partie de la culture fondamentale en orienté objet. Pourtant, les choses ont beaucoup évolué depuis 30 ans et il serait légitime de se demander comment une « telle relique » peut encore avoir une quelconque importance de nos jours.

On peut trouver d’innombrables références (rééditions, articles, billets de blogs…) traitant de ces patterns, malheureusement pas toujours très claires et parfois pas du tout à la hauteur de l’original. L’ouvrage peut être ressenti comme ardu et pour cause, il ne s’adresse pas aux concepteurs objets débutants. Cela est mentionné dès la première phrase de la préface : « This book isn’t an introduction to object-oriented technology or design » (oui, je lis les préfaces des ouvrages, on y trouve souvent plein de bonnes informations pour comprendre la motivation et le contexte qui a conduit à leur écriture 🙂).

Ce premier paragraphe nous dit qu’il faut à la fois une compétence raisonnable dans au moins un langage de programmation orientée objet et une certaine expérience en conception orientée objet. Se lancer dans sa lecture (et la compléter) requiert un investissement non négligeable, pas mal d’efforts et de persévérance. Là encore, dans la préface, les auteurs nous lancent un petit mot d’avertissement et d’encouragement avec un « Ce n’est pas grave si vous ne comprenez pas tout ce livre entièrement à la première lecture, nous ne l’avons pas non plus compris à la première écriture ! ».

Ils nous rappellent (et le titre aussi) que c’est un catalogue. Ce n’est pas fait pour être lu une fois avant de le mettre sur une étagère. C’est fait pour s’y référer à de multiples reprises, c’est fait pour être réutilisé, c’est fait pour modifier profondément notre manière de concevoir objet.

Avec tous ces avertissements, on comprend qu’il reste malgré tout assez difficile pour de nombreuses personnes de répondre à la question classique en entretien : « Citez quelques Design Patterns, autres que Singleton, et expliquez-les ».

Pourtant, ces 23 patterns historiques ne sont qu’une première liste. Les auteurs, toujours dans la préface, nous indiquent qu’ils ne considèrent pas cette collection comme complète ni statique. Il s’agit plutôt d’un « enregistrement de nos réflexions sur la conception » écrivent-ils, toujours dans la préface. Dans les faits, plusieurs autres catalogues de patterns, et pas seulement de Design Patterns, ont effectivement vu le jour depuis.

Mais pour bien répondre à la question initiale (« est-ce que ça a encore de l’importance aujourd’hui ? »), il faut se replacer dans le contexte et bien comprendre les origines de tout cela.

Le livre a eu une longue gestation (ça aussi c’est indiqué dans la préface) car les travaux ont commencé dès 1990. A cette époque, Java n’existe pas encore. Les exemples décrits sont en C++ et Smalltalk, les deux langages phares de l’orienté objet et on est encore au début de la déferlante, cette époque où tout nouveau système devait avoir les deux OO dans son nom pour pouvoir obtenir un peu d’attention. UML n’existe pas non plus, les diagrammes de classes sont en OMT et lorsque le livre sera publié en 1994, le web n’en sera qu’à sa première année d’existence publique. Plus important encore, les principes objets dont les fameux principes SOLID ne sont pas encore formulés.

Pour comprendre la motivation et la manière dont ces Design Patterns ont été catalogués, il faut, cette fois, aller lire le premier chapitre d’introduction, « Qu’est-ce qu’un Design Pattern ? » et se demander qui est ce Christopher Alexander qui aurait dit (ou plutôt écrit) : « Chaque modèle décrit un problème qui se produit encore et encore dans notre environnement, puis décrit le cœur de la solution à ce problème, de telle manière que vous pouvez utiliser cette solution un million de fois, sans jamais faire deux fois la même chose. ». Avec quelques recherches internet, on découvre alors que la notion de pattern et cette idée de catalogue vient tout droit d’un autre best seller encore plus ancien : “A pattern language”, paru en… 1977. Le titre complet est « A Pattern Language: Towns, Buildings, Construction » (notez que même dans le titre, on retrouve des similitudes). Un best seller sur l’architecture et l’urbanisme, la « vraie », celle des bâtiments et des villes. Ce livre était apparemment très en vogue dans les milieux de la conception et de l’ingénierie dans les années 80. Il ne recense pas moins de 253 patterns, censés constituer une langue pour que tout le monde, et pas seulement les professionnels de l’architecture, ait une méthode de travail pour améliorer son quartier avec ses voisins ou conçoive sa propre maison, bureau ou bâtiment. Dit comme ça, cela semble plutôt très abstrait (encore une similitude). J’ai pendant longtemps cité un exemple dont je n’avais plus la source exacte et qui est bien un des 253 patterns : le pattern 180 : Window Place. Ce pattern stipule qu’il est nécessaire (et ce n’est pas simplement un luxe) d’avoir un endroit confortable près d’une grande fenêtre dans ses pièces. Dans le cas contraire, une tension, éventuellement minime mais inévitable, arrive entre le désir d’être installé confortablement et celui d’avoir de la lumière.

On le comprend ici, le pattern décrit un problème et une « solution » qu’on peut appliquer un million de fois sans reproduire exactement la même chose. On trouve de nombreuses images et illustrations de telles Window Places sur le web et il est intéressant de remarquer qu’elles suscitent généralement une certaine envie d’aller s’y prélasser avec un bon bouquin.

Voilà donc l’idée générale qui a animé le GoF dès 1990 : observer de nombreux projets informatiques, repérer une liste de problèmes récurrents et décrire l’essence des solutions élégantes et remarquables auxquelles les concepteurs expérimentés ont abouti, indépendamment, après plusieurs essais (les patterns ont été sélectionnés selon le critère que l’approche instinctive utilisée par un concepteur débutant pour résoudre le problème n’est généralement pas une solution flexible et réutilisable).

Notez ici que la caractéristique importante recherchée à l’époque était d’obtenir une solution améliorant la flexibilité et la réutilisabilité du code. La fameuse réutilisabilité tant vendue par le marketing pour promouvoir l’orienté objet. Les choses ont considérablement changé depuis. Le temps est loin où le développement de frameworks maison était la règle. Aujourd’hui les patterns sont embarqués directement dans les langages (penser à Iterator,  Observer, Listener dans Java) et dans les frameworks (rechercher simplement les classes et interfaces dans Spring et dans Java contenant des mots comme Factory, Adapter, Bridge, Strategy, Builder, Chain, Command, Composite, Decorator, Facade, Prototype, Proxy, Singleton, State, Template, Visitor… presque tous les 23 Design Patterns du GoF sont bien présents d’une manière ou d’une autre et c’est la preuve de leur intemporalité mise en avant par Alexander et évidemment recherchée par les quatre compères du GoF.

Ces problèmes recensés sont donc toujours d’actualité et il est important de les connaître car c’est là toute l’utilité des patterns : reconnaître les problèmes rencontrés pour trouver l’essence de la bonne solution ou au moins une réflexion sur les solutions possibles sans passer du temps à la réinventer, d’une mauvaise manière. Et pour cela, il faut avoir au moins parcouru une première fois le catalogue, à défaut d’avoir tout compris.

Pour nous aider, les auteurs les ont regroupés historiquement dans 3 catégories : Creational, Structural et Behavioral Patterns.

J’ai tendance à expliquer ces trois catégories en les rapprochant des deux principes fondamentaux de l’orienté objet et de la conception en général : le faible couplage et la séparation des préoccupations.

Les Creational Patterns traitent du premier souci important qui est laissé quasiment sous silence dans les notations telles qu’UML. Lorsqu’on parle d’objets ou que l’on fait un diagramme, on réfléchit toujours à assembler des objets ou à les faire communiquer mais jamais on ne parle de leur création. Les seuls diagrammes qui traitent de la création sont les diagrammes de séquence avec les messages de création. D’une part, la création d’instance est extrêmement spécifique au langage (un message de classe en Smalltalk, un opérateur new dans les langages inspirés de C) mais surtout cet opérateur introduit un couplage très fort dans le code. Derrière un new, on ne peut indiquer qu’une classe réelle à instancier. Il n’est donc pas étonnant que les patterns créateurs décrivent cinq manières standards de déléguer, interdire, déplacer, transformer le new : Singleton (interdire), Factory Method (isoler le new dans une méthode pour permettre de la redéfinir dans une sous-classe), Abstract Factory (déplacer le new dans une autre classe), 

Builder (décomposer le new d’un objet complexe pour permettre de scripter sa construction) et Prototype (remplacer le new par une copie d’une instance existante). Il est à noter que d’autres patterns ont été recensés depuis pour ce sujet (Registry, Dependency Injection…) 

Les Structural Patterns traitent d’un tout autre problème : la séparation des préoccupations. La conception objet nous incite à faire des objets simples et mono-préoccupation. Un objet qui fait trop de choses ou qui a trop d’attributs, manque de cohésion et sera difficile à maintenir et à faire évoluer. La question devient donc « Comment assembler ces petits objets spécialisés pour construire des systèmes complexes ». Je résume d’habitude cela avec la question suivante : « Comment construire des cathédrales avec de simples pierres taillées, du mortier et des troncs d’arbres ? ». Il faut assembler tout cela précisément pour résoudre de nombreux problèmes de tensions et d’harmonie pour espérer construire une cathédrale qui tient debout. Les patterns structuraux nous aident à adapter, transformer, assembler.

Les Behavioral Patterns traitent presque du même problème mais du point de vue des traitements. Comment faire des traitements complexes si les objets sont mono-préoccupation et ne font que des choses simples ? Il faut diviser les tâches complexes, déléguer, coordonner le flux d’exécution. C’est le rôle des patterns comportementaux.

Tous ces patterns font partie de la culture de l’orienté objet. Ils permettent de modifier notre manière de penser, de concevoir, de raisonner, de communiquer. Le multi-paradigme tend à se généraliser depuis un bon moment. Java a suivi la tendance en introduisant le paradigme fonctionnel depuis Java 8 et est en train d’ajouter la programmation orientée data. Certes, ce n’était pas le sujet ni la tendance il y a 30 ans. Chaque paradigme arrive avec ses propres patterns et il est important de comprendre que la connaissance, même superficielle, des Design Patterns du Gof est plus le début d’un changement d’état d’esprit qu’une recette à connaître et à appliquer dans une situation donnée. Donc, oui, il est important de connaître ces patterns, au moins les problèmes qu’ils solutionnent, et d’essayer de les comprendre. La section Guide to Readers suggère de commencer par Abstract Factory, Adapter, Composite, Decorator, Factory Method, Observer, Strategy et Template Method.

Alors, si vous n’avez pas encore fait le premier pas, trouvez une bonne Window Place et accrochez-vous, ça vaut vraiment le coup. Bon courage !