Domain-Driven Design, I'm trying to figure out what the difference some kind of mathematically and not intuitively. In my current project, we have some kind of payment transfers between banks.
In this system, the bank is carried not like a physical building but an abstract bank. It has BankCode for sure, country and Bank Name. And the question is: Is the bank should be an entity or value object. I intuitively feel that it should be entity, but some people say that it could be like a value object.
As I know, entities MIGHT have the same attributes but still be different. On the other hand, value objects must not have an identity, they should be the same in case all attributes are the same, they should answer what they are, not who or which they are. Please If I'm wrong - correct me.
In the system, banks are not changing during any flow, like another Value object Country or Currency, probably we could say, that banks with the same bank code, name, and country are the same banks. As well as we can say that Country with the same country code (ISO format) is the same. But still, for me, I feel like they are entities. Could someone prove where I'm wrong, and give mathematic proofs that they should be either Value object or Entities.
Currently, I end up with that: "The one difference between Entity and Value Object is the entity can contain the all same attributes and still be different, the Value Object can't", like transaction and people can have same amounts and goods, same names, but still be different, and like address should be the same if the country, city, and house number are the same. Please correct me, and maybe there are more differences
The classic example difference between the two, is based on the context (as DDD always is), so lets go for it...
Classic Example: An airplane flight (allocated seat or any seat)...
Entity
Each seat has a number, and you allocate a passenger a specific seat (Seat: 10 E)
Value Object
The plane has a number of seats, and you give a passenger 1 (or more) seat(s), on the plane (non specific, sit anywhere).
The key question is, do you care about the individual entity (a seat) or just the total number of available seats?
You can see the DDD - context separation here, even if you allocate seats, not every context is going to care. If I'm doing a capacity piece, I don't care about the entities, I just want to know
var unused = available - used.
Your initial Question
Simple Answer
It's an entity
Deeper Answer
It depends on the context.
And then...
In some contexts it may be a Domain Model in itself, like your context.
If I want to move money from Bank1 and Bank2 then, I'm going to do...
// Both domain models
Bank sendingBank = _bankStore.Get(fromBank.Id);
Bank receivingBank = _bankStore.Get(toBank.Id);
_moneyTransfer(sendingBank, receivingBank, amount);
Or alternatively
Calling code
Customer customer = _customerStore.Get(customerId);
var balanace = customer.GetBalance();
Entity Version: Customer
public class Customer {
public Bank {get; private set;}
public Decimal GetBalance () {
return this.Bank.GetBalance();
}
}
Value Object Version: Customer
public class Customer {
public Balance {get; private set;}
public Customer (..., decimal bankBalance) {
this.Balance = bankBalance;
}
}
Is the bank should be an entity or value object
A prior question to ask is: do you need to model the bank?
In particular, do you control the rules by a which a bank changes? Or are you just managing a local cache/repository of information that is provided to you by some other authority (in the same way that country code information is provided to us by the ISO 3166 Maintenance Agency).
An important principle in domain driven design is to take the care to ensure that you are modeling the thing that you are supposed to be modeling.
we could say, that banks with the same bank code, name, and country are the same banks. As well as we can say that Country with the same country code (ISO format) is the same. But still, for me, I feel like they are entities.
Yes. Banks are certainly entities. So are countries.
But they are real world entities. Your domain model doesn't own them. What you have in your data store is locally cached information about those entities.
For example, the ISO-3166-1 standard is a living document; it was changed as recently as 2020-03-02 (a correction to the full names for MK). A given country code and date gives you a fixed identifier. Because country codes are reserved for 50 years, the country code alone is unambiguous for non trivial time periods.
The token MK is certainly a value object. The lookup table that says token MK means North Macedonia is an entity. But... it is a stable entity, so in some contexts we might be able to treat it as fixed.
(That's a general property of standardized identifiers - standards are worthless if they aren't adopted, so the change management policies are designed to make things easy for adopters).
Unless you are yourself doing work for ISO 3166/MA, though, it isn't your entity. The information you have is just a copy.
My guess is that's true of your bank codes as well.
Part of the point of domain driven design: that if we do the work to make sure that we really understand the actual business problem that we are trying to model, then our subsequent implementation will be well aligned with what we want, and easy to change in the face of new requirements.
Which is to say, you really need to make sure you understand "bank" in the context of your domain to determine if it is an entity or a value object.
In your case, bank should be an Entity as each bank has a unique BankCode to identify it. Even if at this point your system doesn't update banks, it doesn't mean that it won't be possible in the future.
If some attribute of the bank changes, for example, it's main office address (just made it up...) of whatever else you got changes, the code that uniquely identifies it will remain the same, hence the same bank, but with a different main office address.
This bank BankCode: 1234, Location: US Texas and this bank after a change in the Location attribute BankCode: 1234, Location: US Colorado is still the same thing.
Giving a mathematical definition is difficult because mathematics is about values.
This kind of uniqueness based not on attributes but on some kind of Identity that remains the same as it changes is closer to how the real world works, so it's difficult to give non-intuitive definitions of it.
Here's a good example of a ValueObject from math. Let's say you model a 3D math library with vectors and matrices. Vector and Matrix are ValueObjects.
Let's say that we have two vectors:
v1 -> x = 1, y = 2, z = 3
v2 -> x = 1, y = 2, z = 3
You do have two vectors, but from a math point of view, they are identical i.e. represent the same thing and are equal. The same applies to matrices.
Let's have a transformation T (translation for example). In math what you have is:
v3 = T (v1, v2)
You get a brand new vector when you apply this transformation. This brand we vector may have the same coordinates as v1 and v2 as a result so they will be equal, but you do not change v1 or v2.
Let's say you get a hair cut and let's say that this is a transformation too. If this true in the real world?
You2 = T(Hairdresser, You1)
No, it's not. It' still you with a different hair cut, you do not create a different you when you apply the transformation.
A good example of when a concept can be both a value and an entity depending on the system is when modeling Money. In your case when you make bank transfers, you transfer money between accounts. In this case, Money is a ValueObject because you do not case to differentiate between 5$ and 5$, it's still the same amount.
Let's say you go to a store to buy a drink, This drink is 5$. If you have two Banknotes of 5$, it doesn't matter which one you use to pay because they represent the same amount.
On the other hand, each Banknote has a serial number. The two 5$ Banknotes will have different serial numbers making them unique and different, so they are Entities.
If your system tracks Banknotes then you model it as an Entity. If not, you model it as a ValueObject.
Do vectors and matrices have serial numbers on them or any kind of Identity? Your car (if you have one) does. If you go to a parking lot with lots of cars and you have two cars yours and some else's car, that are exactly the same, do you care which one you take? Well, it's better to take yours, otherwise, it stealing and it's against the law and someone won't be happy about it.
Let's take our vectors again and the transformation T.
T(v1, v2), T(v2, v2), and T(v1, v1) all give the same result because these two vectors are equal and we do not care which one we use.
Maybe, i could explain the question at another aspect. Entity usually has a identify, but what does the identity used to do? I think it used to trace the entity state changing. Why we should trace the state changing? Because the entity is referenced by other context/object according identify.
That's why we said that it depends on the specific context/case. For some context, we don't care the state changing, it will be Value Object, otherwise it will be Entity.
The Address often regarded as Value Object. You entered your address on a shopping website, the address will not be refered by your family members when they logging in the same the system, even if all of you have the same address.
But when you browsing, modifing or deleting the address entered before, it must be a Entity, becuase it is referred by Address Editor and Address Book with identify.
When an Adress used by an order, it will be an Object Value or Entity depends on the Address should be changed when Address Book changed.
I have an entity called Person. It represents a person that may share information with other persons. I also define two entities TelephoneNumber and Address, that represents some information. Each person may provision the database with their telephone number and address, as instances of TelephoneNumber and Address, and the information provisioned belongs only to that person. Then, a person that owns a certain information telephone number and address may associate these with each other through the entity Association, and may share this association to other persons.
I'm trying to follow domain driven design methodology. Since a telephone number or address belongs to only one person, the identities of TelephoneNumber and Address are local to this Person's identity. So, I think there is an aggregate that includes the entities Person, TelephoneNumber, Address and Association. The root of the aggregate would be the entity Person. So, obviously I need a repository for the entity Person, since it is the aggregate root, and I can "reconstitute" a person element from a data store using this repository.
Now, a certain person wants to add a telephone number and address, and wants to associate them. So, assuming the person already exists in the data store, I get the Person in question using the repository. How do I then add the information?
I see two approaches. Using addTelephoneNumber and addAddress methods in the Person entity, or using repositories for TelephoneNumber, Address and Association.
Assuming the first approach is the correct one, what do these methods have to do? How may these methods add information to the data store? I precise that I've chosen a traversal direction for the associations between Person and TelephoneNumber/Address, from TelephoneNumber/Address to Person. So, each time I retrieve a Person, I don't retrieve all its phones and addresses.
In this case, when a person wants to add a phone using the addTelephoneNumber method, what the method does? Where the new phone is put?
PS: The telephone numbers and the addresses owned by a person are not necessarily those of this person, they are just information that this person knows and wishes to share with other persons.
The notion of an object encapsulating a phone number and an address seems important in your domain, so you could have something like a ContactInfo entity ("Association" seems a bit too vague) containing a PhoneNumber and an Address. Phone and address don't really "change" per se -it's rather the ContactInfo that changes, so you could make them value objects.
Person would remain the aggregate root and the only entity to have a Repository. You'd just call person.AddContactInfo() to add a new contact info and contact infos would be persisted later together with the person.
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!
Suppose a Person object may have many Addresses but must have one
Do you favor making the one required Address explicit in the object model? If so, any implementation tips?
Cheers,
Berryl
Person{
Address TheRequiredAddress {get;}
IList<Address> OtherAddresses {....}
}
I like this question. As with most design decisions, this is contextual. How will this be used.
Assume I have a primary address in Seattle and a summer house in Phoenix, and a PO box for business purposes. Will my primary address have special priority over my other addresses, or is the choice of address arbitrary? Will you try to locate me in Seattle before you try my summer house or my PO box?
In the case where the primary address is treated differently, I would store it in an explicitly separate location. Otherwise, store them in an arbitrarily ordered collection and enforce the requirement for at least one within the class implementation.
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