这是一个很长的问题,我将直接进入主题。下面是伪代码,更好地说明了问题。
数据库结构
用户(UserID,Name,LastName)
地址(AddressID,UserID,Street,City,State,ZipCode)=>与用户之间存在多对一关系
电话(PhoneID,UserID,Number,IsPrimary)=>与用户之间存在多对一关系
领域类
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;}
}
到目前为止,我们对于这个领域及其模型有一个非常基本的表示。
我的问题是:假设我想更新其中一个地址或者修正一个号码的区号,因为在最初输入时出现了错误拼写。
如果我遵循Evan的《领域驱动设计》中的价值对象概念,那么价值对象应该是不可变的,也就是说,在创建之后不能更改其属性或字段。 如果是这种情况,那么我想,我的所有类都不是价值对象,因为我不能仅仅因为电话号码中的某一部分字符串错误就重新创建整个ContactInfo类。那么,我想这样就把所有的类都变成了实体类?
请记住,每个类都有一个“持久性ID”,因为它们存储在数据库中。
假设我决定将Phone作为一个值对象,因为它可以在构造函数中轻松重建。
public Phone(string newNumber)
所以,这就像是将一个方法添加到用户(聚合根)和联系信息中一样?(迪米特法则)
就像...
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;
}
但我仍然要处理持久化id... 嗷!真是个头疼的问题。
有时候,当我阅读那些博客时,我觉得大多数“ddd专家”并没有正确使用价值对象,或者说过度使用了。
针对这种情况,什么是最好的解决方案呢?谢谢。
if... then... else
,那已经是一个坏迹象了。但这种事情只能通过不断重复来发展。微服务使它更容易,因为您的AR和Bounded Context的逻辑分离现在是物理的。没有跨引用AR的风险等。 - Pepito Fernandez