L'architecture hexagonale
Hélène Lessieux
Posted on June 29, 2022
Ce nom vous dit probablement quelque chose car on en entend de plus en plus parler. Pourtant son origine n’est pas si récente. L’architecture hexagonale ou encore Ports & Adapters Pattern date de 2005, quand Alistair Cockburn en décrit les contours.
Habituellement, dans nos projets Spring Boot nous utilisons l’architecture n tiers mais ce n’est pourtant pas la seule manière de construire une application. Pour certains, l’architecture hexagonale peut même apparaître comme plus cohérente car elle remet la logique métier au cœur de nos développements.
Le but principal de cette architecture étant de bien dissocier les besoins métier des algorithmes, on peut tout à fait l’utiliser pour des langages back mais aussi front. Ici, je vais surtout parler de sa mise en place dans un framework Spring Boot mais cela marche également pour les autres frameworks.
Avant de vous en présenter les avantages, j’aimerais vous montrer globalement à quoi cela ressemble.
L’architecture n tiers que l’on connaît bien :
Un exemple! Un exemple! Un exemple!
Ok 😄 Prenons un exemple concret. Nous souhaitons réaliser une application permettant de créer des événements (sportifs, culturels, caritatifs, etc…). L’idéal serait évidemment de pouvoir ensuite les rechercher à tout moment, les filtrer par ville, type, prix, etc…de pouvoir les modifier, les supprimer, etc…bref une application complète 🙂 Mais là pour notre exemple, on va simplement s’intéresser à la création d’un événement.
Et on n’oubliera pas d’implémenter deux règles métier pour mettre en avant la logique métier de notre projet. Ici, je vais par exemple dire que si un événement a lieu dans le passé, il ne sera pas créé. Et de même si un événement caritatif est créé avec un prix de participation à l’événement alors il ne sera pas créé.
Dans notre Domain, on y trouve l’ensemble des objets dont a besoin notre métier. Ici, l’objet Event.
Dans notre User side port, on va y trouver un certain nombre d’interfaces (idéalement une par domain visé) qui vont lister l’ensemble des besoins métier. Ici, on aura une interface ICreateEvent dans laquelle on aura la méthode create.
Dans notre service, on va y trouver un certain nombre de classes Service (idéalement une par domain visé), chacune détaillant les méthodes de nos interfaces juste au-dessus. Ici, on aura une classe EventService qui va implémenter ICreateEvent. On va donc définir ce que la méthode create doit faire. Ça peut être un calcul propre au métier ou ça peut simplement être un appel à une des interfaces de notre server side port. Ici on fera un appel à l’interface ISaveEvent.
Dans notre Server side port, on y trouve aussi un certain nombre d’interfaces mais cette fois-ci il s’agit de lister l’ensemble des méthodes dont on va avoir besoin côté infrastructure pour agir sur la base de données ou le fichier de données qu’on a, et on répartit ces méthodes par interface (idéalement une par domain visé)
Ici, on aura notre interface ISaveEvent qui contiendra la méthode save.
Dans notre controller, c’est comme avec une architecture n tiers, on définit les endpoints de notre API. On prendra également soin de créer un controller par domain visé. Ici ce sera par exemple EventController.
Dans notre DTO, on définit les éventuels DTO dont on a besoin.
Dans notre entity, on y trouve les objets utiles au métier que l’on a éventuellement modifiés pour correspondre à notre base de données. On passe d’objet à entity. Ici on aura par exemple EventEntity.
Dans notre adapter, on va définir précisément toutes les méthodes dont notre logique métier a besoin pour réaliser des actions dans notre système de sauvegarde de données. Ici, on aura EventAdapter qui implémente notre interface ISaveEvent et qui va décrire précisément ce que doit faire la méthode save. Ça peut être un simple appel à un repository mais on peut aussi en profiter pour transformer notre objet en entity si nécessaire.
Dans notre Repository, on y trouve toutes les méthodes qui vont réaliser les requêtes sur notre système de sauvegarde de données. Ici, on aura par exemple EventRepository.
Dans le dossier config on y met toute la configuration dont a besoin notre application. Ici on a un BeanConfig et un SecurityConfig.
Vous pouvez retrouver le code ici
Pourquoi avons-nous besoin d’un BeanConfig?
Habituellement, sous Spring Boot par exemple (mais ce pourrait être avec un autre framework ce serait pareil) lorsque nous utilisons nos classes et nos interfaces, les beans sont automatiquement créés par Sring Boot. C’est toujours le cas dans notre partie infrastructure mais plus dans notre partie logique métier puisque celle-ci doit être totalement indépendante du framework utilisé. Nous devons donc nous même créer les beans utilisés dans la partie logique métier.
Avez-vous fait attention au sens des flèches sur les schémas?
Ils sont très importants! Je le répète encore une fois car c’est vraiment la base de l’architecture hexagonale 😃 : la logique métier doit être totalement indépendante. Mais nous devons la faire communiquer avec l’infrastructure pour que notre projet fonctionne. Pour cela, nous devons toujours faire appel à notre logique métier dans notre infrastructure mais jamais l’inverse.
Et les avantages dans tout ça?
Comme promis, j’y viens 😉
redonner du sens à nos développements car on part de choses concrètes qui sont ici les besoins métier et on va réfléchir à comment traduire cela en algorithmes alors que dans une architecture n tiers, on part d’une structure figée dans laquelle on essaie de faire rentrer les besoins métier et on peut avoir tendance à les complexifier inutilement
limiter les systèmes legacy car on peut changer beaucoup plus facilement la partie infrastructure sans impacter les besoins métier se trouvant dans la partie logique métier
une meilleure gestion de la dette technique car les futurs développements n’entraîneront que peu de coûts supplémentaires sur l’ensemble du projet. S’il s’agit d’améliorer l’interface utilisateur ou de mieux gérer le traitement des données, on sait qu’il ne faut s’intéresser qu’à une partie du projet et non à sa globalité. Et de même, tant que les besoins métier ne changent pas, si de nouveaux développeurs arrivent dans l’équipe, il n’est pas nécessaire qu’ils perdent du temps à les comprendre puisqu’ils n’auront pas à toucher à cette partie du code
des tests moins contraignants. Nous devons réaliser des tests sur l’ensemble de notre projet mais la partie la plus importante est la partie logique métier, et puisqu’elle est isolée de l’infrastructure, les tests sont plus faciles et rapides à réaliser et à maintenir
Des inconvénients?
Eh oui! Comme pour tout il y a quelques inconvénients :
la courbe d’apprentissage est un peu plus élevée
les projets sont plus volumineux qu’en n tiers
une organisation de l’application en couches, le projet est plus segmenté et il faut s’y tenir sinon on perd les avantages de faire de l’architecture hexagonale
Pour conclure
L’architecture hexagonale est une réelle alternative dans la construction de nos projets. Elle ne sera peut-être pas adaptée à tous les projets mais elle vaut vraiment le coup d’apprendre à la découvrir et de la populariser car elle replace les besoins finaux, et donc l’intérêt de nos développements, au cœur de nos projets.
Posted on June 29, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.