Qu'est-ce qu'une racine agrégée?

447

J'essaie de comprendre comment utiliser correctement le modèle de référentiel. Le concept central d'une racine agrégée revient sans cesse. Lorsque je cherche à la fois sur le Web et sur Stack Overflow pour savoir ce qu'est une racine agrégée, je continue à trouver des discussions à leur sujet et des liens morts vers des pages qui sont censées contenir des définitions de base.

Dans le contexte du modèle de référentiel, qu'est-ce qu'une racine agrégée?

Dinah
la source
16
Pensez à revoir les études de cas suivantes. Conception d'agrégats efficaces Partie I: Modélisation d'un agrégat unique dddcommunity.org/wp-content/uploads/files/pdf_articles/… Partie II: Faire fonctionner les agrégats ensemble dddcommunity.org/wp-content/uploads/files/pdf_articles/… Partie III: Obtenir des informations grâce à la découverte dddcommunity.org/wp-content/uploads/files/pdf_articles/…
Ben Vitale

Réponses:

310

Dans le contexte du modèle de référentiel, les racines d'agrégat sont les seuls objets que votre code client charge à partir du référentiel.

Le référentiel encapsule l'accès aux objets enfants - du point de vue de l'appelant, il les charge automatiquement, soit en même temps que la racine est chargée ou quand ils sont réellement nécessaires (comme avec le chargement paresseux).

Par exemple, vous pourriez avoir un Orderobjet qui encapsule des opérations sur plusieurs LineItemobjets. Votre code client ne chargerait jamais les LineItemobjets directement, juste celui Orderqui les contient, qui serait la racine agrégée de cette partie de votre domaine.

Jeff Sternal
la source
21
En théorie, si le code client avait besoin du LineItem à d'autres fins, cela formerait-il un agrégat séparé (en supposant qu'il y aurait d'autres objets impliqués non liés à l'objet Order)?
Ahmad
20
@Ahmad, d'autres agrégats peuvent faire référence à LineItems en tant que données en lecture seule, ils ne peuvent tout simplement pas les modifier . Si d'autres agrégats pouvaient les modifier, vous ne pouviez pas protéger les invariants de l'ordre (ni les éléments de campagne).
Jeff Sternal
4
Jetez un œil à cela, par exemple lostechies.com/blogs/jimmy_bogard/archive/2010/02/23/… . Dans l'exemple, le client est un invariant de la commande, non? Cependant, le client peut également être une autre racine agrégée? Ou est-ce que je manque une compréhension fondamentale ici?
Ahmad
3
@Jeff Vous avez dit "ils ne peuvent tout simplement pas les changer" - est-ce exécutoire ou conventionnel?
Neil Barnwell
4
@Neil: Je l'imposerais en utilisant les mécanismes de langage disponibles - par exemple, en créant une classe immuable pour représenter les données.
Jeff Sternal
206

De Evans DDD:

Un AGRÉGAT est un cluster d'objets associés que nous traitons comme une unité dans le but de modifier les données. Chaque AGRÉGAT a une racine et une frontière. La limite définit ce qui se trouve à l'intérieur de l'agrégat. La racine est une ENTITE unique et spécifique contenue dans AGRÉGAT.

Et:

La racine est le seul membre de AGGREGATE auquel les objets extérieurs sont autorisés à contenir des références à [.]

Cela signifie que les racines agrégées sont les seuls objets qui peuvent être chargés à partir d'un référentiel.

Un exemple est un modèle contenant une Customerentité et une Addressentité. Nous n'aurions jamais accès à une Addressentité directement à partir du modèle car cela n'a pas de sens sans le contexte d'un associé Customer. Nous pourrions donc dire que Customeret Addressformer ensemble un agrégat et c'est Customerune racine agrégée.

Jason
la source
57
Mise à jour d'Eric Evans : insister sur le fait que les racines d'agrégat sont des limites de cohérence pour les transactions / accès concurrents et souligner que les entités externes ne peuvent pas contenir de références aux entités enfants d'autres agrégats.
Brian Low
3
Donc le verbiage me confond toujours. Each AGGREGATE has a rootet The root is the only *member* of the AGGREGATE- ce verbage implique que la racine est une propriété sur l'agrégat. Mais dans tous les exemples, c'est l'inverse: la racine contient des propriétés qui sont des agrégats. Pouvez-vous clarifier?
Sinaesthetic
1
Pour que ma langue soit correcte, la Customerclasse est-elle considérée comme la racine agrégée ou les Customer instances ?
Joe
1
D'une manière générale, dans le paradigme de la ligne de commande client, le client serait la racine agrégée. L'instance d'un client serait une instance de cette racine agrégée. Lorsque vous parlez d'une racine agrégée appelée client, vous discutez de la construction logique d'un client qui constitue l'instance d'un client. Une collection de clients n'est qu'une collection.
Ibrahim Malluf
111

La racine agrégée est un nom complexe pour une idée simple.


Idée générale

Un diagramme de classe bien conçu encapsule ses éléments internes. Le point par lequel vous accédez à cette structure est appelé aggregate root.

entrez la description de l'image ici

Les composants internes de votre solution peuvent être très compliqués, mais l'utilisateur de cette hiérarchie utilisera simplement root.doSomethingWhichHasBusinessMeaning().


Exemple

Vérifiez cette hiérarchie de classes simple entrez la description de l'image ici

Comment voulez-vous conduire votre voiture? Choisissez une meilleure API

Option A (cela fonctionne simplement):

car.ride();

Option B (l'utilisateur a accès aux inernals de classe):

if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
    for (Wheel w: car:getWheels()){
        w.spin();
    }
}

Si vous pensez que l'option A est meilleure, alors félicitations. Vous obtenez la raison principale derrière aggregate root.


La racine agrégée encapsule plusieurs classes. vous pouvez manipuler toute la hiérarchie uniquement via l'objet principal.

Marcin Szymczak
la source
17
J'aime l'exemple, mais j'ai du mal à trouver un scénario dans lequel le client devrait référencer le moteur. Il semble que le moteur devrait être encapsulé derrière la voiture. Pouvez-vous nous en dire un peu plus?
emragins
À mon avis, le moteur lui-même doit être à l'intérieur d'un modèle spécifique à une voiture, par exemple une BMW série 5 avec un moteur de 3000 cm3. Avec cette modélisation, le moteur est un composant pour une voiture.
Parama Dharmika
1
@ParamaDharmika bien sûr, vous pouvez le modéliser de cette façon. Cela dépend de la façon dont les clients sont «avancés» avec les voitures. Dans le modèle de base, il devrait avoir accès à carla racine agrégée. Vous pouvez également autoriser une situation comme celle du dessin. La bonne solution dépend du modèle commercial de l'application. Cela peut être différent dans chaque cas.
Marcin Szymczak
1
@MarcinSzymczak correct, je ne pourrais pas être plus d'accord que la solution dépend du modèle de domaine lui
Parama Dharmika
En fait, la roue est un agrégat qui contient des pneus (et d'autres pièces). Si vos règles exigent que l'agrégat Wheel ne soit accessible que via le Car Root-Aggregate, le moteur est également contenu dans le Car Root Aggregate et ne doit pas être accessible en dehors de la voiture. C'est dans le domaine d'une instance Car. Un propriétaire de voiture (client) ne ferait référence à un moteur que dans le contexte de sa voiture.
Ibrahim Malluf
35

Imaginez que vous ayez une entité Ordinateur, cette entité ne peut pas non plus vivre sans son entité Logiciel et son entité Matériel. Ceux-ci forment l' Computeragrégat, le mini-écosystème de la partie informatique du domaine.

La racine agrégée est l'entité mère à l'intérieur de l'agrégat (dans notre cas Computer), il est courant que votre référentiel ne fonctionne qu'avec les entités qui sont des racines agrégées, et cette entité est responsable de l'initialisation des autres entités.

Considérez la racine d'agrégat comme point d'entrée d'un agrégat.

En code C #:

public class Computer : IEntity, IAggregateRoot
{
    public Hardware Hardware { get; set; }
    public Software Software { get; set; }
}

public class Hardware : IEntity { }
public class Software : IValueObject { }

public class Repository<T> : IRepository<T> where T : IAggregateRoot {}

Gardez à l'esprit que le matériel serait probablement aussi un ValueObject (ne possède pas d'identité à lui seul), considérez-le comme un exemple uniquement.

Francisco Aquino
la source
6
where T : IAggregateRoot- Celui-ci a fait ma journée
Cristian E.
Le libellé est un peu contradictoire, je pense et c'est ce qui m'embrouille en essayant d'apprendre cela. Vous dites que l'ordinateur est l'agrégat, mais vous dites ensuite que la racine serait l'entité mère à l'intérieur de l'agrégat. Alors, quelle est l'entité "vaisseau mère" à l'intérieur de l'agrégat dans cet exemple?
Sinaesthetic
Salutations de l'avenir !. Ce que le gars veut dire, c'est que l'ordinateur en lui-même est la racine de l'agrégat, tandis que l'ordinateur ET tout ce qu'il contient est l'agrégat. Ou plus clairement: le cas en lui-même est la racine de l'agrégat, tandis que tout l'ordinateur est l'agrégat (la collection de tout ce qui constitue "l'ordinateur, par exemple l'éclairage RVB, le matériel, l'alimentation, le système d'exploitation, etc.)
Captain Kenpachi
La technique IAggregateRoot apparaît dans la documentation de Microsoft: docs.microsoft.com/en-us/dotnet/architecture/microservices/…
Samuel Danielson
16

Si vous suivez une approche basée sur la base de données, la racine agrégée est généralement la table du côté 1 d'une relation 1-plusieurs.

L'exemple le plus courant étant une personne. Chaque personne a plusieurs adresses, un ou plusieurs bulletins de paie, factures, entrées CRM, etc. Ce n'est pas toujours le cas, mais 9/10 fois.

Nous travaillons actuellement sur une plateforme de commerce électronique et nous avons essentiellement deux racines agrégées:

  1. Les clients
  2. Les vendeurs

Les clients fournissent des informations de contact, nous leur attribuons des transactions, les transactions obtiennent des éléments de ligne, etc.

Les vendeurs vendent des produits, ont des contacts, des pages sur nous, des offres spéciales, etc.

Ceux-ci sont pris en charge par le référentiel client et vendeur respectivement.

Capitaine Kenpachi
la source
8
Si vous suivez une approche basée sur la base de données, vous ne pratiquez pas la conception pilotée par domaine, vous suivez la conception pilotée par les données.
Sinaesthetic
5
C'est un forum de questions / réponses où les gens viennent pour résoudre des problèmes et / ou apprendre - Ce n'était pas moi qui vous piquais. Par définition, DDD est un état d'esprit plus que toute autre chose et il prête à confusion pour beaucoup, c'est pourquoi je m'assurais que le commentaire était fait pour ceux qui apprennent DDD dans le but d'aider à atténuer toute confusion potentielle des méthodologies de conception.
Sinaesthetic
12

Dinah:

Dans le contexte d'un référentiel, la racine agrégée est une entité sans entité parent. Il contient zéro, une ou plusieurs entités enfants dont l'existence dépend du parent pour son identité. C'est une relation un à plusieurs dans un référentiel. Ces entités enfants sont de simples agrégats.

entrez la description de l'image ici

Ibrahim Malluf
la source
1
Donc, si vous êtes un vendeur de voitures, alors Car serait une racine globale à part entière? Parce que vous pouvez avoir beaucoup de voitures qui n'ont pas encore de client
JorgeeFG
2
@JorgeeFG la vraie réponse est que personne n'a la moindre idée du tout. Il y a tellement d'informations contradictoires disséminées.
Mardoxx
3
Les entités enfants ne sont pas des agrégats, ce sont juste des entités qui se trouvent être des membres de l'agrégat dans lequel la racine agrégée contrôle. Un «agrégat» est un regroupement logique d'entités.
Sinaesthetic
@JorgeeFG cela dépend vraiment du contexte borné que vous concevez. Si vous êtes un vendeur de voitures, alors quelque chose comme un Carshop devient la racine agrégée, et en dessous, il suit les voitures ...
jokab
8

À partir d'un lien brisé :

Dans un agrégat, il y a une racine d'agrégat. La racine d'agrégat est l'entité parente de toutes les autres entités et objets de valeur au sein de l'agrégat.

Un référentiel fonctionne sur une racine agrégée.

Plus d'informations peuvent également être trouvées ici .

Otávio Décio
la source
4
Je vous remercie. C'est certainement le lien brisé le plus courant et le plus frustrant que je connaisse continuellement.
Dinah
De plus, la formulation semble à l'envers. Comment la racine peut-elle être dans l'agrégat et être son parent en même temps?
Sinaesthetic
1
La racine agrégée est la classe racine. Un agrégat ordinaire est toujours contenu dans une racine d'agrégat. En utilisant le diagramme posé ci-dessus ... Le client est la racine agrégée. Le Client peut posséder une ou plusieurs voitures. Les voitures sont des agrégats par rapport au client. Les voitures ont un moteur. Le moteur est un agrégat contenu dans l'agrégat de voiture. Ce qui fait du client une racine agrégée est l'hypothèse du modèle selon laquelle l'accès à une voiture ou à ses composants se fait toujours par le client propriétaire de la voiture.
Ibrahim Malluf
8

L'agrégat signifie la collecte de quelque chose.
racine est comme le nœud supérieur de l'arbre, d'où nous pouvons accéder à tout comme le <html>nœud dans le document de la page Web.
Blog Analogy, Un utilisateur peut avoir de nombreux articles et chaque article peut avoir de nombreux commentaires. Donc, si nous récupérons un utilisateur, il peut agir en tant que root pour accéder à tous les messages associés et autres commentaires de ces messages. Ce sont tous ensemble dit être collection ou agrégé

palash140
la source
1

L'agrégat est l'endroit où vous protégez vos invariants et forcez la cohérence en limitant son accès à la racine agrégée. N'oubliez pas, l'agrégat doit se baser sur les règles métier et les invariants de votre projet, et non sur la relation avec la base de données. vous ne devez injecter aucun référentiel et aucune requête n'est autorisée.

Alireza Rahmani Khalili
la source