This is a long question so i am gonna go straight to the point. This is pseudo code for better illustration of the problem
DB Structure
User (UserID, Name, LastName)
Address(AddressID, UserID, Street, City, State, ZipCode) =>Many to One User relationship
Phone (PhoneID, UserID, Number, IsPrimary) =>Many to One User relationship
Domain Classes
class User:IEntity
{
public string Name {get;set;}
public string LastName {get;set;}
public ContactInfo{get;set;}
}
class Phone: IValueObject or IEntity? will see later.
{
public int id; // persistence ID, not domain ID
public string Number {get;set;}
}
class Address: IValueObject or IEntity? will see later.
{
public string Line1 {get;set;}
public string City {get;set;}
public string State {get;set;}
public string ZipCode {get;set;}
}
class ContactInfo: IValueObject or IEntity? will see later.
{
List<Address> Addresses {get;set;}
List<Phone> PhoneNumbers {get;set;}
}
So, so far we have a very basic representation of this domain and its models.
My question is the following. Let's say that i want to Update one of the addreses or fix the area code for one of the numbers because of misspelling wnen it was initially typed in.
If i follow Evan's bible about DDD, Value Objects should be immutable. Meaning, no changes to its properties or fields after it was created. If that's the case, then i guess, none of my classes are a ValueObject, since i can't just recreate the whole ContactInfo class just because one portion of the string in the phone number is wrong. So, i guess that makes all my classes Entities?
Keep in mind that i have a "persistence id" for each of this classes since they are stored in a database.
Let's say that i decide to make Phone a value object, since it's easy to recreate in the constructor
public Phone(string newNumber)
so, it would be something like adding a method to User (agg root) AND contactinfo? (Demeter Law)
like...
User....
public void UpdatePrimaryPhoneNumber(string number)
{
this.ContactInfo.UpdatePrimaryPhoneNumber(number);
}
ContactInfo....
public void UpdatePrimaryPhoneNumber(string number)
{
var oldPhone = Phones.Where(p=>p.IsPrimary).Single();
var newPhone = new Phone(number, oldPhone.persistenceid???-> this is not part of the domain)
oldPhone = newPhone;
}
but i still have to deal with persistence id... grrrrr. what a headache.
Sometimes i feel when i read those blogs that most "ddd experts" that value objects are overused or i would say misused.
What would be the best solution to this scenario? Thank you
if... then... else
outside your AR, that's already a bad sign. But this kind of thing you can only develop them by constant repetition. Microservices makes it even easier because the logical separation of your AR and Bounded Context is now physical. No risks of cross-referencing ARs, etc. – Sisson