I'm new to DDD and I want to clearly understand each domain object structure and role:
Aggregate Root:
1.1. The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root? (Yes/No)
1.2. Can an aggregate root contain only value objects ? for example User root, it contain only address, phone, things which are value objects as far as I understand. So is it a sign of bad design when your aggregate root contain only value objects? shall it contain only entities and via entities interact with value objects?
Entities: Shall the entities contain only value objects? or it can also contain other entities? can you give me a simple example please ?
Value Objects: shall I go ahead and encapsulate every primitive type in an value object? I can go deep and make every primitive type as an value object, for example: PhoneNumber can be a string or an value object which contains country code, number. the same thing can be applied to all other primitive type value such as name, email. So where to draw the line ? where to say "Ok I'm going to deep", or going deep is the right way of doing DDD?
Factories: Do I really need them? I can go ahead and write an static method within the domain object which knows more precisely how to construct it, am I doing wrong ?
Sorry for the long questions, but I'm feeling little lost despite of continues reading, if you can help me I would be glad.
I'll try to answer all your questions:
1.1. The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root? (Yes/No)
Entities live within ARs and allowing the client to create them would violate encapsulation, so for entities you are correct, ARs create their own entities which don't get exposed to the outside (copies/immutable views could be).
On the other hand, value objects are generally immutable and therefore there's no harm in having them supplied to the AR as data inputs.
In general all modifications needs to go through the AR so that the AR is aware of the modification. In special situations the AR could detect modifications within it's cluster by listening to events raised by internal entities when it's impractical to go through the root.
1.2. Can an aggregate root contain only value objects ? for example User root, it contain only address, phone, things which are value objects as far as I understand. So is it a sign of bad design when your aggregate root contain only value objects? shall it contain only entities and via entities interact with value objects?
Favor value objects as much as you can. It's not unusual for all parts of an AR being modeled as values. However, there's no limitation or law stating whether or not an AR should have only values or entities, use the composition that's fit to your use case.
Entities: Shall the entities contain only value objects? or it can also contain other entities? can you give me a simple example please ?
Same answer as above, no limitation nor law.
Value Objects: shall I go ahead and encapsulate every primitive type in an value object? I can go deep and make every primitive type as an value object, for example: PhoneNumber can be a string or an value object which contains country code, number. the same thing can be applied to all other primitive type value such as name, email. So where to draw the line ? where to say "Ok I'm going to deep", or going deep is the right way of doing DDD?
Primitive obsession is worst than value object obsession in my experience. The cost of wrapping a value is quite low in general, so when in doubt I'd model an explicit type. This could save you a lot of refactoring down the road.
Factories: Do I really need them? I can go ahead and write an static method within the domain object which knows more precisely how to construct it, am I doing wrong ?
Static factory methods on ARs are quite common as a mean to be more expressive and follow the UL more closely. For instance, I just modeled as use case today where we had to "start a group audit". Implemented a GroupAudit.start static factory method.
Factory methods on ARs for other ARs are also quite common, such as var post = forum.post(author, content) for instance, where Post is a seperate AR than Forum.
When the process requires some complex collaborators then you may consider a standalone factory though since you may not want clients to know how to provide and setup those collaborators.
I'm new to DDD and I want to clearly understand each domain object structure and role
Your best starting point is "the blue book" (Evans, 2003).
For this question, the two important chapters to review are chapter 5 ("A model expressed in software") and chapter 6 ("the life cycle of a domain object").
ENTITIES and VALUE OBJECTS are two patterns described in chapter 5, which is to say that they are patterns that commonly arise when we are modeling a domain. The TL;DR version: ENTITIES are used to represent relationships in the domain that change over time. VALUE OBJECTS are domain specific data structures.
AGGREGATES and FACTORIES are patterns described in chapter 6, which is to say that they are patterns that commonly arise when we are trying to manage the life cycle of the domain object. It's common that modifications to domain entities may be distributed across multiple sessions, so we need to think about how we store information in the past and reload that information in the future.
The only contact point the client can interact with the domain objects, the client should not be able to modify or create new Entities or value objects whiteout the aggregate root?
Gray area. "Creation patterns are weird." The theory is that you always copy information into the domain model via an aggregate root. But when the aggregate root you need doesn't exist yet, then what? There are a number of different patterns that people use here to create the new root entity from nothing.
That said - we don't expect the application to be directly coupled to the internal design of the aggregate. This is standard "best practice" OO, with the application code coupled to the model's interface without being coupled to the model's implementation/data structure.
Can an aggregate root contain only value objects ?
The definition of the root entity in the aggregate may include references to other entities in the same aggregate. Evans explicitly refers to "entities other than the root"; in order to share information with an entity other than the root, there must be some way to traverse references from the root to these non-root entities.
Shall the entities contain only value objects?
The definition of an entity may include references to other entities (including the root entity) in the same aggregate.
shall I go ahead and encapsulate every primitive type in an value object?
"It depends" - in a language like java, value objects are an affordance that make it easy for the compiler to give you early feed back about certain kinds of mistakes.
This is especially true if you have validation concerns. We'd like to validate (or parse) information once, rather than repeating the same check every where (duplication), and having validated vs unvalidated data be detectably different reduces the risk that unvalidated data leaks into code paths where it is not handled correctly.
Having a value object also reduces the number of places that need to change if you decide the underlying data structure needs improvement, and the value object gives you an easily guessed place to put functions/methods relating to that value.
Factories: Do I really need them?
Yes, and...
I can go ahead and write an static method within the domain object
... that's fine. Basic idea: if creating a domain object from so sufficient set of information is complicated, we want that complexity in one place, which can be invoked where we need it. That doesn't necessarily mean we need a NOUN. A function is fine.
And, of course, if your domain objects are not complicated, then "just" use the objects constructor/initializer.
Related
No, it is not a duplication question.
I have red many sources on the subject, but still I feel like I don't fully understand it.
This is the information I have so far (from multiple sources, be it articles, videos, etc...) about what is an Aggregate and Aggregate Root:
Aggregate is a collection of multiple Value Objects\Entity references and rules.
An Aggregate is always a command model (meant to change business state).
An Aggregate represents a single unit of (database - because essentialy the changes will be persisted) work, meaning it has to be consistent.
The Aggregate Root is the interface to the external world.
An Aggregate Root must have a globally unique identifier within the system
DDD suggests to have a Repository per Aggregate Root
A simple object from an aggregate can't be changed without its AR(Aggregate Root) knowing it
So with all that in mind, lets get to the part where I get confused:
in this site it says
The Aggregate Root is the interface to the external world. All interaction with an Aggregate is via the Aggregate Root. As such, an Aggregate Root MUST have a globally unique identifier within the system. Other Entites that are present in the Aggregate but are not Aggregate Roots require only a locally unique identifier, that is, an Id that is unique within the Aggregate.
But then, in this example I can see that an Aggregate Root is implemented by a static class called Transfer that acts as an Aggregate and a static function inside called TransferedRegistered that acts as an AR.
So the questions are:
How can it be that the function is an AR, if there must be a globaly unique identifier to it, and there isn't, reason being that its a function. what does have a globaly unique identifier is the Domain Event that this function produces.
Following question - How does an Aggregate Root looks like in code? is it the event? is it the entity that is returned? is it the function of the Aggregate class itself?
In the case that the Domain Event that the function returns is the AR (As stated that it has to have that globaly unique identifier), then how can we interact with this Aggregate? the first article clearly stated that all interaction with an Aggregate is by the AR, if the AR is an event, then we can do nothing but react on it.
Is it right to say that the aggregate has two main jobs:
Apply the needed changes based on the input it received and rules it knows
Return the needed data to be persisted from AR and/or need to be raised in a Domain Event from the AR
Please correct me on any of the bullet points in the beginning if some/all of them are wrong is some way or another and feel free to add more of them if I have missed any!
Thanks for clarifying things out!
I feel like I don't fully understand it.
That's not your fault. The literature sucks.
As best I can tell, the core ideas of implementing solutions using domain driven design came out of the world of Java circa 2003. So the patterns described by Evans in chapters 5 and six of the blue book were understood to be object oriented (in the Java sense) domain modeling done right.
Chapter 6, which discusses the aggregate pattern, is specifically about life cycle management; how do you create new entities in the domain model, how does the application find the right entity to interact with, and so on.
And so we have Factories, that allow you to create instances of domain entities, and Repositories, that provide an abstraction for retrieving a reference to a domain entity.
But there's a third riddle, which is this: what happens when you have some rule in your domain that requires synchronization between two entities in the domain? If you allow applications to talk to the entities in an uncoordinated fashion, then you may end up with inconsistencies in the data.
So the aggregate pattern is an answer to that; we organize the coordinated entities into graphs. With respect to change (and storage), the graph of entities becomes a single unit that the application is allowed to interact with.
The notion of the aggregate root is that the interface between the application and the graph should be one of the members of the graph. So the application shares information with the root entity, and then the root entity shares that information with the other members of the aggregate.
The aggregate root, being the entry point into the aggregate, plays the role of a coarse grained lock, ensuring that all of the changes to the aggregate members happen together.
It's not entirely wrong to think of this as a form of encapsulation -- to the application, the aggregate looks like a single entity (the root), with the rest of the complexity of the aggregate being hidden from view.
Now, over the past 15 years, there's been some semantic drift; people trying to adapt the pattern in ways that it better fits their problems, or better fits their preferred designs. So you have to exercise some care in designing how to translate the labels that they are using.
In simple terms an aggregate root (AR) is an entity that has a life-cycle of its own. To me this is the most important point. One AR cannot contain another AR but can reference it by Id or some value object (VO) containing at least the Id of the referenced AR. I tend to prefer to have an AR contain only other VOs instead of entities (YMMV). To this end the AR is responsible for consistency and variants w.r.t. the AR. Each VO can have its own invariants such as an EMailAddress requiring a valid e-mail format. Even if one were to call contained classes entities I will call that semantics since one could get the same thing done with a VO. A repository is responsible for AR persistence.
The example implementation you linked to is not something I would do or recommend. I followed some of the comments and I too, as one commenter alluded to, would rather use a domain service to perform something like a Transfer between two accounts. The registration of the transfer is not something that may necessarily be permitted and, as such, the domain service would be required to ensure the validity of the transfer. In fact, the registration of a transfer request would probably be a Journal in an accounting sense as that is my experience. Once the journal is approved it may attempt the actual transfer.
At some point in my DDD journey I thought that there has to be something wrong since it shouldn't be so difficult to understand aggregates. There are many opinions and interpretations w.r.t. to DDD and aggregates which is why it can get confusing. The other aspect is, in IMHO, that there is a fair amount of design involved that requires some creativity and which is based on an understanding of the domain itself. Creativity cannot be taught and design falls into the realm of tacit knowledge. The popular example of tacit knowledge is learning to ride a bike. Now, we can read all we want about how to ride a bike and it may or may not help much. Once we are on the bike and we teach ourselves to balance then we can make progress. Then there are people who end up doing absolutely crazy things on a bike and even if I read how to I don't think that I'll try :)
Keep practicing and modelling until it starts to make sense or until you feel comfortable with the model. If I recall correctly Eric Evans mentions in the Blue Book that it may take a couple of designs to get the model closer to what we need.
Keep in mind that Mike Mogosanu is using a event sourcing approach but in any case (without ES) his approach is very good to avoid unwanted artifacts in mainstream OOP languages.
How can it be that the function is an AR, if there must be a globaly unique identifier to it, and there isn't, reason being that
its a function. what does have a globaly unique identifier is the
Domain Event that this function produces.
TransferNumber acts as natural unique ID; there is also a GUID to avoid the need a full Value Object in some cases.
There is no unique ID state in the computer memory because it is an argument but think about it; why you want a globaly unique ID? It is just to locate the root element and its (non unique ID) childrens for persistence purposes (find, modify or delete it).
Order A has 2 order lines (1 and 2) while Order B has 4 order lines (1,2,3,4); the unique identifier of order lines is a composition of its ID and the Order ID: A1, B3, etc. It is just like relational schemas in relational databases.
So you need that ID just for persistence and the element that goes to persistence is a domain event expressing the changes; all the changes needed to keep consistency, so if you persist the domain event using the global unique ID to find in persistence what you have to modify the system will be in a consistent state.
You could do
var newTransfer = New Transfer(TransferNumber); //newTransfer is now an AG with a global unique ID
var changes = t.RegisterTransfer(Debit debit, Credit credit)
persistence.applyChanges(changes);
but what is the point of instantiate a object to create state in the computer memory if you are not going to do more than one thing with this object? It is pointless and most of OOP detractors use this kind of bad OOP design to criticize OOP and lean to functional programming.
Following question - How does an Aggregate Root looks like in code? is it the event? is it the entity that is returned? is it the function
of the Aggregate class itself?
It is the function itself. You can read in the post:
AR is a role , and the function is the implementation.
An Aggregate represents a single unit of work, meaning it has to be consistent. You can see how the function honors this. It is a single unit of work that keeps the system in a consistent state.
In the case that the Domain Event that the function returns is the AR (As stated that it has to have that globaly unique identifier),
then how can we interact with this Aggregate? the first article
clearly stated that all interaction with an Aggregate is by the AR, if
the AR is an event, then we can do nothing but react on it.
Answered above because the domain event is not the AR.
4 Is it right to say that the aggregate has two main jobs: Apply the
needed changes based on the input it received and rules it knows
Return the needed data to be persisted from AR and/or need to be
raised in a Domain Event from the AR
Yes; again, you can see how the static function honors this.
You could try to contat Mike Mogosanu. I am sure he could explain his approach better than me.
In Domain Driven Design,domain objects are fall into two categories,entity and value object.It is very easy to make out which is entity,which is value object,but i don't know why we have to do that?Before the advent of DDD, we model the domain without entity and value object.After the DDD was put forwar,we use entity and value object to classify domain object, so what is the advantage of such classification?
domain objects are fall into two categories,
Actually, no, objects are a possible implementation of a domain Concept , which is basically just information, not code. A concept can be an Entity because it makes sense to identify it in a uniquely and consistent manner, regardless how it changes over time (e.g: a Customer can change their name but it's the same customer. 2 customers with the same name are not necessarily the same person).
A Value Object (a name that still reminds us that DDD started a bit too coupled to OOP) represent a Domain concept that it's just a value. Or more precisely, the business only cares about its value. If you change it, it's another value all together. Basically, 5 dollars is 5 dollars, you don't really care which is which, any of them is good enough, because only the value is important.
Another thing is, as a domain modeler you identify the nature of a concept based on how the business looks at a concept. The business tells you what they care about.
Now, that we know that a concept can be a Entity, we can select a certain instance of it (User with Id 3). You can't do that with VO, because a VO doesn't have an identity.
Even more, when we identify aggregates, most of the time, the aggregate components (other concepts) are mostly VOs, because they usually are just values (but they do respect business constraints).
So, in conclusion, we classify concepts into Entity and VO, because
The business sees them in this manner: uniquely identifiable or just value
Entities keep their identity regardless how they change (obviously the identity itself is read-only), we treat each one as unique
VO are values that can be used interchangeably, we don't care which is which as long as they represent the same value (which itself, as an implementation detail can be a complex - composite - value). Also, a VO by its nature is immutable, so we know that we can't change it without becoming another value.
Before the advent of DDD, we model the domain without entity and value object.After the DDD was put forwar,we use entity and value object to classify domain object, so what is the advantage of such classification?
You should review Chapter 5 ("A Model Expressed in Software") of the Blue Book.
Evans writes:
Defining objects that clearly follow one pattern or the other makes the objects less ambiguous and lays out the path toward specific choices for robust design.
Tracking the identity of ENTITIES is essential, but attaching identity to other objects can hurt system performance, add analytical work, and muddle the model by making all objects look the same.
... bidirectional associations between two VALUE OBJECTS just make no sense. Without identity, it is meaningless to say that an object points back to the same VALUE OBJECT that points to it. The most you could say is that it points to an object that is equal to the one pointing to it, but you would have to enforce that invariant somewhere.
My own summary would be this: recognizing that some domain concepts are entities is useful, because it encourages the designer to acknowledge that identity, continuity, and life cycle are important concerns for the entity in this domain. Similarly, recognizing that a concept is a value immediately frees you from those concerns, bringing your attention to their immutable nature and equivalence.
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.
As part of my domain model, lets say I have a WorkItem object. The WorkItem object has several relationships to lookup values such as:
WorkItemType:
UserStory
Bug
Enhancement
Priority:
High
Medium
Low
And there could possibly be more, such as Status, Severity, etc...
DDD states that if something exists within an aggregate root that you shouldn't attempt to access it outside of the aggregate root. So if I want to be able to add new WorkItemTypes like Task, or new Priorities like Critical, do those lookup values need to be aggregate roots with their own repositories? This seems a little overkill especially if they are only a key value pair. How should I allow a user to modify these values and still comply with the aggregate root encapsulation rule?
While the repository pattern as described in the blue book does emphasize its use being exclusive to aggregates, it does leave room open for exceptions. To quote the book:
Although most queries return an object or a collection of objects, it
also fits within the concept to return some types of summary
calculations, such as an object count, or a sum of a numerical
attribute that was intended by the model to be tallied.
(pg. 152)
This states that a repository can be used to return summary information, which is not an aggregate. This idea extends to using a repository to look up value objects, just as your use case requires.
Another thing to consider is the read-model pattern which essentially allows for a query-only type of repository which effectively decouples the behavior-rich domain model from query concerns.
Landon, I think that the only way is to make those value pairs aggregate roots. I know that is might look overkill, but that's DDD braking things into small components.
The reasons why I think using a repository is the right way are:
A user needs to be able to add those value pairs independently of a Work Item.
The value pairs don't have a local, unique identity
Remember that DDD is just a set of guidelines, not hard truths. If you think that this is overkill, you might want to create a lookup that returns the pairs as value objects. This might work out specially if you don't have a feature to add value pairs in the application, but rather through the database.
As a side note, good question! There are quite a few blog posts about this situations... But not all agree on the best way to do this.
Not everything should be modeled using DDD. The complexity of managing the reference data most likely wouldn't justify creating aggregate roots. A common solution would be to use CRUD to manage reference data, and have a Domain Service to interface with that data from the domain.
Do these lookups have ID's ? If not, you could consider making them Value Objects...
Let's say we have CQRS-inspired architecture, with components such as Commands, Domain Model, Domain Events, Read Model DTOs.
Of course, we can use Value Objects in our Domain Model. My question is, should they also be used in:
Commands
Events
DTOs
I haven't seen any examples where Value Objects (VO) are used in the components mentioned above. Instead, primitive types are used. Maybe it's just the simplistic examples. After all, my understanding of VOs use in DDD is that they act as a glue for the whole application.
My motivation:
Commands.
Let's say user submits a form which contains address fields. We have Address Value Object to represent this concept. When constructing command in the client, we should validate user input anyway, and when it is well-formed, we can create Address object right there and initialize Command with it. I see no need to delegate creation of Address object to command handler.
Domain Events.
Domain Model already operates in terms of Value Objects, so by publishing events with VOs instead of converting them to primitive types, we can avoid some mapping code. I'm pretty sure it's alright to use VOs in this case.
DTOs.
If our query-side DTOs can contain Value Objects, this allows for some more flexibility. E.g., if we have Money object, we can choose whether to display it in EUR or USD, no need to change Read Model.
Ok I've changed my mind. I have been trying to deal with VOs a bunch lately and after watching this http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson it clarified a couple of things for me.
Commands and Event are messages (and not objects, objects are data + behavior), in some respects much like DTOs, they communicate data about an event and they themselves encapsulate no behavior.
Value Objects are not like DTOs at all. They are a domain representation and they are, generally speaking, rich on behavior like all other domain representations.
Commands and Events communicate information into and out of the domain respectively, but they themselves do not encapsulate any behavior. From that perspective it seems wrong and a possibly a violation context boundaries to pass VOs inside of them.
To paraphrase Oren (though he was referring to nHibernate and WCF) "Don't send your domain across the wire".
http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx
If you want to communicate a value object, then I suggest passing the necessary attributes needed to re-construct the VO within them instead.
Original Text (for posterity):
If you are asking if Value Objects can be passed by the domain model to events or passed in by commands, I don't really see a huge problem with the former, though the latter may violate some of the rules of the aggregate root being the "owner" of values.
That said a value object represents concepts like for example a color. You don't have green, you are green or not. There seems to be nothing intrinsically wrong with a command telling you that you are green by passing this.
Reading the chapter from DDD on the Aggregate Root pattern explains Entities and Value Objects quite well and is worth reading over a few times.
I say it's a bad idea.
There's a reason we don't do the same with entities - to avoid coupling other parts of the system to the domain (in the wrong places). The same is true for Value Objects, the only difference between value objects and entities is lifetime and ownership - these differences do not affect how we should and should not couple to them.
Imagine that you make an event contain a VO. A change in your domain requires you to change that VO. You've now boxed yourself into a corner where your event is also forced to change, ditto for any Commands or DTO's it's a part of.
This is to be avoided.
Use DTO's and/or primitives. Map them (AutoMapper makes it a 1-line deal).
Similar to other answers, in SOA this would break encapsulation of the service as the domain is now leaking out.
According to Clean Code your DTOs are data structures (just to add another term), while value objects are objects. The difference that objects can have behavior. Mixing data structures with objects is generally a very bad idea, because it will be hard to maintain the hybrid you get.
I don't feel right to put value objects to DTOs from an architecture perspective as well. The value objects are inside of the domain model while the DTOs you mentioned are defining the interface of the model. We usually build an interface to decouple the outside world from the inside of something. So in the current case we added DTOs to decouple the outside world from the value objects (and other model related stuff). After that adding value objects to the interface is crazy.
So you haven't met this solution yet because it is an anti-pattern.
Value Objects are or at least should be immutable. Once instantiated with a value that value will never change throughout the lifetime of the object. Thus, passing VOs as data to DTOs (such as Events) should not be an issue since all you can do with them is get their value. At the most their value in a differing representation such as toString() as opposed to an original getValue() which might return an integer or whatever the value is.