Étude de cas
Application E-Commerce Mono-Module
Code source- Mono-module Maven, Java 17, Spring Boot 3.2.5.
- 50 classes réparties dans 9 packages techniques.
- 10 anti-patterns typiques d'un découpage par couche technique.
Legacy
L'application legacy
Cette application e-commerce illustre un anti-pattern courant : le découpage horizontal par couche technique.
Chaque package correspond à un rôle technique (
Chaque package correspond à un rôle technique (
controller, service, model, repository) plutôt qu'à un domaine métier. Le résultat est une application qui semble organisée mais où le domaine reste invisible, noyé sous JPA et Spring.| # | Anti-pattern |
|---|---|
| 1 | Couplage domaine/persistance |
| 2 | Services sans distinction de rôle |
| 3 | Aucune inversion de dépendance |
| 4 | Modèle anémique |
| 5 | Absence de typage métier |
| 6 | Références directes entre agrégats |
| 7 | Héritage technique imposé |
| 8 | Dépendance au framework pour les événements |
| 9 | Fuite de responsabilité |
| 10 | Aucune séparation des couches |
Structure
Organisation des packages
L'application suit un découpage purement technique :
Il n'existe aucun package
controller, service, model, repository, dto, config, exception, event et util.Il n'existe aucun package
domain, aucun port, aucun agrégat : la frontière entre métier et infrastructure est inexistante.com.acme.shop/├── ShopApplication.java├── controller/ (5 classes)├── service/ (8 classes)├── model/ (11 classes)├── repository/ (6 interfaces)├── dto/ (7 records)├── config/ (2 classes)├── exception/ (4 classes)├── event/ (1 classe)└── util/ (2 classes)Code métier et code technique imbriqués dans les mêmes classes.
- Les 11 classes
model/sont à la fois des entités JPA et des objets du domaine : le domaine dépend directement de l'infrastructure - Les 8 classes
service/mélangent orchestration, logique métier et accès aux repositories Spring Data - Changer de framework ou migrer l'infrastructure implique de réécrire le domaine entier
Code legacy
Exemple : Order.java
La classe
C'est exactement ce que HexaGlue va analyser et signaler dans le rapport d'audit initial.
Order telle qu'elle existe dans le projet : annotations JPA, héritage de BaseEntity, primitives pour les montants et adresses, référence directe à Customer au lieu d'un identifiant typé.C'est exactement ce que HexaGlue va analyser et signaler dans le rapport d'audit initial.
@Entity@Table(name = "orders")public class Order extends BaseEntity {
@Column(nullable = false, unique = true) private String orderNumber;
// Anti-pattern : référence directe à l'entité au lieu d'un identifiant typé @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "customer_id", nullable = false) private Customer customer;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true) private List<OrderLine> lines = new ArrayList<>();
@Enumerated(EnumType.STRING) @Column(nullable = false) private OrderStatus status = OrderStatus.DRAFT;
@Column(precision = 10, scale = 2) private BigDecimal totalAmount;
private String currency; private String shippingStreet; private String shippingCity; private String shippingZipCode; private String shippingCountry;
// getters, setters...}- Domaine invisible sous les annotations JPA (
@Entity,@Table,@ManyToOne) - Couplage fort :
Orderréférence l'entitéCustomerau lieu d'un identifiant typéCustomerId - Absence de typage métier :
BigDecimalpour le montant,Stringpour la devise et l'adresse éclatée en primitives - Héritage technique imposé par
BaseEntity(@MappedSuperclass) avecLong idauto-généré - Aucun comportement métier : uniquement des getters/setters, la logique vit dans les services
Premier diagnostic
Brancher HexaGlue sur le projet
Pour obtenir un diagnostic architectural, on ajoute le plugin HexaGlue au
En mode mono-module, HexaGlue s'intègre au cycle de vie Maven et produit un rapport d'audit complet en une seule commande
pom.xml et on déclare le package racine à analyser.En mode mono-module, HexaGlue s'intègre au cycle de vie Maven et produit un rapport d'audit complet en une seule commande
mvn verify.<plugin> <groupId>io.hexaglue</groupId> <artifactId>hexaglue-maven-plugin</artifactId> <version>6.1.1</version> <extensions>true</extensions> <configuration> <basePackage>com.acme.shop</basePackage> <failOnError>false</failOnError> </configuration> <dependencies> <dependency> <groupId>io.hexaglue.plugins</groupId> <artifactId>hexaglue-plugin-audit</artifactId> <version>3.1.1</version> </dependency> </dependencies></plugin>extensions=true: HexaGlue s'intègre au cycle de vie Maven et déclenche automatiquement la classification à la phasecompileet l'audit à la phaseverifybasePackage: toutes les classes souscom.acme.shopseront analysées et classifiées par HexaGluefailOnError=false: le build ne sera pas bloqué par les violations, utile pour un premier diagnostic non intrusif
Rapport d'audit
Résultat de la première exécution de l'audit HexaGlue sur les 50 classes du projet e-commerce.
Verdict
Verdict de l'audit initial
Le score global, la note et les violations sont affichés en tête du rapport. Ce premier verdict donne une photographie chiffrée de l'état architectural avant toute modification.
13
/100
Grade F
FAILED
43
violations
19
critical
24
major
Le grade F confirme que l'architecture ne respecte aucun principe DDD ni hexagonal. L'application n'a ni ports, ni identifiants typés, ni séparation domaine/infrastructure. Les sections suivantes détaillent la décomposition du score et les violations par catégorie.
Score
Décomposition du score
Le score de 13/100 est calculé à partir de 5 dimensions pondérées. Ce tableau montre la contribution de chaque dimension et son écart par rapport au seuil attendu.
| Dimension | Score | Status | |
|---|---|---|---|
| DDD Compliance | 0% | ||
| Hexagonal Architecture | 0% | ||
| Dependencies | 0% | ||
| Coupling | 30% | ||
| Cohesion | 58% | ||
| TOTAL | 13.20 | ||
- DDD Compliance et Hexagonal Architecture à 0% : ces deux dimensions représentent 50% du score total. Aucun agrégat, aucun port et aucun identifiant typé n'existe dans le code
- Dependencies à 0% : les dépendances vont du domaine vers l'infrastructure, l'inverse de ce qu'attend l'architecture hexagonale
- Coupling et Cohesion contribuent légèrement : l'organisation en packages techniques apporte un minimum de découplage structurel
Violations
Violations détectées
Chaque violation correspond à une règle architecturale enfreinte par le code. Elles sont classées par sévérité : Critical pour les problèmes structurels fondamentaux, Major pour les écarts significatifs qui bloquent la progression vers une architecture hexagonale.
| Contrainte | Nombre Nb | Sévérité Sév. |
|---|---|---|
| ddd:domain-purity | 10 | CRITICAL CRIT |
| ddd:entity-identity | 9 | CRITICAL CRIT |
| hexagonal:port-direction | 6 | MAJOR MAJ |
| hexagonal:port-coverage | 6 | MAJOR MAJ |
| hexagonal:layer-isolation | 12 | MAJOR MAJ |
Les 19 violations Critical ont toutes la même cause racine : les annotations JPA dans le modèle de domaine.
- ddd:domain-purity : le domaine importe
jakarta.persistence, il dépend structurellement de la couche de persistance - ddd:entity-identity : les 9 entités JPA utilisent un
Long idauto-généré, pas un identifiant métier typé
Les 24 violations Major signalent l'absence de structure hexagonale. La prochaine étape commence par configurer les exclusions pour éliminer le bruit d'analyse, puis restructure le code en couches hexagonales.