Should the "user/developer" who wants to do something with an aggregate only be faced with the aggregate root? So should every method I want to call on an entity deep inside that aggregate be "routed" through the root? That would make the root having a very broad interface with a lot of boring code.
Or ist it allowed to traverse and navigate through the aggregate, picking the entity you want to deal with and invoke the method directly on it?
Or have I to ask the root to give me the entity (not allowed to traverse and navigate through the aggregate from the outside) and then call the method on this entity directly?
the entity designated as the aggregate "root" is the gatekeeper, so all method calls need to go through him first. if you think about it this makes sense. if you hand out an internal entity, how can you be sure it is used in the intended way and the invariants are upheld? also, now your internal details are coupled and making internal structural changes will ripple throughout the system.
remember we strive to design small aggregate so if the surface area is getting too large that might be a sign your aggregate boundaries are wrong.
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)
I have a question regarding the design of aggregates, as presented by Vernon, both in his articles in the DDD community (Effective Aggregate Design, Part 3) as well as on his book (Implementing Domain-Driven Design).
In there, he explores two possible approaches when designing BacklogItem and Task. In one of them Task is not its own Aggregate Root because it runs the "risk of leaving the true invariant unprotected", and the aggregate root is the BacklogItem
However, one of the other guidelines for designing aggregates roots is that access to an entity should only be done through the root itself. Which means that in order to get access to a Task in this approach one would have to now the BacklogItem it belongs to and ask for the backlog item. Normally, though one would just want to see the Tasks is assigned with, and not the backlog item.
In this case we will need to access the entity directly and not via the Backlog item. How does this sit with the proposed design? (I understand that this may be just an educational demo but how would someone have to think this if this was real life?)
Thanks in advance for any answers
In this case we will need to access the entity directly and not via the Backlog item. How does this sit with the proposed design?
That depends: "access directly" is under specified.
Bertrand Mayer's language of command query separation helps here. Queries leave the model unchanged; commands update the model.
Here's the key idea: the unique concern of the aggregate root is commands; any change to the state of the aggregate is achieved by sending a command to the root entity, which may at its discretion delegate the responsibility of changing the state to some other entity.
So if you are accessing the Task to query its current state, that's just fine. But getting the Task so that you can send commands to it directly? that breaks the rules. The aggregate root has the privilege of exclusive access to the commands of all of the entities within the aggregate.
The implication is that you would never invoke Task.estimateRemainingHours() directly; you would instead invoke some analogous method on the aggregate root. BacklogItem.logEstimateFromTeamMember(), perhaps, which would in turn decide which tasks need to be updated.
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
i've been assigned a quite simple project as an exam and i had the idea to develop it using the Domain Driven Design.
Many of you might say that the application is so simple that going with repositories and UoW is just a waste of time, and you probably be correct but i think of it as an opportunity to learn something more.
The application is a "Flight tickets" system and from the following image you could probably well guess it's functionality.
The thing is that i am not sure if i am correctly seperating the aggregates and their roots.
EDIT:
I presented the data model so anyone can spot the whole functionality easily.
The thing is that from an employe perspective the flight as "Rad" said encapsulates the whole functionality and is the aggregate root.
However from an admin perspective, flights are none his bussiness.
He just want to update or add new planes-companies, etc..
So then there is a new aggregate root which is the Airplane which encapsulates the Airplane seats(Entity), the seatType(value object) and the company(Entity) as a new aggregate.
This tends to confuses me as i have an aggregate root(Airplane) inside another aggregate(Flight Aggregate).
Since the aggregate root is consider to be the "CORE" entity which without it the other entities inside it will not make any sense without it, i am thinking about Company. And i conclude that company makes sense without the airplane.
To explain more i think of the scenario where the admin want to just insert a new Company, or want to first load a company and then its airplanes.
DDD principles say that any entities inside the aggregate may only be loaded from the root itself.
So here is the confusion.
Mmm, where is the Aggregate and Aggregate roots here ? This is only Data Model... Not Domain Model.
Aggregate is a cluster of items (Domain Object) that are gathered together, and Aggregate Root are the entity root... (If you consider the Flight Aggregate encapsulates Seats, Location... The Aggregate Root should be Flight entity).
[Edit]
You have to ignore the persistent. In your app you can have many aggregate it depends in your Domain, maybe Flight is an Aggregate and Company another one ;), don't confuse entity and Aggregate...
An aggregate is a group of entities (objects with identity) and maybe value objects (objects without identity, immutable). There is exactly one entity in an aggregate that is the aggregate root. You can easily identify it by checking if the other objects in the aggregate depend on it, for example, if you delete an object of the aggregate root type, the remaining objects don't make sense anymore (in database terms, you'd cascade delete the dependent objects).
The aggregate root is the sole object in the aggregate that gives access to the other types in the aggregate, hence you'll have one repository per aggregate and it returns instances of aggregate root type.
Based on the following definitions from Domain-Driven Design: Tackling Complexity in the Heart of Software,
An aggregate is:
A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the AGGREGATE, designated as the root. A set of consistency rules applies within the AGGREGATE'S boundaries.
I don't think the Aggregate root should hold a reference to the repository. Since the Aggregate root is the only one that should be holding references to its entities and aggregates, they should be private.
How can my repository persist and restore this private data ?
Edit:
Let's take the classic Order, OrderLines example.
An order is the Aggregate root.
It's lines are Entities.
Since the Aggregate root(order) is the only object allowed to hold references to its entities (order lines), I do not understand how would I persist order lines from the repository.
As far as I understand the aggregate root, it must be the place to access all the entities inside it's scope. That means, as long as traditional ORM is used, that you can access the OrderLines throug the Order.
Further it is not forbidden for anyone to grab a reference to the entitiy inside the root, but these references must be volatile (i.e. short lived) and you must obtain the rerefence via the aggregate root.
In terms of DDD you will use a repository to hide data access, the factory might in turn use a factory to assemble the object. The facotry knows well about the internal structure of the object and must be able to build up a new object or restore one from the data the repository hands over.
Perhaps you might also look into CQRS + Event Sourcing which provides a different approach to persisting entities.
Well, most folks consider the repository to be a logical feature of hte aggregate root (since there's only one per aggregate, in traditional DDD), so it does & should have access to the orderlines.
If you really want them to be private, though, you would need to resort to reflection, or else have the aggregate root entity return them in some persistable fashion (perhaps w/ an internal call of some kind).