GevoxxInsights All articles
Software engineering · Architecture

L'architecture hexagonale (ports & adapters) expliquée simplement

Isoler le cœur métier des détails techniques (base, framework, API) : le principe des ports et adaptateurs, avec un exemple concret et ses bénéfices en test.

L'architecture hexagonale (ports & adapters) expliquée simplement

L'architecture hexagonale, aussi appelée ports & adapters, a été formulée par Alistair Cockburn. Son idée tient en une phrase : le cœur métier de votre application ne doit dépendre d'aucun détail technique — ni de la base de données, ni du framework web, ni des API externes. Ces détails deviennent des « branchements » interchangeables autour d'un centre stable.

Le problème qu'elle résout

Dans une application classique en couches, la logique métier finit souvent mêlée au framework : des annotations de persistance sur les objets métier, des appels HTTP au milieu des règles, une logique impossible à tester sans démarrer toute l'infrastructure. Résultat : changer de base de données ou de framework devient un chantier, et les tests sont lents et fragiles.

Le métier ne devrait pas savoir s'il est appelé par une API REST, un test, une file de messages ou une ligne de commande. Il rend un service ; peu lui importe qui l'appelle et où sont stockées les données.

Ports et adaptateurs

On place le domaine (les règles métier) au centre. Il communique avec l'extérieur uniquement à travers des ports — des interfaces qu'il définit lui-même. Les adaptateurs sont les implémentations concrètes de ces ports :

  • Ports d'entrée (driving) — comment on pilote le métier. Ex. une interface CreerFactureUseCase, appelée par un contrôleur REST, un test, ou un consommateur Kafka.
  • Ports de sortie (driven) — ce dont le métier a besoin. Ex. une interface FactureRepository ou NotificationPort, implémentée par un adaptateur PostgreSQL ou SMTP.

Point crucial : les flèches de dépendance pointent vers le centre. Les adaptateurs dépendent du domaine, jamais l'inverse. C'est l'application directe du principe d'inversion des dépendances (le « D » de SOLID).

Un exemple concret

// --- DOMAINE (aucune dépendance technique) ---
public interface FactureRepository {         // port de sortie
    void enregistrer(Facture f);
}
public class CreerFactureService {           // cas d'usage
    private final FactureRepository repo;     // dépend de l'abstraction
    public CreerFactureService(FactureRepository repo) { this.repo = repo; }
    public Facture creer(Commande c) {
        Facture f = Facture.depuis(c);        // règle métier pure
        repo.enregistrer(f);
        return f;
    }
}

// --- ADAPTATEUR (détail technique, à la périphérie) ---
@Repository
class FactureRepositoryJpa implements FactureRepository {
    public void enregistrer(Facture f) { /* mapping + JPA */ }
}

Le service métier ne connaît que FactureRepository. En production, Spring injecte l'adaptateur JPA ; en test, on injecte une implémentation en mémoire (une HashMap). Les tests deviennent rapides et sans infrastructure.

Bénéfices et coûts

Les gains sont réels : testabilité (le métier se teste en isolation, en millisecondes), remplaçabilité (changer PostgreSQL pour Mongo, ou REST pour gRPC, n'affecte pas le domaine), et clarté (les règles métier sont regroupées, non diluées). Le coût : plus de couches et d'interfaces, ce qui peut être excessif pour un petit CRUD sans logique. L'hexagonal brille sur les applications à logique métier riche et durée de vie longue.

Cousines : Clean & Onion Architecture

L'architecture hexagonale, la Clean Architecture de Robert C. Martin et l'Onion Architecture de Jeffrey Palermo partagent le même principe fondamental : un cœur métier indépendant, entouré de couches qui dépendent vers l'intérieur. Les noms diffèrent, l'esprit est identique. On la combine souvent avec le Domain-Driven Design pour modéliser un domaine complexe.

Sources et références