Mathieu Eveillard

Une architecture qui laisse des portes ouvertes

Une architecture qui laisse des portes ouvertes

The job of an architect is to build a structure that allows decisions to be delayed as long as possible

Cet aphorisme d’Uncle Bob ne constitue sans doute pas une définition de l’architecture logicielle, mais il en souligne une composante essentielle : la nécessité de laisser des portes ouvertes, de ne pas obérer le futur. En tout cas, le moins possible.

Voici cinq considérations architecturales qui illustrent ce propos.

Les bounded contexts

Les contextes, au sens du Domain-Driven Design, sont des zones de cohésion forte couplées faiblement les unes aux autres. Dit autrement, le bon contour des contextes est celui qui minimise le besoin de communication entre ces derniers. Les contextes sont donc des zones d’isolation : la facturation peut raisonnablement être considérée comme une chose distincte, presque indépendante de la vente. Tout est dans le « presque », parce qu’il y a bien sûr des échanges d’information (une vente déclenche l’émission d’une facture). Mais le fait d’opérer une distinction fonctionnelle entre ces deux contextes permet quand-même de dire qu’on pourra faire évoluer l’un en minimisant les conséquences sur l’autre et sur le système dans son ensemble. Les portes restent grandes ouvertes.

Le monolithe modulaire

Est-il encore besoin de le présenter en 2025 ? Le monolithe modulaire, c’est la voix de la raison : il vous offre à peu près tous les avantages de la modularité, à commencer par l’isolation dont nous parlions précédemment, sans les inconvénients propres au déploiement de microservices. Concrètement, les différents contextes, bien qu’isolés fonctionnellement, restent solidaires en termes de déploiement. Ils sont déployés d’un seul tenant, constituant un monolithe. Un monolithe bien rangé, et donc un monolithe qu’il sera toujours possible de faire évoluer ultérieurement vers des microservices, si besoin. Encore une fois, on laisse les portes ouvertes, on n’obère pas le futur.

L’architecture hexagonale

On se situe à présent à l’intérieur d’un contexte. Dès qu’il y a un peu de logique métier, il faut l’isoler. Non seulement parce que cela facilite le test, mais aussi parce que c’est la chose la plus stable dans le temps. Le cœur de métier d’une entreprise ne change pas tous les quatre matins, alors que les technologies, oui. On aimerait donc pouvoir écrire le code du domaine en faisant abstraction des contingences matérielles du monde extérieur (bases de données, APIs tierces etc.) Ça tombe bien, l’architecture hexagonale permet cela, au moyen de l’inversion de dépendances et de quelques mappers. On repousse ainsi le choix des technologies à une date ultérieure. Et quand viendra le moment de stocker de la donnée, on fera un choix bien plus éclairé, parce qu’on saura précisément de quelles requêtes on a besoin, en lecture comme en écriture.

Le pattern CQRS

Le pattern CQRS (Command Query Responsibility Segregation) consiste à faire diverger les modèles d’écriture et de lecture, permettant de les spécialiser. Autrement dit, d’avoir un très bon modèle d’écriture et un très bon modèle de lecture plutôt qu’un modèle « moyen » faisant mal les deux. On pourrait même avoir 1 modèle de lecture et N modèles d’écritures. Dit encore autrement, cela permet de laisser des portes ouvertes, de reporter des choix à demain. L’Event Sourcing, en particulier, est souvent utilisé comme modèle d’écriture. Sa responsabilité est de stocker fidèlement l’ensemble des événements, de manière infalsifiable (append only), peu importe comment l’information sera restituée ultérieurement. Les comptables connaissent bien cela.

SQL

Je vous l’accorde, SQL n’est pas une architecture, c’est un langage. Mais le raisonnement tient : parmi toutes les bases de données, les bases SQL ont ceci de particulier qu’elles ne sont pas spécialisées pour un type de requête. Elles permettent a priori toutes les requêtes, quitte à optimiser ultérieurement le chemin d’exécution de quelques-unes. La conception du modèle physique s’effectue d’ailleurs en considération des 8 formes normales, et ce modèle physique n’est modifié qu’à la marge pour optimiser les requêtes. Cela s’oppose à la famille NoSQL, où le choix d’une base se fait en fonction d’une requête bien précise : pour trouver toutes les relations de 3ème degré d’une personne (cas d’usage typique d’un réseau social), mieux vaut utiliser une base en graphe, Neo4j par exemple.

Conclusion

Cette considération d’Uncle Bob ne doit pas être prise au pied de la lettre : l’objectif n’est pas de faire des usines à gaz de généricité pour « le cas où », mais bien de faire des choses simples, qui évolueront facilement. Autrement dit, ne pas apporter la complexité aujourd’hui mais permettre qu’elle advienne demain.

← Tous les articles