I am modeling my entities, and have been struggling with this for a long time. Here is my Person Entity:
Person
ID
Name
Email
Password
City
Phone
Biography
Rating
Description
I have tried to divide these properties into Value Objects, but so far I only have been able to convert them to VOs (for example, City is a VO made with a city name, and country name).
Should I try to create larger VOs, by putting together, for example, Email and Password into a Credentials VO ? Am I going too deep in the separation into VOs ?
Any help is greatly appreciated
[EDIT]
After some discussion, it appears that the best solution is to keep every property in it's own VO, except for Email and Password that should be grouped in a "Credentials" VO.
Value objects are things who's values uniquely identify them I.e. equality is done by the values, rather than an explicit property (like ID) to provide uniqueness. Two value objects are equal if all their fields are equal
When trying to identify them, follow the language the domain experts use. What words do they use when discussing People? Do they refer to credentials, or email and password?
Also look to identify groups of properties that are always used together. For example, if Password is always used alongside Email it makes sense to group them in a Credentials object, as you can then push behaviour there (i.e. Credentials.Validate())
[UPDATE]
All of the following properties are candidates for value objects depending on the invariants you need to enforce
Name
are there min / max values for names?
are there any characters not allowed?
Email
is it a valid email address
can two people have the same email address?
Password
min / max length?
required characters?
invalid characters?
Phone
is it a valid phone number?
how do you deal with international dialing codes?
Rating
is there a min and max value allowed for a rating?
how is it calculated? (is it calculated?)
Description
Biography
City
etc....
If you create Value Objects for the above concepts instead of using primitive values such as int or string, you can encapsulate your business rules inside the value objects.
You might want to combine Email and Password into a Credentials Value Object if you use the two things cohesively. i.e. login with credentials etc... You can still access Credentials.Email if you need to use the Email outside of the Credentials object.
What you have there looks suspiciously as a data structure (CRUD). In proper DDD you start with the business case like "Create Person" and then you find out the model representing the Person concept.
The model is defined by a group of components and business rules. Your components are usually VOs , because they are models representing minor concepts that can be expressed as a simple or composite value with no explicit identity and they encapsulate specific business constraints. For example, the Email VO makes sure you have a valid email value.
You should let the domain tells you if it makes sense to create bigger VO; usually you start with a VO and you discover it's made up from other VOs. Generally, we go top to down. You can see here a modelling example.
It's hard when you don't have a domain expert but you can still try to think in business cases and identify whatever specific model for each case. If you end up with mainly simple structures and some data validation rules, perhaps you have a simple enough domain to just use a CRUD approach.
Don't try to impose a particular domain model structure, you need to approach domain modeling from the use cases perspective.
Should I try to create larger VOs, by putting together, for example, Email and Password into a Credentials VO ?
You should do that only if the two tend to be used together. If they don't, leaving them along is just fine.
Note that sometimes it makes sense to extract a single property into its own value object if the number of invariants it needs to support is high enough to justify introducing a new concept. Take a look at this article for more details.
it is not always clear a concept in your domain is a value object or entity and unfortunately there are no objective attributes you could use to get to know it whether or not a notion is a value object fully it depends on the problem domain, a concept can be an entity in one domain model or a value object in another. most of times a money class is a value object but not all money objects are value object. how you can find out a value object? first of all you should check the notion of identity if it is structurally equal (it means two objects are same if objects values are same, not ids of objects), you can safety replace an instance of class which has same set of attributes. that is good sign this concept is a value object.
a good way of thinking value object is thinking if it is an integer, do you really care if integer 5 is same as 5 you used in other function? definitely not all 5 in your application are same, regardless how they were instantiated. that's make integer essentially a value object, now ask your self the object in your domain is like an integer? if answer is yes then it is a value object. also, value objects are immutable and more light weight as entities.
Related
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.
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'm working on a project where I had a value object (called SkillProfile) within an aggregate. Aggregate root is the User entity and the User has a unidirectional one-to-one association to it's SkillProfile. There is use case in the business where a SkillProfile can be shared with another User, but always as a copy (so modifying one of the profile won't change any of the other users profile). So far so good.
Now the business has the new requirement that it should be possible to see in reports which users share the same skill profile. This requirement cannot be fulfilled by the equals method on the skill profile, since there are skill profiles which coincidentally have the same values but weren't "shared" in terms of explicitly doing it. Of course the old requirement that skill profiles have to be immutable is still valid.
So here my question: Is it a good idea to invent a new field "Id" or "SharingCode" on the SkillProfile class and therefore give it some sort of identity although it's still a value object and not an entity since it has no state or lifecycle?
First,
so modifying one of the profile won't change any of the other users profile
If SkillProfile is indeed a value object, there should be no possibility to modify one! Replacing it within the User is fine of course. (just to have this clear before discussing your question)
With the new requirements, SkillProfile needs an identity - whether explicit or implicit - because it can no longer be compared by just looking at its value. Thus, it is now an entity.
Note that you don't need to treat it much differently than you were the value object before - it's a good idea to keep the entity immutable, for example, because this is still in the nature of the concept. So it shouldn't be a big step to make it an entity.
I just started learning about domain driven design, and one of the few things that confuse me the most is how to determine which one should be entity, which one should be value object
I know to determine entity/value object, we need to base on the domain context, in one context, one domain object can be entity, in another, it can be value object, but still there are some situations I can't decide
.e.g. address
- In the context of a customer management application (let's just say an application to manage customers, add/delete/change status,etc of customers), address is clearly value object because here we don't need to differentiate between one address from another, 2 customers can have same address
- On the other hand, in the context of a online booking application, can I say address is an entity? because now we need to differentiate customers by their billing address (just ignore the case 2 customers having same address for the moment)
To me, address is unique itself, so it definitely already has identity. So identity of a domain object will not decide whether it's an entity or value object, if so then what will be the key factors to choose?
Another example, I have one application that list a number of areas in one country, user can choose one area, and find all the restaurants that fit their searching criteria in that area. In this case, is area a value object or entity? Currently I think it's more on an entity but still not very sure. Each area is unique also
I'm not sure whether my question is clear or not, I try my best to explain my thinking currently
I think some of your difficulties may be in the subtle meanings of some of these terms. For example, you mention "To me, address is unique itself, so it definitely has identity". In terms of how most people use "identity" in domain-driven design, your statement would probably be incorrect.
A value object's set of attributes is its definition. If you change any aspect of it, you have a completely different object. Using your address example, if you change any part of it, you get a entirely different address. It is not the same address with aspects of it changed. Your customer moved to a new address; they did not change aspects of the same address.
However, if you were a mapping application and the address itself changed, then here, the address would be a entity. In such a scenario, the city planners may want to re-number houses on the street. In that case, the SAME address is being modified. In that case, we would need to update the entity, not a value object.
Regarding your billing address example, the billing address is probably still a value entity (at least the physical address portion of it). A payment method (e.g. credit card) may be the entity in that example, and it may include other value objects (such as billing address, credit card number, etc).
You may find it helpful to see review this question and its answers as well: Value vs Entity objects (Domain Driven Design)
Hope this helps. Good luck!
I have gotten so far that I understand entity objects have an ID while value object have not, but in the most common example you have the person entity that have a address value object attached to it. What is the big advantage of creating a separate address object instead of just keeping the address properties within the Person Entity?
In addition to the things already mentioned, Greg Young makes a big deal out of the fact that since they are immutable, you can validate them on creation and never worry about validation again. If the state cannot be changed, then you know it's always valid.
Value objects can be used as arguments for other methods in other classes
It can make your design clearer
It might help with performance optimization (example: fly-weight pattern)
Value objects can be reused in different entities. (example: user and location entities with address value objects.
Don't forget that "not having an id" is not the only difference between value objects and entities, being immutable is also very important.
Think of it as a reusable component. You can make it into a home address, work address without much extra effort. You can use it to decouple other systems from the person entity. Say you introduce a business entity. It will also have an adress.
Related to this subject is another important subject: composition vs. inheritance