Guide Architecture DDD — Référence universelle¶
Résumé¶
Référence universelle pour tous les projets TypeScript/Node.js de Bernard. Documente l'architecture DDD stricte avec Express 5 + Prisma + Redis + BullMQ + Winston, issue de la fusion de DDD_Module (entités, ServiceValidation, ports HTTP, DI robuste) et ProjetFilleMere (auto-discovery déclaratif, multi-tenant, CUID). Contient 26 règles absolues issues de bugs réels, une checklist en 8 phases et une table de nommage exhaustive.
Contenu structuré¶
Stack technique¶
- Runtime : Express 5, TypeScript 5, tsx watch
- ORM : Prisma (
db push— jamaismigrate dev) - IDs : CUID via
@paralleldrive/cuid2— jamais UUID - Queue : BullMQ + ioredis
- Logs : Winston via
AppLogger - Validation : Zod (deux niveaux distincts)
Structure des couches #ddd¶
domain/ ← zéro dépendance externe
application/ ← uniquement interfaces domain + shared
infrastructure/ ← Prisma, Redis, BullMQ ici uniquement
interface-adapters/← pont HTTP ↔ domaine
Voir shared/architecture/shared-infra-docker pour l'infrastructure partagée VPS.
Couche Domain¶
- Entité : constructeur
private, factorystatic creer(), reconstitutionstatic depuisDB() - Entité :
versObjetPlain()(interne) ETversObjetPlainPublic()(HTTP) distincts — ne jamais exposerversObjetPlain()en HTTP - Value Object : constructeur
private,static creer()avec validation,equals(), immuable - Exception :
extends ErreurMetier(jamaisextends Error), union type pour les codes d'erreur domain/schemas/: constantes string uniquement — zéro import Zod ici
Couche Application — Use Case en 5 étapes¶
1. Validation (Zod + règles métier via ServiceValidation)
2. executerLogique() — logique métier, peut lancer ErreurXxx typée
3. auditer() — try/catch séparé, JAMAIS de throw
4. construireResultat() — appelle versObjetPlainPublic()
5. gererErreur() — retourne TOUJOURS ResultatXxx, jamais de re-throw
Interface Use Case — 4 sections obligatoires : DonneesXxx, ResultatXxx, CodeErreurXxx (union type), interface avec JSDoc.
Couche Infrastructure¶
- Repository :
idUtilisateurdans leWHEREde toutes les requêtes (multi-tenant) - Repository :
updateMany/deleteMany(pasupdate/delete) pour multi-tenant - ServiceValidation : un par module, Map
, deux sous-étapes (Zod → règles métier) - Module DI : ordre init obligatoire — repositories → services → use cases → controllers
Couche Interface-Adapters¶
- Handler :
extends BaseActionHandler, hooks obligatoiresexecuteBusinessLogic()+getActionName() - Controller : 3 lignes max par méthode, factory function obligatoire
createXxxController(deps) - Wrapper module : arrow functions uniquement (préserve le
this), litreq.utilisateur(pasreq.user) - Routes : déclaratives, statiques avant dynamiques (ex:
/exportavant/:id)
Routing Auto-Discovery¶
Chaque module expose un fichier {nom}.module.routes.ts déclaratif. Le GestionnaireModulaire monte automatiquement toutes les routes au démarrage via AutoDiscoveryModular.
Voir aussi shared/flow-connexion-auth pour le flow d'authentification transversal.
Points clés¶
26 règles absolues (sélection critique)¶
| # | Règle | Piège |
|---|---|---|
| 3 | Méthode use case = toujours executer() |
Jamais execute(), run(), process() |
| 7 | IDs Prisma : z.string().min(1) |
Jamais z.string().uuid() — CUIDs ≠ UUIDs |
| 8 | Lire req.utilisateur?.id |
Jamais req.user?.id — bug de prod documenté |
| 13 | auditer() toujours non-bloquant |
Jamais de throw dans auditer() |
| 14 | construireResultat() appelle versObjetPlainPublic() |
Jamais versObjetPlain() en HTTP |
| 19 | prisma db push uniquement |
Jamais migrate dev — shadow DB absente |
| 26 | sed échoue sur les accents |
Utiliser python3 -c "..." pour fichiers UTF-8 |
Checklist création d'un nouveau module (8 phases)¶
- Domain — entité, value objects, exceptions, interfaces, constantes schemas
- Schemas Zod — un fichier par action dans
infrastructure/schemas/zod/ - ServiceValidation — Map
+ deux sous-étapes - Application — interfaces + implémentations use cases (5 étapes)
- Infrastructure repository — Prisma + multi-tenant + mapper()
- Interface-Adapters — handlers + controllers + factory functions
- Routing + DI — fichier routes déclaratif + module DI
- Tests et validation — health check, validation, CRUD, audit non-bloquant
Table de nommage (extraits)¶
| Élément | Convention |
|---|---|
| Interface use case | I{Action}{Nom}UseCase.ts |
| DTO entrée | Donnees{Action}{Nom} |
| DTO sortie | Resultat{Action}{Nom} |
| Codes erreur | CodeErreur{Action}{Nom} (union type) |
| Exception | Erreur{Nom} extends ErreurMetier |
| ServiceValidation | ServiceValidation{Nom}.ts |
| Controller wrapper | {Nom}ModuleController.ts |
| Constante schema | schema{Action}{Nom} (string, pas Zod) |
Liens connexes¶
- shared/architecture/shared-infra-docker — infrastructure partagée postgres/redis sur laquelle s'appuient les repositories
- shared/flow-connexion-auth — flow auth transversal compatible avec ce pattern (JWT, middleware,
req.utilisateur) - DDD_Module/architecture/deploiement-monorepo — premier projet implémentant ce pattern en production
- DDD_Module/debug/erreurs-deploiement-resolu — 7 pièges documentés lors du premier déploiement
- shared/Meilleur LLM pour le coding en 2026 — comparatif LLM pour le coding Clean Architecture/DDD
- shared/architecture/infrastructure-partagee-postgres-redis — réseau Docker partagé entre projets