Oyun Kitabı
Code DDD : entité, objet de valeur et agrégat (Code Ddd Entite Objet DE Valeur Et Agregat)
Comment fonctionnent les modèles tactiques DDD ? Limites de l'objet de valeur, de l'entité, de l'agrégat, du service de domaine, du service d'application et du référentiel avec un exemple de commande réelle…
DDD - Langage commercial du logiciel
Partie 2 de 4
Question de cet article
Dans la première partie, nous sommes partis du langage et des règles de l’entreprise. Maintenant, la question est : où conservons-nous ces décisions dans le code ? Nous utiliserons le même domaine e-commerce : argent, ligne de commande, flux de commande et de paiement.```text Money + Address + Quantity → Value Object OrderLine + Order → Entity Order (Root) + OrderLine → Aggregate Repository → Aggregate Root'u yükler ve kaydeder
## Concepts à la première mention```text
📦 Value Object
Kimliği olmayan, değeriyle tanımlanan ve değişmez tutulması gereken kavram.
📦 Entity
Nitelikleri değişse de kimliği boyunca aynı kalan nesne.
📦 Aggregate
Birlikte tutarlı kalması gereken nesnelerin transaction sınırı.
📦 Aggregate Root
Aggregate'e dışarıdan girilebilen tek kapı.
```Par exemple, deux `Money(100, "TRY")` représentent la même valeur ; Deux commandes ont des identités différentes même si leurs sommes sont les mêmes.
## Commencer par l'objet valeur
Value Object enseigne le mieux la façon de penser en DDD. `decimal` n'est pas de l'argent en soi : il comporte des règles de devise, d'arrondi, de remise et de fiscalité. Stockez ces règles dans le concept plutôt que de les distribuer à la couche service.```csharp
public sealed record Money(decimal Amount, string Currency)
{
public Money Add(Money other)
{
if (Currency != other.Currency) throw new DomainException("Currency mismatch");
return new Money(Amount + other.Amount, Currency);
}
}
```L'objet de valeur est immuable : lorsque la valeur change, une nouvelle instance est créée. Ainsi, la même adresse, e-mail, plage de dates ou valeur monétaire ne produit pas d’effets secondaires inattendus dans les différentes étapes de transaction. La comparaison est effectuée en fonction du contexte ; Par conséquent, le coût d’égalité est O(m) avec le nombre de champs, mais le coût de modification diminue car la règle métier reste au même endroit.
## Entité : identité et cycle de vie
`Order` est une entité. Peut changer son adresse ou son total ; C'est toujours le même ordre. La différence ne réside pas dans l'utilisation de setters, mais dans la modélisation de la transition en tant que comportement au travail.```text
❌ order.Status = Paid
✓ order.ConfirmPayment(payment)
❌ order.Total = total - discount
✓ order.ApplyDiscount(discount)
````ConfirmPayment` vérifie en un seul endroit comme preuve de paiement, que la commande n'a pas été annulée et que la transition est légale. La tâche de l'entité n'est pas de déplacer toutes les données, mais d'éviter les situations invalides au cours de son cycle de vie.
## Agrégat : pas un groupe d'objets, mais une limite de cohérence
La commande et ses lignes doivent rester cohérentes au sein d'une même transaction : le nombre de lignes est positif, le total est égal à la somme des lignes, et la ligne ne peut plus être modifiée une fois la commande confirmée. Ainsi, `Order` devient la racine agrégée pour `OrderLine`.```text
Order aggregate
├─ OrderLine
├─ ShippingAddress
└─ Total
Dış dünya → Order.AddLine() / Order.ConfirmPayment()
Dış dünya ↛ OrderLine'a doğrudan yazmaz
```Rendre Aggregate grand produit des verrous et des conflits de versions, pas de sécurité. Mettez à jour le plus grand agrégat possible dans la demande d'écriture. Connectez-vous à un autre agrégat par ID au lieu de référence d'objet ; Si une coordination est requise, utilisez l’orchestration d’événements de domaine ou d’applications. Cela limite les conflits de concurrence optimistes et les coûts d’installation inutiles.
## Service de domaine et service d'application
Si une règle n'appartient pas naturellement à un seul Agrégat, il peut s'agir d'un Service de Domaine : par exemple, une tarification basée sur le taux de change. En revanche, le service d'application gère le cas d'utilisation : charge la commande, appelle le comportement, l'enregistre et termine la transaction.
| Couche | Responsabilité |
| --- | --- |
| Objet de valeur / Entité / Agrégat | Maintien des règles métier et des invariants |
| Service de domaine | Compte de domaine pur n'appartenant pas à Aggregate |
| Service de candidatures | Orchestration de cas d'utilisation, appels de transactions et d'adaptateurs |
Mettre des règles dans Application Service est un retour du modèle anémique à la couche service.
## Dépôt : pas d'API de table
Le référentiel donne au domaine la sensation d'une collection en mémoire ; Ce n'est pas un détail SQL ou ORM. Au lieu de créer un référentiel pour chaque table, utilisez-le uniquement pour les racines agrégées. Le remplacement direct de l'entité enfant par `OrderLineRepository.Find()` contourne les règles maintenues par Root.```text
order = orderRepository.get(orderId)
order.confirmPayment(payment)
orderRepository.save(order)
```Cette limite permet également une vérification indépendante de l'infrastructure du comportement du domaine avec un référentiel fictif lors des tests. Le constructeur vide d'ORM ou l'exigence de chargement rapide ne devraient pas façonner le modèle de domaine ; Le mappage relève de la responsabilité de l'adaptateur.
## Correspondances qui créent une fausse confiance```text
❌ Value Object = küçük DTO
✓ Value Object değer, doğrulama ve davranış taşır.
❌ Aggregate = mümkün olduğunca büyük nesne grafiği
✓ Aggregate = küçük tutulmuş transaction ve consistency boundary.
❌ Domain Service = iş kuralı çöplüğü
✓ Yalnızca tek Aggregate'e ait olmayan saf domain davranışı.
❌ Repository = her tablo için CRUD API
✓ Repository = Aggregate Root'un kalıcılık sınırı.
Liste de contrôle de candidature
- Des concepts tels que
Money,Email,Address,Quantitycirculent-ils en tant que primitifs ? - Chaque comportement d'entité empêche-t-il réellement un état invalide ?
- Une demande d'écriture tente-t-elle de mettre à jour atomiquement plusieurs agrégats ?
- Le service applicatif prend-il des décisions ou orchestre-t-il simplement ?
- Le référentiel installe-t-il uniquement les racines agrégées ?
Commencez par la règle métier la plus coûteuse ; Ne transformez pas l'ensemble du système en DDD tactique d'un seul coup.
Ce qu'il faut retenir de cet article
Value Object porte la valeur et les règles du concept. L'entité conserve son identité et son cycle de vie. Aggregate définit une petite limite de transaction pour des raisons de cohérence. Le référentiel rassemble cette limite avec la permanence.
L'objectif du DDD tactique n'est pas d'ajouter plus de classes, mais d'empêcher la règle métier de s'infiltrer dans la mauvaise couche.
Dans la section suivante, nous examinerons comment parler de ces frontières dans un système plus large : contexte délimité, cartographie du contexte et décomposition au sein du monolithe.
FAQ
Frequently asked questions
Qu'est-ce qu'un objet de valeur ?
Un concept qui n'a pas d'identité, est défini par sa valeur et doit rester constant.
Qu’est-ce que l’entité ?
Un objet qui reste le même tout au long de son identité même si ses qualités changent.
"Value Object = small DTO" est-il correct ?
L'objet de valeur comporte de la valeur, une validation et un comportement.
Que corrige cette section ?
Dans la première partie, nous sommes partis du langage et des règles de l’entreprise. Maintenant, la question est : où conservons-nous ces décisions dans le code ? Nous utiliserons le même domaine e-commerce : argent, ligne de commande, flux de commande et de paiement. Dans la première partie, nous sommes partis du langage et des règles de l’entreprise. Maintenant, la question est : où conservons-nous ces décisions dans le code ? Nous utiliserons le même domaine e-commerce : argent, ligne de commande, flux de commande et de paiement.
Principes d'ingénierie appris
- Value Object combine des données primitives avec la sémantique métier et la validation.
- L'agrégat doit être petit et avoir une limite de cohérence claire.
- Le service d'application gère le processus ; le comportement du domaine décide.
Continuer la lecture
Continuer la lecture
Suivant en série
Comment DDD fonctionne-t-il sur les grands systèmes ?
Comment DDD évolue-t-il sur de grands systèmes ? Contexte délimité, cartographie du contexte, loi de Conway, monolithe modulaire, limites des microservices…
Suivant en série
DDD - Concevoir des logiciels pour l'entreprise, pas pour la base de données
Qu’est-ce que la conception pilotée par domaine ? Un guide sur les limites de la conception basée sur les bases de données, la puissance du langage commun…
Même série
DDD en production : systèmes distribués et stratégies de modernisation
Comment implémenter DDD dans un environnement de production ? Guide de conversion hérité avec Event Storming, Saga, Transactional Outbox, Anti-Corruption…