Domain-Driven Design : modéliser le métier, pas la base de données
Le DDD, ce n'est pas d'abord une histoire de repositories et d'agrégats,c'est parler aux experts métier jusqu'à ce que le code parle leur langage. Voici comment le DDD stratégique et tactique s'articulent.
Le Domain-Driven Design, formalisé par Eric Evans, a deux volets constamment confondus : le DDD stratégique, qui concerne la façon de découper un grand domaine en morceaux gérables, et le DDD tactique, les patterns,entities, value objects, aggregates,utilisés pour modéliser à l'intérieur d'un de ces morceaux. La plupart des équipes sautent directement aux patterns tactiques en zappant le travail stratégique qui les rend utiles.
DDD stratégique : les bounded contexts
Un bounded context est une frontière à l'intérieur de laquelle un modèle spécifique et son ubiquitous language s'appliquent de façon cohérente. Le mot "Order" ne signifie pas la même chose dans le contexte Ventes (un contrat signé) que dans le contexte Livraison (un colis à router). Vouloir construire un modèle "Order" unifié pour les deux est là où les projets DDD dérapent généralement.
- ✓Identifier les sous-domaines : core (votre avantage concurrentiel), supporting (nécessaire mais pas différenciant), et generic (problèmes déjà résolus,acheter, pas construire).
- ✓Dessiner une context map : quels contextes existent, et comment se relient-ils ?
- ✓Choisir les relations délibérément : shared kernel, customer-supplier, ou anticorruption layer en intégrant un contexte qu'on ne contrôle pas.
L'ubiquitous language
Le vocabulaire utilisé par les experts métier en conversation doit être le même vocabulaire dans le code,noms de classes, de méthodes, même de variables. Si le code a besoin d'une couche de traduction entre "ce que le métier appelle ça" et "ce que le code appelle ça", cet écart est là où bugs et malentendus s'accumulent.
DDD tactique : value objects, entities, aggregates
Un value object n'a pas d'identité,il est défini entièrement par ses attributs et devrait être immuable. Une entity a une identité qui persiste même quand ses attributs changent.
// Value Object : pas d'identité, défini entièrement par ses attributs, immuable
final readonly class Money
{
public function __construct(
public int $amount,
public string $currency,
) {}
public function equals(Money $other): bool
{
return $this->amount === $other->amount && $this->currency === $other->currency;
}
}
// Entity : a une identité qui persiste même si ses attributs changent
final class Order
{
public function __construct(
private readonly OrderId $id, // identité
private OrderStatus $status,
private Money $total,
) {}
}Les aggregates sont des frontières de cohérence, pas des graphes d'objets
Un aggregate regroupe des entities et value objects qui doivent rester cohérents ensemble, et expose exactement un point d'entrée : l'aggregate root. Garder les aggregates petits,référencer les autres aggregates par ID, pas par référence d'objet,et traiter un aggregate par transaction comme règle par défaut.
final class Order
{
private array $lines = [];
private OrderStatus $status;
public function addLine(ProductId $product, int $quantity): void
{
if ($this->status !== OrderStatus::Draft) {
throw new DomainException('Impossible de modifier une commande confirmée.');
}
$this->lines[] = new OrderLine($product, $quantity);
}
public function confirm(): void
{
if (empty($this->lines)) {
throw new DomainException('Impossible de confirmer une commande sans lignes.');
}
$this->status = OrderStatus::Confirmed;
}
}L'erreur DDD la plus courante est le modèle de domaine anémique : des classes qui ne sont que des sacs de données avec getters et setters, pendant que toute la logique métier vit dans une couche "service" séparée. Mettez les invariants à l'intérieur de l'aggregate lui-même,si une règle peut être violée en appelant un setter, le modèle ne fait pas son travail.
Quand le DDD vaut l'investissement
- ✓Les règles métier sont complexes et changent fréquemment,pas du simple CRUD.
- ✓Plusieurs équipes travaillent sur différents sous-domaines et ont besoin de frontières de responsabilité claires.
- ✓Les experts métier sont disponibles et prêts à collaborer étroitement avec l'ingénierie.
Le plus gros retour du DDD n'est pas les patterns tactiques,c'est le vocabulaire partagé qu'il impose entre ingénieurs et métier. Commencer par les conversations et les bounded contexts. Les aggregates et repositories sont un moyen, pas le but.
Besoin d'aide sur ce sujet ? Développement Full Stack
Découvrir ce service →