Infrastructure générée,
application fonctionnelle.
- Plugins JPA et REST configurés avec routage multi-module.
- ~32 fichiers d'infrastructure générés automatiquement.
- Score final 67/100, grade D, 0 violation.
Configuration HexaGlue
hexaglue.yaml à la racine du projet configure les quatre plugins actifs et déclare le rôle architectural de chaque module Maven.Deux clés structurent la configuration : les exclusions de classification pour les packages hors périmètre DDD, et les rôles de modules qui permettent le routage du code généré.
classification: exclude: - "com.acme.banking.core.exception.*"
plugins: io.hexaglue.plugin.jpa: entitySuffix: "JpaEntity" repositorySuffix: "JpaRepository" adapterSuffix: "RepositoryAdapter" generateRepositories: true generateAdapters: true generateEmbeddables: true enableAuditing: false targetModule: banking-persistence outputDirectory: "src/main/java"
io.hexaglue.plugin.rest: targetModule: banking-api flattenValueObjects: true generateExceptionHandler: true generateConfiguration: false
io.hexaglue.plugin.livingdoc: outputDir: "living-doc"
io.hexaglue.plugin.audit: generateDocs: false
modules: banking-core: role: DOMAIN banking-persistence: role: INFRASTRUCTURE banking-service: role: APPLICATION banking-api: role: API banking-app: role: ASSEMBLYtargetModule: banking-persistence: tout le code JPA généré (entités, repositories, mappers, adapters) est routé vers le module de persistance dédié, sans polluer le domainetargetModule: banking-api: les contrôleurs REST, DTOs et l'exception handler sont routés vers le module APIgenerateConfiguration: false: nécessaire ici car lesApplicationServicesont définis dansbanking-service. HexaGlue ne peut pas générer la configuration Spring dans un module qui ne voit pas ces services ; la configuration reste manuelle dansbanking-app- Rôles de modules : DOMAIN, INFRASTRUCTURE, APPLICATION, API, ASSEMBLY permettent à HexaGlue de valider les règles d'isolation entre couches et de router la génération vers le bon module
Code généré automatiquement
Aucun de ces fichiers n'est écrit à la main : le code JPA est produit dans
banking-persistence, le code REST dans banking-api.Plugin JPA → banking-persistence
AccountJpaEntity, BeneficiaryJpaEntity, CardJpaEntity, CustomerJpaEntity, TransactionJpaEntity, TransferJpaEntity
AddressEmbeddable, MoneyEmbeddable
AccountJpaRepository, BeneficiaryJpaRepository, CardJpaRepository, CustomerJpaRepository, TransactionJpaRepository, TransferJpaRepository
AccountMapper, BeneficiaryMapper, CardMapper, CustomerMapper, TransactionMapper, TransferMapper
AccountRepositoryAdapter, BeneficiaryRepositoryAdapter, CardRepositoryAdapter, CustomerRepositoryAdapter, TransactionRepositoryAdapter, TransferRepositoryAdapter
Plugin REST → banking-api
AccountController, BeneficiaryController, CardController, CustomerController, TransferController
Objets de transfert aplatis depuis les value objects domaine (flattenValueObjects: true)
BankingExceptionHandler — gestionnaire global des erreurs domaine
- ~32 fichiers générés remplacent le code infrastructure manuel : 26 fichiers JPA (entités, embeddables, repositories, mappers, adapters) et environ 6 fichiers REST de base (controllers, exception handler), auxquels s'ajoutent les ~18 DTOs
- 38 types domaine manuels restent : les agrégats, value objects, identifiants, ports et services applicatifs constituent l'architecture métier que HexaGlue analyse et ne génère pas
- Synchronisation garantie : si le domaine évolue, toute la couche infrastructure est régénérée automatiquement à la compilation suivante, sans intervention manuelle
Rapport d'audit
Rapport d'audit final après génération automatique JPA et REST, purification des services et câblage des driven ports.
Verdict de l'audit
Le statut PASSED reflète l'absence totale de violations architecturales. Le grade D traduit la qualité globale mesurée sur cinq dimensions.
- Statut PASSED : aucune violation Blocker, Critical ou Major. Toutes les contraintes DDD et hexagonales sont respectées
- Grade D (score ≥ 60) : DDD Compliance et Hexagonal Architecture sont au maximum (100%), mais Dependencies (0%) et Coupling (51%) plafonnent le score total. Ces dimensions mesurent les cycles de dépendances et le couplage entre packages, indépendamment de la conformité hexagonale
Décomposition du score
DDD Compliance et Hexagonal Architecture sont au maximum. Dependencies et Coupling, qui mesurent les cycles inter-packages, concentrent les points perdus.
| Dimension | Score | Status | Delta |
|---|---|---|---|
| DDD Compliance | 100% | +91 | |
| Hexagonal Architecture | 100% | +100 | |
| Dependencies | 0% | = | |
| Coupling | 51% | +11 | |
| Cohesion | 68% | +28 | |
| TOTAL | 67.85 | ||
- DDD Compliance à 100% : tous les patterns tactiques DDD sont en place — agrégats avec identifiants typés, value objects, ports de domaine. Le modèle domaine est complet
- Hexagonal Architecture à 100% : les services applicatifs sont des POJOs purs, chaque port dispose d'un adaptateur généré, les couches sont isolées sans aucune dépendance croisée
- Dependencies à 0% : cette dimension pénalise les cycles de dépendances entre packages. Des cycles inter-packages subsistent dans la base de code, indépendamment de la qualité de l'architecture hexagonale
- Coupling à 51% : le couplage inter-packages reste élevé car plusieurs bounded contexts partagent des types. Des identifiants typés réduiraient les références croisées entre agrégats
- Cohesion à 68% : la concentration fonctionnelle des packages est satisfaisante mais pourrait progresser en regroupant les types par bounded context
Inventaire architectural
Il montre la répartition finale entre agrégats, ports et services applicatifs.
| Composant | Nombre |
|---|---|
| Aggregate Roots | 6 |
| Entities | 0 |
| Value Objects | 8 |
| Identifiers | 6 |
| Domain Events | 0 |
| Application Services | 5 |
| Driving Ports | 5 |
| Driven Ports | 8 |
- 6 Aggregate Roots : Account, Beneficiary, Card, Customer, Transaction, Transfer — chaque entité métier principale est un agrégat avec identifiant typé et frontières respectées
- 8 Value Objects : les 4 enums (AccountType, CardType, TransactionType, TransferStatus) plus Money, Iban, Email et Address — le domaine exprime ses concepts sans primitives
- 5 Driving Ports : les 5 use cases exposés par l'hexagone. FraudDetection et NotificationSender sont correctement classifiés comme driven ports (ports sortants)
- 8 Driven Ports : les 6 repositories de persistence plus FraudDetection et NotificationSender — tous couverts par des adaptateurs générés ou câblés manuellement
Violations détectées
La génération automatique et la purification des services ont éliminé les 16 violations de l'étape précédente.
Aucune violation détectée. Toutes les contraintes DDD et hexagonales sont respectées.
Le zéro violation résulte de la combinaison de trois actions menées lors des étapes précédentes :
- Génération JPA : les adaptateurs générés couvrent correctement tous les driven ports, éliminant les violations
port-coverageetlayer-isolation - Génération REST : les contrôleurs et DTOs générés remplacent le code REST manuel, éliminant les violations
adapter-coupling - Purification des services : la suppression des annotations
@Serviceet le reclassement de FraudDetection et NotificationSender en driven ports éliminent les violationsapplication-purity
Métriques de qualité
La pureté du domaine atteint 100%, mais le boilerplate technique reste élevé en raison du code généré.
| Métrique | Valeur | Status |
|---|---|---|
| Domain purity | 100.00% | |
| Domain coverage | 52.63% | |
| Aggregate boundary | 100.00% | |
| Code boilerplate | 88.41% | |
| Code complexity | 1.08 | |
| Adapter independence | 100.00% |
domain.purityà 100% : le domaine ne contient aucune dépendance technique. Les agrégats, value objects et ports sont des POJOs purs Javaaggregate.boundaryà 100% : tous les agrégats respectent leurs frontières. Aucune entité interne n'est exposée directement depuis l'extérieurcode.boilerplateà 88.41% (CRITICAL) : ce ratio inclut le code infrastructure généré par HexaGlue. Les entités JPA, mappers et DTOs sont techniques par nature ; le seuil de 50% est conçu pour le code domaine et ne s'applique pas directement à un projet multi-module avec génération activeadapter.independenceà 100% : les adaptateurs générés ne dépendent pas les uns des autres et restent isolés dans leur modulecode.complexityà 1.08 : la complexité cyclomatique moyenne est très faible, confirmant la lisibilité du code domaine pur
Stabilité des packages
Elle révèle les packages en Zone of Pain (stables mais concrets) et ceux bien positionnés sur la Main Sequence.
| Package | Ca | Ce | I | A | D | Zone |
|---|---|---|---|---|---|---|
| com.acme.banking.api.controller | 0 | 20 | 1.00 | 0.00 | 0.00 | Main Sequence |
| com.acme.banking.core.model | 48 | 0 | 0.00 | 0.00 | 1.00 | Zone of Pain |
| com.acme.banking.core.port.in | 11 | 13 | 0.54 | 1.00 | 0.54 | Main Sequence |
| com.acme.banking.core.port.out | 14 | 13 | 0.48 | 1.00 | 0.48 | Main Sequence |
| com.acme.banking.infrastructure.persistence | 0 | 26 | 1.00 | 0.46 | 0.46 | Main Sequence |
| com.acme.banking.service.application | 0 | 25 | 1.00 | 0.00 | 0.00 | Main Sequence |
core.modelen Zone of Pain (D=1.00) : ce package est très stable (Ca=49, Ce=0 — 49 packages en dépendent) mais totalement concret (A=0). Il concentre toutes les classes domaine. Cette position est attendue pour un modèle métier dense ; la résoudre impliquerait d'introduire des interfaces ou de découper par bounded contextcore.port.inetcore.port.outsur la Main Sequence : les ports sont abstraits (A=1.00) et correctement positionnés. Ils constituent l'hexagone au sens strictinfrastructure.persistence,service.application,api.controller: ces packages sont instables (I=1.00) — aucun package ne dépend d'eux. C'est la position correcte pour les couches externes : elles dépendent du domaine et ne sont pas dépendées
Plan de remédiation
Toutes les violations architecturales ont été résolues. Le plan de remédiation est vide.
Aucune violation à corriger. L'architecture hexagonale est conforme aux contraintes DDD et hexagonales définies.
Avant vs Après
Les chiffres montrent ce que la migration apporte concrètement : suppression de la dette technique, ajout des patterns DDD, et génération automatique de l'infrastructure.
| Critère | Legacy | Hexagonal |
|---|---|---|
| Classes manuelles | ~45 | 38 |
| Infrastructure générée | 0 | ~32 |
| JPA dans le domaine | Oui | Non |
| Value Objects | 0 | 8 |
| Identifiants typés | 0 | 6 |
| Driving Ports | 0 | 5 |
| Driven Ports | 0 | 8 |
| Score architectural | N/A | 67/100 |
Enseignements
Le domaine doit être pur
La suppression des annotations JPA du domaine est le point d'inflexion. Tant que le domaine contient du code technique, HexaGlue ne peut pas générer l'infrastructure correctement.
Multi-module et routage par module
targetModule route le code généré vers le bon module. Le mode reactor analyse tous les modules en une seule passe. Les ports définis dans banking-core sont vus par tous les plugins.
Convention reconstitute()
La factory method reconstitute() est indispensable pour que les mappers générés puissent restaurer les agrégats depuis la persistance, sans compromettre l'encapsulation du domaine.
Migration incrémentale
Chaque étape compile. Les rapports d'audit guident l'étape suivante. Pas de Big Bang : le score progresse de 14 à 67/100 de manière incrémentale.
Le score est un indicateur fidèle
67/100 avec 0 violation montre une architecture hexagonale bien structurée. Dependencies (0%) et Coupling (51%) signalent des cycles inter-packages, un axe d'amélioration distinct de la conformité hexagonale.
Infrastructure sans code manuel
~32 fichiers générés remplacent l'infrastructure manuelle. Le coût de l'architecture hexagonale est absorbé par la génération automatique : entités JPA, repositories, mappers, adapters, controllers et DTOs.
Une architecture hexagonale opérationnelle.
Un socle solide pour aller plus loin.
L'application bancaire multi-modules est passée de 14/100 à 67/100, avec 0 violation et DDD + Hexagonal à 100%.