implementing many to one relationships in object model - domain-driven-design

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.

Related

Actual difference between Value Objects and Entities. DDD

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.

DDD: Classify entity/value object

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!

Address dilemma

I have Person aggregate in which Address is part and vo , but now i have another aggregate Payment which have another VO PaymentInfo , which contains details like Creditacard number and other details, but now i need Billing Address and Shipping Address in PaymentInfo VO. Now since Address is integral to Person i cannot use that.
So what i do ,
Create separate Address Vo in Payment aggregate and use it as billing address and Shipping Address.
Move address in to separate aggregate and reference it in PaymentInfo and Person.
Create two addresses in Person itself and reference it in PaymentInfo Vo.
help me please ?
Important thing here is - value objects have no identity.
That means - they can become shared between entities easily.
With that I mean - not particular instances should be shared, but their classes, type Address instead of "UK, London street 'whatever' 16". Value object instances should never be shared (again - cause they got no identity and their state is what defines them).
So in Your place - I would make sure Address as a concept is mutually ubiquitous for person and for payment info (they must have same structure), move it into right folder/namespace so I could see that it's shared and use it for both entities.
If they aren't ubiquitous, I would rename Address as PersonAddress and create second one - PayerAddress (name might differ according to Your business You are modeling).
Quoting Jeff from provided link:
There's no problem with 2 aggregate roots referencing the same entity - they just can't reference another aggregate's internals. It is different for value objects, which are simpler. Consider how you can reference dates, like "August 20th, 2010," any number of times in your classes.
i will go with ubiquitous nature of it. Dont reference the Person address class to the billing address and the shipping address..
Two things Can be achieved easily .one is the communication benefit which you can get in the business analyst and second is the Coding will be explicit and understandable.

Loading a Value object in List or DropdownList, DDD

I need to clarify something.
Have Person Aggreagate , 2 VOs (Country, StateProvince).
I want to load all country in my presentation layer (i am using mvc)
Evan says you only use repository (IPersonRepository) to work with root entity (it should always return just a reference to the Aggregate Root)
public interface IPersonRepository()
{
void savePerson(Person p);
void removePerson(Person p);
Ilist<Person> getPerson();
}
what i usually do to solve this :
Add in IPersonRepository this method
IList<Country> LookupCountrysOfPerson();
In Infra layer implement the Domain interfaces like this:
public IList<Person> LookupCountrysOfPerson()
{
return Session.CreateQuery("from Countrys").List<Person>());
}
My partner says im wrong.
Sometimes you have to sacrifice your domain model in order to accomplish some task
What is the best way to do this?
with code please! :)
I would say it's unlikely that you need country to be an entity. I suspect that country is nothing more than reference data, much like a person's title would be. Is there any behavior associated to country in your domain? I suspect it's just what's printed onto letters/envelops.
This question is somewhat similar to this one which I answered a while back:
Simple aggregate root and repository question
My suggestion is that you implement a Lookup service that your client can make use of and which is cached. Ignore the rules of DDD and anything to do with aggregates or repositories for this. As someone else has mentioned, this is where CQRS's ideology comes into play; the client shouldn't have to go through the domain in order to get data. The domain is purely transactional, not designed for queries.
This article explains how to build a generic lookup service for reference data for things that typically fill dropdowns in the UI (i.e. Title, Country etc)
http://wtfperminute.blogspot.com/2011/02/working-with-reference-data-lookups.html
Evans also says (pg 170) "An entity as basic as Location may be used by many objects for many reasons..."
I would also consider making Country an entity for the reasons given above. Perhaps more importantly, it is a low level object. You probably are also even supplying Country by configuration rather than through any actual domain activities. Therefore I would remove it from the Person and make it a standalone entity.
Also for this type of object you may not really need a dedicated repository, consider creating a single lookup service that provides query access for a group of similar objects of this nature.
If in your domain country is actually a VO (you don't want to maintain a thread of identity in the country name was changed etc.) which is the most common scenario, I would add a specialized class in the data access layer to return a list of all countries as VOs. I would also add caching (2nd level cache in NHibernate) to the country entity and list all countries query so that I don't have to hit the DB each time.
Actually, this is where CQRS really shines. CQRS acknowledges that you don't have to go through the domain layer in order to get some data for presentation purposes. In CQRS you just grab some data.
It sounds like countries are not in fact value objects here; they have distinct identities and are important for business purposes outside of your Person objects. They should become entities, and be treated in the fashion appropriate to them.
Think of it this way: let's say some volatile country had their current dictator overthrown and got a name change. The Person object's reference to a Country should still be valid, because the Country is not defined by its attributes (i.e. the string denoting its name), but by its identity.

In DDD, what are the actual advantages of value objects?

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

Resources