弱或贫血的域模型仅意味着您的“域对象”是 DTO,没有任何行为。您基本上得到的是事务脚本模式,其中 DTO 被加载、修改和再次保存。CRUD,换句话说。这对于很多应用程序来说都很好,因为它们没有足够复杂的规则来从 DDD 方法中受益。
域对象应该封装行为。这就是他们的本质。任何公共状态(可能没有公共 getter 或 setter)都应该是只读的,如果你想改变状态,你可以调用一个与用例/业务需求相关的方法。
您所有的“域逻辑”都应该在这些类中。域逻辑只是一个花哨的名称,用于描述您选择的域的规则和操作参数。无论是银行、零售、人力资源等。当您的领域专家解释“通过卡付款”用户案例并告诉您“在 PDC 机器与银行联系之前,我们无法打开收银台。”,这是一个业务规则/不变量/域逻辑。
您通常会将域对象(由实体和值对象组成)组装成聚合,聚合定义了必须满足给定规则集的边界。作为该域对象图的根的实体称为聚合根,只有聚合根才能让其他对象持有引用。在您的情况下,User
是一个实体,因为它是聚合中的唯一对象,所以它也是聚合根。例如:
public class User // Entity and also the Aggregate Root
{
private readonly IList<Friendship> _friends = new List<Friendship>();
public void Befriend(User user)
{
_friends.Add(new Friendship(/* Date? */, user));
}
public class Friendship // Entity
{
// ... Date?
private User _friend { get; private set; }
public Friendship(/* Date? */, User friend)
{
_friend = friend;
}
}
}
这真的不是一个很好的例子,因为理论上你需要为一对中的两个朋友中的每一个调用这个,但是任何交易都应该只执行一个操作,而不是两个。在这种情况下,您将引入流程管理器的概念。这些还有更多的对象处理本质上是长期运行的事务(其中两个朋友成为彼此的朋友)的协调。您可能会创建一个友谊(作为聚合根),它的创建会产生某种事件驱动的过程,其中涉及的朋友被加载、结交和保存。