Architecture hexagonale & DDD en pratique
Un cours progressif pour comprendre les concepts qui structurent ce projet — et pouvoir les réutiliser ailleurs, dans un autre langage, un autre framework, un autre métier.
Ce n'est pas un manuel théorique : chaque notion est illustrée par le
code réel de ce dépôt — un gestionnaire de tâches avec deux
tranches, task et user, liées par une relation 1→n, une
API HTTP, un CLI et un worker RabbitMQ.
À qui s'adresse ce cours#
À un développeur qui sait coder mais veut comprendre pourquoi organiser une application de cette manière, et comment raisonner pour la concevoir soi-même.
Prérequis : Python (classes, async/await,
type hints), les bases d'un ORM et d'une API HTTP. Aucune connaissance préalable de
DDD n'est nécessaire.
Comment lire ce cours#
Les chapitres sont progressifs — chacun s'appuie sur le précédent. Les chapitres 03 et 05 sont les plus denses.
- 00Le problèmePourquoi cette architecture existe, avant/après
- 01La règle de dépendanceLa seule règle qui compte, et comment la vérifier
- 02Où vit une règle ?L'arbre de décision central du cours
- 03Le domaineDDD stratégique et tactique, value objects, entités, invariants
- 04Les agrégatsFrontière de cohérence, racine, comment la choisir
- 05Relations entre agrégatsRéférence par identité, cardinalités, N+1
- 06Application & portsUse cases, DTO, où placer un port
- 07Les adaptateursORM, mappers, HTTP, CLI, worker
- 08Transactions & erreursFrontière transactionnelle, erreurs métier vs techniques, DI
- 09Lire sans passer par le domaineQuery services, N+1, CQRS léger
- 10Écrire en masseReconstitution, bulk writers, idempotence,
UnitOfWork - 11Cache & événementsCache-aside, événements de domaine vs d'intégration
- 12Organisation & testsTranches verticales, les trois niveaux de tests
- 13Démarrer un projetLa recette, la checklist, et quand ne pas l'appliquer
- 14AnnexesPrincipe vs notre choix, glossaire, corrigés
En complément, un carnet de terrain sur le DDD stratégique : la procédure d'atelier qu'un dépôt de code ne peut pas enseigner, et un diagnostic honnête des frontières de ce projet.
La méthode de ce cours est aussi distribuée comme Agent Skill pour Claude Code, OpenAI Codex et Cursor, afin de l'appliquer sur tes propres projets. Le cours reste la source de vérité : le skill en est une traduction, pas un raccourci pour l'éviter.
L'idée en une phrase#
Le cœur métier de l'application ne doit dépendre d'aucun détail technique (base de données, framework web, format JSON). Les détails se branchent sur le cœur, jamais l'inverse.
Tout le reste en découle.
Une convention importante : principe ≠ notre choix#
Beaucoup de cours d'architecture présentent les choix de leur auteur comme des lois universelles. C'est le piège le plus courant, et il produit des développeurs dogmatiques. Ici, chaque fois qu'un choix d'implémentation est discutable, tu trouveras un encadré à trois colonnes :
| Concept | Ce que dit le principe | Ce que fait ce projet |
|---|---|---|
| Value object | Pas d'identité, égalité par valeur | dataclass(frozen=True, slots=True), auto-validé |
La colonne du milieu est transférable partout. La colonne de droite est un choix parmi d'autres, valide dans ce contexte. Savoir les distinguer, c'est la différence entre appliquer une recette et concevoir une architecture.
Le tableau complet de ces distinctions est regroupé en annexe.
Vocabulaire de base (à garder sous la main)#
| Terme | Définition courte |
|---|---|
| Domaine | Le cœur métier : les règles, indépendantes de toute technique. |
| Port | Une interface exprimant un besoin du cœur. |
| Adaptateur | Une implémentation concrète d'un port. |
| Driving / driven | Adaptateur qui pilote l'app (API, CLI, worker) vs. qui est piloté par elle (BDD, cache, SMTP). |
| Entité | Objet métier avec une identité stable dans le temps (Task, User). |
| Value object | Objet défini par sa valeur, sans identité propre (Email, TaskTitle). |
| Agrégat | Une frontière de cohérence transactionnelle, avec une racine. |
| Use case | Une action applicative qui orchestre le domaine (CreateTask). |
| Bounded context | Une frontière à l'intérieur de laquelle un modèle et son langage restent cohérents. |
Le glossaire complet est en annexe.
À toi de jouer#
Chaque chapitre se termine par quelques exercices courts. Ils ne demandent pas d'écrire beaucoup de code — surtout de décider où placer quelque chose, qui est la compétence réelle que ce cours essaie de transmettre. Les corrigés sont en annexe.