Architecture Hexagonale en Java, Avantages, Bonnes Pratiques et Exemple
Pourquoi l'architecture hexagonale ?
Une application Java démarre bien. Six mois plus tard, l'architecture en couches s'est transformée en plat de pâtes. Tout est connecté. Les tests deviennent un casse-tête. Le moindre changement menace de tout faire exploser.
J’ai accompagné des équipes dans cette situation chez plusieurs clients bancaires et assurance. Le pattern se répète : la couche métier dépend directement de la base de données, et les tests unitaires ont besoin de toute l’application pour s’exécuter. Un désordre qui coûte plusieurs semaines de lead time par an.
L’architecture hexagonale (ou "Ports et Adapters", formalisée par Alistair Cockburn) répond exactement à ce problème. Le domaine métier au centre, protégé. L'infrastructure (base de données, services externes) réduite à une collection d’adaptateurs interchangeables.
Le concept d'architecture hexagonale
L’architecture hexagonale, également appelée architecture Ports et Adapters, place le domaine métier au centre de l’application. L’objectif est de séparer complètement votre logique métier des aspects techniques comme la base de données, l’interface utilisateur ou encore les services externes.
Un problème de dépendances
La grande faiblesse des architectures traditionnelles (architecture en couches notamment) tient à l'interconnexion excessive des couches. Prenons un service bancaire qui consulte le solde d'un compte. Si la couche métier dépend directement de la base de données, le moindre changement de schéma oblige à modifier la logique métier. La maintenabilité s'effondre.
Une séparation claire : le domaine au centre
L’architecture hexagonale résout ce problème en séparant clairement le domaine métier du reste de l’application. Votre domaine contient toute la logique métier, tandis que les aspects techniques sont gérés par des adapters, qui ne sont que des implémentations concrètes de ports définis dans le domaine.
En termes simples, les ports sont des interfaces qui définissent comment le domaine interagit avec le reste du système, et les adapters sont des implémentations de ces interfaces. Ainsi, vous pouvez changer une implémentation (comme la base de données) sans toucher à votre domaine métier.
TIP : Gardez en tête que le but de cette architecture est de protéger votre domaine métier des changements technologiques. Cela permet de réduire les risques de "cascades de modifications" qui peuvent survenir dans les projets trop couplés à leurs infrastructures.
Exemple : un service bancaire en Java
Voici un exemple simple en Java illustrant cette approche.
Le domaine (Compte et ServiceBancaire) :
public class Compte {
private String id;
private double solde;
public Compte(String id, double solde) {
this.id = id;
this.solde = solde;
}
public double obtenirSolde() {
return this.solde;
}
}
public interface ComptePort {
Compte obtenirCompteParId(String id);
}
public class ServiceBancaire {
private ComptePort comptePort;
public ServiceBancaire(ComptePort comptePort) {
this.comptePort = comptePort;
}
public double consulterSolde(String idCompte) {
Compte compte = comptePort.obtenirCompteParId(idCompte);
if (compte == null) {
throw new RuntimeException("Compte non trouvé !");
}
return compte.obtenirSolde();
}
}
L’implémentation de l'Adapter dans l'infrastructure (Infra) :
public class CompteAdapter implements ComptePort {
private Map<String, Compte> baseDeDonnees;
public CompteAdapter() {
baseDeDonnees = new HashMap<>();
baseDeDonnees.put("123", new Compte("123", 1500.0));
baseDeDonnees.put("456", new Compte("456", 2500.0));
}
@Override
public Compte obtenirCompteParId(String id) {
return baseDeDonnees.get(id);
}
}
Application principale (Main) :
public class Main {
public static void main(String[] args) {
CompteAdapter compteAdapter = new CompteAdapter();
ServiceBancaire serviceBancaire = new ServiceBancaire(compteAdapter);
String idCompte = "123";
double solde = serviceBancaire.consulterSolde(idCompte);
System.out.println("Le solde du compte " + idCompte + " est de " + solde + " €.");
}
}
ALERT : N'oubliez pas que les ports sont des abstractions du domaine métier. Ils doivent rester indépendants des technologies utilisées dans les adapters (comme une base de données). Cela vous évite de lier votre domaine métier à une technologie particulière.
Vous voulez savoir où placer la frontière entre domaine et infrastructure sans hésiter ?
Découper ports et adapters proprement, ça ne s'apprend pas en recopiant un exemple : ça se travaille sur votre vrai code, avec ses zones grises. En mentoring 1:1, je relis vos couches avec vous, on isole le domaine pas à pas, et vous repartez avec le réflexe de poser les bonnes interfaces avant que le couplage s'installe.
Vous montez en niveau sur du concret, pas sur des slides.
Avantages de l'architecture hexagonale
Les bénéfices concrets observés en adoptant cette architecture sur le terrain.
1. Modularité et testabilité
En isolant la logique métier des détails techniques, vous obtenez un code beaucoup plus modulaire. Vous pouvez remplacer les adaptateurs (comme la base de données) sans toucher à la logique métier. Cela facilite également les tests : vous pouvez mock les adaptateurs pour tester votre domaine métier sans avoir besoin d'une vraie base de données.
TIP : Utiliser des mocks pour simuler vos adapters dans les tests est une excellente pratique. Cela vous permet de tester votre logique métier indépendamment de la configuration des systèmes externes comme les bases de données ou les services tiers.
2. Adaptabilité et flexibilité
L’architecture hexagonale vous permet d'ajouter ou de modifier facilement des composants. Si vous décidez d’ajouter une nouvelle interface utilisateur, par exemple une API REST, il suffit d’ajouter un nouvel adapter pour transformer les requêtes HTTP en appels au domaine.
3. Simplicité des changements dans l'infrastructure
Un autre grand avantage est la possibilité de changer l’infrastructure sans impacter le domaine. Si vous devez changer de base de données ou d'outil de communication, le domaine reste intact, et seuls les adaptateurs doivent être modifiés.
Bonnes pratiques et pièges à éviter
L’architecture hexagonale a de nombreux avantages, mais il est essentiel de l’adopter correctement. Voici quelques bonnes pratiques.
1. Ne pas sur-ingénier le projet
N’essayez pas de rendre votre projet inutilement complexe. Si vous commencez à ajouter trop d’interfaces et de couches abstraites, vous risquez de rendre votre code plus difficile à comprendre et à maintenir. Gardez-le simple et pragmatique.
ALERT : Ne tombez pas dans le piège de la sur-ingénierie. Si vous avez un projet simple, n'ajoutez pas de couches abstraites inutiles. L'architecture hexagonale doit vous aider, pas vous compliquer la vie.
2. Respecter les principes SOLID
L’architecture hexagonale s’intègre parfaitement dans les principes SOLID, notamment en respectant le principe de responsabilité unique et l’inversion des dépendances. Assurez-vous que chaque composant a une responsabilité bien définie et que le domaine ne dépend jamais directement de l’infrastructure. Pour aller plus loin sur la règle de dépendance et la direction des flèches dans l’architecture, les 3 règles de la Clean Architecture sont complémentaires.
3. KISS : Keep It Simple, Stupid
Restez simple. L’objectif est de simplifier la maintenance et les changements dans le projet, pas de compliquer inutilement les choses. Si votre projet est petit, ne vous forcez pas à utiliser l’architecture hexagonale partout. Elle doit apporter une valeur ajoutée.
TIP : Adoptez le principe KISS. L’architecture hexagonale est puissante, mais elle doit rester un outil au service de la simplicité et de la maintenabilité, et non un fardeau architectural.
L'hexagonale n'est qu'une pratique parmi les 100 qui font le craft
Protéger son domaine derrière des ports et adapters, c'est une pièce du puzzle. Le Craft Bundle réunit les 100 pratiques que j'applique pour coder propre au quotidien, du découpage des couches à la discipline de test qui rend cette architecture vraiment payante. Ce sont les réflexes que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vus tenir un système en prod sur la durée.
FAQ sur l’architecture hexagonale
1. L’architecture hexagonale est-elle adaptée à tous les projets ?
Pas nécessairement. Pour les petits projets ou les prototypes simples, elle peut être surdimensionnée. Cependant, elle devient très utile pour des projets plus complexes, ou ceux qui nécessitent de fréquents changements de technologie.
2. Comment commencer dans un projet existant ?
Vous pouvez commencer progressivement en appliquant les principes hexagonaux à de nouvelles fonctionnalités ou modules, tout en refactorisant doucement l’existant. Cela évite de tout casser d’un coup.
3. Est-ce que ça complique trop les petites applications ?
Cela dépend de l’application. Si vous prévoyez des évolutions futures importantes, l’architecture hexagonale peut aider dès le début. Pour des projets très simples, une architecture en couches peut parfois suffire.
4. Quels outils Java facilitent la mise en œuvre ?
Java propose de nombreux frameworks qui s’intègrent bien avec cette architecture. Spring est souvent utilisé pour implémenter les ports et adaptateurs, en particulier avec sa gestion des dépendances. Les tests peuvent être facilement gérés avec JUnit et Mockito.
Ressource gratuite : Votre équipe livre-t-elle aussi vite qu'elle le pourrait ?
30 questions, 5 dimensions, score sur 100. Mesurez la maturité engineering de votre équipe avec le benchmark utilisé dans des DSI de 50 à 800+ développeurs, et identifiez vos 3 chantiers prioritaires.


