After reading Evans and Vernon I still have one fundamental Question.
I'm aware that of course one entity (instance) can only be in one aggregate.
But can an entity class be used in multiple aggregates (classes)?
For clarification, I ask on the class level.
Other formulation: Can two different aggregate root classes (!) aggregate the same entity class? Of course any of the entity instances has to belong to only one instance of one of the two aggregate root classes.
For Value Object classes this seems to be possible. At least I have the impression that a value object class for example for "money" can be used in different aggregate types.
As you rightly pointed out, Entity instances shouldn't be shared between aggregates, as one aggregate wouldn't be aware of changes to the entity made through another aggregate and couldn't enforce its invariants.
Entity classes could theoretically be shared between 2 aggregates, but, by the same reasoning, only if the set of entity instances in an Aggregate is disjoint from the other. This raises questions :
Why would you want that in the first place ? If there are two big categories of instances of the same class, isn't this a sign that there are two semantically different concepts, which should each have their own class, or at least subclass ?
How do you prevent an entity instance belonging to one aggregate from being added to the other, at runtime (bug), or at programming time (uneducated developer decision) ?
Value Objects escape these issues because they are usually immutable or treated as such -- you don't modify a VO, you modify its parent Entity so that it points to a whole new VO instance. Also, as Value Objects don't have an identity, it doesn't make much sense to say that the "same" VO is in two aggregates at the same time. You can thus safely reuse a VO type in different aggregate classes.
I think Udi's blog post here is very relevant - he suggests that entities can not only be part of multiple aggregates but also be an aggregate root themselves. It is a bit of a funny one to get your head around! http://udidahan.com/2009/06/29/dont-create-aggregate-roots/
Related
If we are working on a sub-domain where we're only dealing with a read-only scenario, meaning that our entities and value objects will not be changed, does it make sense to create aggregates composed by roots and its children or should each entity of this context map to a single aggregate?
Imagine that we've entity A and entity B.
In a context where modifications are made, we create an aggregate composed by entity A and entity B, where A is the aggregate root (let's say that B can't live without A and there are some invariants involved).
If we move the same entities to a different context where no modifications are made, does it make sense to keep this aggregate or should we create an aggregate for entity A and a different one for entity B?
In 2019, there's fairly large support for the idea that in a read only scenario, you don't bother with the domain model at all.
Just load the data directly into whatever read only data structure makes sense to support the use case.
See also: cqrs.
The first thing is if B cant live without A and there are some invariants involved, to me A is an Aggregate root, with B being an entity that belongs to it.
Aggregate roots represent a real world concept and dont just exist for the convenience of modification. In many of our applications, we don't modify state of our aggregate roots once created - i.e. we in effect have immutable aggregate roots. These would have some logic for design by contract checks/invariant checks etc but they are in effect anaemic as there is no "Update" methods due to its immutability. Since the "blue book" was written by Eric Evans, alot of things have changed, e.g. the concept of NoSql database have become very popular, functional programming concepts have become very influential rising to more advanced DDD style architectures being recommended such as CQRS. So for example, rather than doing updates to a database I can append (i.e. insert) instead. This leads to aggregates no longer having to be "updated". This leads to leaner anaemic types but this is what we want in this context. The issue before with anaemic types was that "update logic" for a given type was put elsewhere in the codebase instead of being put into the type itself. However if you do not require "update logic" in the first place then you dont have that problem!
If for example there is an Order with many OrderItems, we would create an Order aggregate root and an OrderItem entity. Its a very important concept to distill your domain to properly identify what are aggregates, entities and value types.
Then creation of domain services, repositories etc just flows naturally. For example, aggregate roots and repositories are 1 to 1 i.e. in the example above we would have an Order repository and not have an OrderItem repository. That way your main domain concepts are spread throughout your code in a predictable and easy to understand way.
Finally, in your specific question I would not treat them as the same entities. In one context, you seem to need modification logic - in the other they you dont - they are separate domain concepts to me.
In context where modifications are made: A=agg root, B=entity.
In context without modifications: A=agg root (immutable), B=entity(immutable)
Is there any drawbacks when a concept is modeled in a bounded context as a root entity and in another bounded context as a child entity (same identity in both BC's)?
From Eric Evans DDD:
ENTITIES other than the root have local identity, but it only needs to
be unique within the aggregate, since no outside object can ever see
it out of the context of the root ENTITY.
The concept would have global identity even when it plays the role of child entity.
I think Evan's point is to avoid modification of the child entity outside its aggregate, but in another BC no invariants would be violated.
What do you think?
Using a global id here is perfectly fine. I think Eric meant that the id should be unique at least within its parent aggregate.
I have a lot of similar cases in the systems we work on, and that's the exact way we've designed it.
The drawbacks, as I see it, are the leaking of concepts between Bounded Contexts when sharing Entities.
At first it may seem like a good idea in terms of preventing duplication however you will pay for it later. I can see a scenario where changes in one context make sense but not in the other.
This is fine; the 'child entity' is an immutable value object in the context of the 'root entity'. In other words, the root entity may reference child entities, but it cannot alter their attributes.
I mean, is there any PersonAggregate class? I understand it doesn't exist. I only have an entity acting as aggregate root. Is it correct?
I only have an entity acting as aggregate root. Is it correct?
That's correct.
The aggregate is implicit - it's the boundary that separates two disjoint sets of state that can be modified independently of each other. Equivalently, the aggregate is a graph of business state within a model that can be modified without consulting state outside the graph, and vice versa.
The aggregate root is explicit. That's the single entity in the graph that is exposed - which is to say that it serves as the entry point through which all modifications to the graph must pass.
Hypothetically, you could implement an aggregate that has two different exposed entities that can each execute commands to modify the state; Evans introduced the notion of a single aggregate root because multiple entry points is difficult to get correct.
I have seen both solutions used in projects, but most often people do not use this suffix.
One interesting solution for this is make aggregate classes public and non-aggregate classes package(default). You'd see directly from your IDE which classes have which visibility and you can determine easily where is an aggregate. Additionally non-public class cannot be used outside package which is an original intent.
My understanding is an Aggregate Root is an Entity but an Entity might not be an Aggregate Root. Therefore, I view 'Aggregate Root' as more of a stereotype.
Not in domain-driven design. That would be exposing technological jargon, essentially implementation detail, to the domain experts
From a post I read it seems that Entity is just a subset of Aggregate. I've read about the two patterns in both Domain-Driven Design and Implementing Domain-Driven Design, and I'm trying to understand the UML difference between them.
Let's consider a simple class. It's a Letter holding a message, a receiver, and possibly the sender.
I guess this Letter class would be considered an Entity?
Now let's say we want to expand our parcel business to be able to send also Packages, then it could look like the following.
Since all the Items in the Package will be lost if the whole Package is lost, we use a UML Composition relation (a filled diamond). We also want to preserve the Package's consistency by prohibiting Items from being changed or removed from outside the Package. The description of Aggregate reads
The aggregate root guarantees the consistency of changes being made
within the aggregate by forbidding external objects from holding
references to its members.
We therefore make sure the Composition relation is hidden, and with preserved invariants, within the Aggregate.
My question is:
Can we say that the UML difference between Entity and Aggregate is that Entity does not contain any Composition relation whereas Aggregate contains at least one Composition relation?
To answer your question, no you can't say that. An aggregate root is entity itself, and may or may not be composed of child entities. The child entities can also be composed of other entities as well (though not recommended usually).
The aggregate root is responsible for maintaining the state and enforcing the invariants of both itself and it's child entities.
So to recap, an aggregate and a child entity can each have 0 or more child entities. All child entities require an aggregate root however.
An Entity represents the M(odel) in MVC. It's usually denoted as a <<entity>> stereotyped class.
An Aggregate is a synonym for a class which aggregates different other classes. That means it needs the other classes for its life time. There's also a Composite which is similar except that the related class instances will die along with the composite class.
To answer your final question: an Entity is atomar. It does not aggregate anything.
Edit Since I just encountered it for my work: There are Entities which compose/aggregate other entities. 30 years ago at university we called them trapeze for they hang between two other entities and relate them. Nowadays I'd call them association class.
An Entity in Domain-Driven-Design (DDD) is just a class stereotype in UML terms. That stereotype indicates to you that the object is identified by an explicit unique identifier, rather than its attributes.
Objects in an object model collaborate together. Together they form object graphs. An Aggregate represents a group of objects that need to be considered together because not doing so would potentially leave one or more of the objects in an invalid state.
"Can we say that the UML difference between Entity and Aggregate is that Entity does not contain any Composition relation whereas Aggregate contains at least one Composition relation?"
No. A UML composition or aggregation association is unrelated to the concept of DDD Aggregate or Entity.
For example, one can represent a Transaction-LineItem relationship in UML without composition or (UML) aggregation.
Transaction --- 1 -------- 0..* --- LineItem
Both these objects as modeled above would need to be part of the same (DDD) Aggregate because they need to be treated as a pair. If mistreated individually, one could make their combined states invalid or incorrect.
I've read countless posts on differences between Entities and Value objects and while I do think that at least conceptually I understand how the two differ, it appears that in some of these posts authors consider a particular domain concept to be a VO simply because it is immutable ( thus its state will never change, at least within that particular domain model ).
Do you agree that if the state of an object will never change within particular domain model, then this object should never be an entity? Why?
thank you
Do you agree that if the state of an object will never change within
particular domain model, then this object should never be an entity?
Why?
I'd say 90+% of entities will change at some point in their lifetime. But some entities might be unchangeable because of their nature in the domain - a PrepaidPhoneCard, a TransferOrder in a banking system for instance.
Some also like to make their Entities immutable by default because it helps shaping a design that preserves invariants and makes domain operations explicit : http://www.jefclaes.be/2013/04/designing-entities-immutability-first.html
The object could be an entity if you need to identify it.
According to the DDD book, if an object has identity and lifecycle but will not change over time, you could also consider the object as an event.
In two words: yes, they can.
Eric Evans in his book tells about a "thread of continuity" inherent to entities. In layman terms, an entity can be POSTed by a front-end as JSON, get converted into a DTO by a framework, then into a domain object, then into a DTO again and then finally get stored in a database table. During all these transformations the entity will be easily distinguishable because it possesses one or more unique business ids.
With this in mind, aren't some forms of immutability a form of another thread of continuity? Imagine copy-on-write: all of the immutable object's copies are formally different objects representing it at different points of its lifetime. Yet, there is a unique id allowing us to say it's the same entity.
Now, let's talk about the "extreme" form of immutability: read-only objects. Can an entity be a read-only object? Sure, a good example is a credit card statement.
Summing up:
One entity can exist in many forms. In fact, you will almost always have multiple representations of your entity in a program without being aware about it.
A true requirement an entity is an existence of a unique business identity (not a surrogate id that is used for technical purposes) that makes it distinguishable from other entities.
Entities can be immutable, whether we talk about COW or read-only objects.