Comment concevoir son architecture microservice ?

L'architecture microservice

L'architecture microservice est un type d'architecture logicielle émergente qui tente de répondre aux problématiques des applications dites "monolithiques" Celles-ci concernent le développement fastidieux, le manque de flexibilité, les difficultés de déploiement ou encore l'absence de scalabilité. Le principe des microservices est simple : on décompose l'application en plusieurs applications plus petites et plus autonomes qui gravitent autour d'un Business Domain. L'intérêt des microservices est de se recentrer sur le métier et les problèmes fonctionnels que l'application tente de résoudre.

 

Caractéristiques d'un microservice

Les microservices ont l'avantage d'être plus petits et donc plus flexibles en termes de développement, de déploiement et de maintenabilité. Chaque microservice se doit de répondre à un aspect métier que l'on appelle "Contexte Délimité" ("Boundary Context" en anglais). L'enjeu de l'architecture microservice est de s'assurer que la délimitation en domaine fonctionnel est suffisamment pertinente et cohérente pour assurer des microservices aussi petits que possible mais suffisamment autonomes.

La taille des microservices est en fait le piège de cette architecture. Il paraît évident que plus les microservices sont petits, plus il sera facile de les gérer. Cependant, on peut s'apercevoir très vite que certains microservices communiquent beaucoup entre eux car ils ont souvent, voir systématiquement, besoin des informations de l'autre pour fonctionner. Si un tel comportement est observé, cela veut dire que deux microservices ne doivent former qu'un.

L'analyse architecturale préalable d'une solution en microservice doit aboutir à la séparation du Business Model initial en plusieurs contextes délimités, les plus petits et autonomes possible. Dans ce contexte, la cohésion doit être le maître mot. En effet, chaque contexte doit être suffisamment cohérent avec lui-même afin d'éviter le surplus de communication avec les autres.

Le concept Domain Driven Design

Le concept Domain Driven Design (appelé DDD) a été introduit pour la première fois par Eric Evans en 2004 dans son livre "Domain-Drive Design: Tackling Complexity in the Heart of Software". Aujourd'hui, cette oeuvre est répandue mondialement et je vous conseille fortement sa lecture intéressante.

Le DDD est une méthode mettant en œuvre l'ensemble des concepts cités ci-dessus. Lors de la phase d'analyse de l'architecture du projet, le DDD permet le découpage en contexte délimités en identifiant les sous-domaines, qui deviennent par la suite les microservices.

Lors de la conception des microservices, le code est souvent divisé en couches. Cette division en couches est à la fois conceptuelle et technique. Cela permet aux développeurs de mieux reconnaître les différentes parties de l'application en séparant d'une manière bien précise les entités qui composent le code. Ces couches sont des abstractions logiques destinées à une meilleure compréhension du code.

 

Voici comment nous pourrions définir les différentes parties représentées ci-dessus :

  • ● Application : contient la partie opérationnelle du microservice en exposant le métier et le Domain model vers l'extérieur. Cette couche contient ainsi tout le paramétrage et le code nécessaire afin que le microservice puisse exister et fonctionner dans un environnement qui est le sien. Cette partie ne connaît pas le business, et s'occupe simplement de coordonner les interactions entre les autres couches et/ou le monde extérieur ;
  • ● Domain model : représente les concepts propres au business que le microservice peut traiter dans le système d'information. L'état propre du service est représenté dans les entités de cette couche, et représente clairement le cœur du business du microservice ;
  • ● Infrastructure : les données sont stockées en base de données (ou autre).

Les dépendances entre les différentes couches sont importantes et ne doivent pas se faire de manière aléatoire. Dans un premier temps, la couche Domain model ne doit pas avoir de dépendance avec les autres couches. La librairie doit rester neutre, elle est exploitée dans les autres librairies en tant que dépendance. Ensuite, la couche Infrastructure n'a qu'une seule dépendance vers le Domain model. Cela paraît évident puisque c'est elle qui est responsable de la persistance des données. Les modèles permettent de symboliser les entités de la base de données. Enfin, la couche Application possède des dépendances vers les autres parties car :

  • Elle a besoin des services disponibles dans la partie Infrastructure afin d'effectuer les actions nécessaires pour traiter les requêtes entrantes et répondre aux besoins métiers ;
  • Elle a besoin des modèles du Domain model pour faire transiter / créer / mettre à jour les données ;

La couche Application peut être considérée comme l'orchestratrice des autres couches.

L'importance des entités

 

La notion de Domain model étant très importante, il est indispensable de bien découper ses contextes afin d'avoir une cohérence dans les entités. Une entité, si son identifiant est le même au travers de plusieurs microservices, peut être partagée dans tout le système, mais pas forcément sous le même modèle. Par exemple, une entité Acheteur et une identité Facture vont dépendre de 2 microservices créés spécialement pour permettre de les gérer tous deux de manière indépendante. Le microservice Acheteur va reposer sur un modèle très complet de l'acheteur. Cependant, le microservice Facture n'a pas besoin d'un modèle aussi complet : l'identifiant de l'acheteur suffit, mais d'autres propriétés peuvent intervenir en cas de besoin. Le contexte de chaque microservice influe sur son Domain model.

Une autre règle est très importante en DDD :

Chaque entité du Domain model doit contenir les données et les comportements qui lui sont propre selon son contexte.

Dans un premier temps, cela veut dire qu'on ne créé pas de modèle dit DTO (Data Transfer Objects), mais des modèles POCO (Plain Old CLR Object) qui contiennent du comportement. Selon Martin Fowler et Eric Evans, précurseurs du DDD, utiliser des DTO avec classes de services donnerait des anti-patterns comme du code spaghetti ou des scripts transactionnels. On parle alors de domaine anémique. Pour des microservices simples (type CRUD), cela pourrait suffir mais dans le cadre d'un système complexe avec plusieurs microservices, la bonne pratique est d'utiliser des modèles POCO, c’est-à-dire des modèles qui contiennent les méthodes permettant de gérer ses données (ajout, modification, etc).

Martin Fowler explique clairement cette différence dans plusieurs de ses articles :

https://martinfowler.com/bliki/AnemicDomainModel.html et https://martinfowler.com/eaaCatalog/domainModel.html

De ce fait, au sens de Martin Fowler et Eric Evans, les entités doivent ressembler à ceci :

Il est cependant tout à fait possible d'avoir des entités sans méthodes. Cela peut arriver dans le cas d'entités enfants très simples où le microservice n'a pas besoin de beaucoup de complexité.
Plusieurs débats tournent autour du modèle anémique et beaucoup de gens pensent que c'est un anti-pattern. Au final, cela dépend vraiment du contexte de votre projet et du microservice. Pour un microservice très simple, un modèle anémique est certainement ce qu'il vous faut. Néanmoins, plus la complexité va s'agrandir, plus il est judicieux de construire des modèles de type POCO afin de regrouper au même endroit les règles métiers. Un modèle riche ne sera qu'un plus pour la conception d'un système avec DDD et permettra aux différents microservices de garder leur pérennité sur le long terme.


L'approche DDD est tournée vers le domaine métier, et sa représentation dans le code tend à former un système d'information répondant aux problèmes clients de manière optimale. Les notions de contexte délimités, de couches d'abstraction, d'entité POCO et de modèle anémique constituent les facettes de cette méthodologie qu'il faut appréhender lorsqu'une architecture microservice est adoptée.

 

Christophe Gigax

Technical Leader Microsoft et Angular  - MVP Visual Studio & Development Technologies