Choisir un domaine, modéliser en DDD, préparer le projet de fin de Session 1
Bootcode IWA-S04 — Semaine 21, Jour 1
1. Choisir un domaine adapté
2+ agrégats, 4+ use cases — ni trop simple, ni trop ambitieux
2. Modéliser les agrégats
Propriétés, règles métier, invariants à respecter
3. Identifier tous les événements de domaine
Ce qui se passe dans le système : UserCreated, OrderPaid, etc.
4. Définir les use cases avec entrées/sorties
Chaque action métier a un contrat clair (Input → Output)
Présenter le projet de fin de Session 1
Un domaine complet en DDD + Clean Architecture + Inversify
Proposer les domaines possibles
Aider chaque étudiant à choisir le sien
Guider la modélisation
Bounded contexts, agrégats, value objects, événements, use cases
Définir les livrables pour vendredi
Code fonctionnel + présentation de 10 min
Démarrer le document de modélisation
Les étudiants commencent à écrire leur modèle
Un domaine complet, de la modélisation à la démo
🧠
DDD
Bounded contexts, agrégats, événements
🧱
Clean Architecture
core/ → adapters/ → controllers
💉
Inversify
Injection de dépendances, container, Build
La même structure que le monorepo Bootcode — 4 jours pour la mettre en place
# mon-projet/
src/
core/ # domaine pur : agrégats, value objects, events, usecases, errors
adapters/ # infrastructure : TypeORM entities, mappers, repositories, Build
controllers/ # API REST : reçoit HTTP, délègue aux use cases
shared/ # identifiants, types communs, Usecase<I, O>
tests/ # tests unitaires avec repositories in-memory
💡 La règle d'or : core/ ne dépend de RIEN d'externe. Les dépendances pointent toujours vers l'intérieur.
Kick-off & modélisation
Choisir le domaine, écrire le document de modélisation
Implementation core/
Agrégats event-sourcés, value objects, erreurs, use cases
Implementation adapters/
Entités TypeORM, mappers, repositories, classe Build
Controllers + Tests
Endpoints REST, tests unitaires, intégration complète
Présentations & démos
10 min par étudiant : 5 min démo + 5 min questions
Assez riche pour être intéressant, assez simple pour être fini en 4 jours
✅ 2+ agrégats
Au moins deux entités racines avec leurs propres règles
✅ 4+ use cases
Assez d'actions pour montrer le pattern Usecase<I, O>
✅ Des événements de domaine
Des choses qui se passent : création, changement d'état
✅ Des règles métier
Des invariants à faire respecter par les agrégats
💡 Le bon test : « Est-ce que je peux expliquer ce domaine en 2 phrases à quelqu'un de non technique ? »
Des idées pour démarrer — adaptez-les ou inventez la vôtre
🏋️ FitClub
Agrégats : Member, Session. Use cases : inscrire un membre, réserver une session, annuler, marquer présent.
📚 Bibliothèque
Agrégats : Book, Loan. Use cases : emprunter, rendre, réserver, payer une amende.
🍔 FoodOrder
Agrégats : Order, Restaurant. Use cases : créer une commande, confirmer, préparer, livrer.
🎫 Ticketing
Agrégats : Event, Booking. Use cases : créer un event, réserver un siège, payer, annuler.
⚠️ Évitez les domaines type « réseau social complet » ou « ERP » — trop vastes pour 4 jours.
❌ Trop ambitieux
// "Uber-like" — 7 agrégats
User, Driver, Ride,
Payment, Rating,
Notification, Geo
// 20+ use cases, géoloc temps réel...
// → Jamais fini en 4 jours
On passe 3 jours à coder, 0 jour à tester. La démo plante.
✅ Bien calibré
// "Bibliothèque" — 2 agrégats
Book // ISBN, titre, dispo
Loan // memberId, bookId, dates
// 5 use cases : borrow, return,
// reserve, payFine, listOverdue
// → Terminé, testé, démo OK
On modélise jour 1, on code jours 2-4, on démontre jour 5.
Ce que doit contenir votre document
1️⃣
Bounded Context
2️⃣
Agrégats
3️⃣
Value Objects
4️⃣
Événements
5️⃣
Use Cases
La frontière de votre domaine — ce qui est dedans, ce qui est dehors
Définition
Un contexte délimité dans lequel un modèle s'applique. Le même mot peut avoir un sens différent selon le contexte.
Pour le projet
Un seul bounded context suffit. Nommez-le clairement (ex : library, fitclub).
// Exemple : contexte "library"
// Dedans : Book, Loan, Member
// Dehors : Paiement bancaire, notifications email, géoloc
// Le contexte définit ce que votre code va gérer
Les entités racines qui protègent leurs invariants
// Exemple : agrégat Book (event-sourcé)
class Book {
private id: BookId;
private isbn: string;
private title: string;
private isBorrowed: boolean;
// Factory : création
static init(props): Book { ... }
// Rebuild : depuis les événements
static restore(events): Book { ... }
// Méthode métier avec invariant
borrow() {
if (this.isBorrowed) throw new BookAlreadyBorrowedError();
this.recordEvent(new BookBorrowed(...));
}
}
💡 L'agrégat est la seule porte d'entrée pour modifier son état. L'invariant (isBorrowed) est protégé par la méthode borrow().
Des concepts sans identité, définis par leurs valeurs — avec validation
Caractéristiques
Exemples
BookId (identifiant typé)ISBN (avec validation du format)Money (montant + devise)EmailAddress (validé à la création)class ISBN {
private constructor(private readonly value: string) {}
static create(raw: string): ISBN {
if (!isValidIsbn(raw)) throw new InvalidISBNError(raw);
return new ISBN(raw);
}
}
Ce qui s'est passé dans le système — au passé, nommé en PascalCase
Règles de nommage
BookBorrowedBorrowBook (commande)Pourquoi event-sourcing ?
class BookBorrowed implements DomainEvent {
constructor(
readonly bookId: BookId,
readonly memberId: MemberId,
readonly borrowedAt: Date
) {}
}
Chaque action métier = un use case avec un contrat Input → Output
interface BorrowBookInput {
bookId: string;
memberId: string;
}
interface BorrowBookOutput {
loanId: string;
dueDate: Date;
}
class BorrowBook implements Usecase<BorrowBookInput, BorrowBookOutput> {
constructor(private bookRepo: BookRepository) {}
async execute(input: BorrowBookInput): Promise<BorrowBookOutput> {
const book = await this.bookRepo.findById(input.bookId);
book.borrow(); // l'agrégat valide l'invariant
await this.bookRepo.save(book);
return { loanId: ..., dueDate: ... };
}
}
💡 Le use case orchestre : il charge l'agrégat, appelle sa méthode métier, sauvegarde. Il ne contient PAS de logique métier — c'est l'agrégat qui la détient.
Le livrable de fin de journée — à valider avant de coder demain
# modelisation.md
## Contexte
Nom du bounded context + description en 2 phrases
## Agrégats
Book : id, isbn, title, isBorrowed
Loan : id, bookId, memberId, borrowedAt, dueAt
## Value Objects
BookId, ISBN, MemberId
## Événements
BookAdded, BookBorrowed, BookReturned
## Use Cases
AddBook(input) → { bookId }
BorrowBook(input) → { loanId, dueDate }
ReturnBook(input) → { returnedAt }
ListOverdueLoans() → { loans[] }
L'atelier FitClub est votre modèle — la même démarche, appliquée à votre domaine
📋
Le document
Relisez le document de modélisation FitClub produit en S17-J5
🔍
La structure
Mêmes sections : contexte, agrégats, VO, events, use cases
⚖️
Le niveau de détail
Chaque agrégat a ses propriétés ET ses règles métier
✅ Si votre document ressemble à celui de FitClub en termes de clarté, vous êtes prêt à coder demain.
❌ Choisir un domaine trop ambitieux
7 agrégats et 20 use cases = projet jamais fini. Visez 2-3 agrégats, 4-6 use cases.
⚠️ Commencer à coder sans modéliser
La modélisation d'abord, le code ensuite. Sans document clair, on refactor en boucle.
❌ Modélisation trop vague
« Un User avec des trucs » ne suffit pas. Chaque agrégat doit avoir ses propriétés et ses règles explicites.
⚠️ Oublier les événements
Les événements sont la base de l'event-sourcing. Listez-les tous pendant la modélisation.
✅ Le projet est une mise en pratique autonome — le formateur guide mais ne code pas à votre place.
✅ Le domaine doit être simple mais riche : 2+ agrégats, 4+ use cases, terminable en 4 jours.
✅ La modélisation d'abord — pas de code avant d'avoir un document clair.
✅ Les 5 briques : Bounded Context, Agrégats, Value Objects, Événements, Use Cases.
✅ Inspirez-vous de l'atelier FitClub (S17-J5) pour le niveau de détail attendu.
Demain : on implémente le core/ 🚀