(1) 你的服务层功能/任务/工作单元是否调用工厂或实体实例上的行为方法或域服务函数?我对这些组件的责任基于调用堆栈感到迷惑。
通常情况下,顶层检索必要的聚合根并调用其功能。有时顶层检索多个聚合根并将它们传递给域服务,但不经常,因为域服务是一个相当强的迹象,表明存在未识别的聚合根。最后,顶层确保聚合根被持久化。
(2) 实体实例是否具有像上面那样的“行为方法”?例如,一个帖子是否具有p.UpdatePost(string bodyText)或者这不是领域模型的关注点,因此应该通过存储库实现相同的效果?或者,服务层函数在这种情况下是否应该调用存储库,而实体实例仅具有特定于域而不是持久性的行为方法?但是,为什么听起来“更新帖子”是一个领域函数,而这是用户的目标呢?
是的,它们需要。领域模型应该意识到其状态变化,这比起初看来更有益。这个伟大的事情在于你获得了可扩展性点。如果客户一周后走向你并说他想让系统在用户更新帖子时检查其他内容,你将能够直接转到
post.UpdatePost
方法并在那里附加必要的东西,而不是搜索每一行
post.bodyText="new value"
。
另一方面,CRUD与领域驱动设计并不是互相排斥的。例如,在我的应用程序中,管理用户及其角色的操作没有足够的趣味性,以至于我甚至不试图对其进行粒度建模。您需要识别业务应用程序描述和处理的重要部分。
请记住,领域驱动设计仅适用于复杂应用程序。简单的博客应用程序不需要它。
引用:
(3) 我是否错误地假设服务层(而不是领域服务)应封装接口与领域层的交互方式?
据我所见- 应用服务更多是用来编排基础设施的。如果没有涉及基础设施,那么应用服务就
失去了价值:
应用服务基本上只是门面。如果它增加的复杂性超过了解决的问题,那么每个门面都很糟糕。
域内:
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
this.Name=name;
}
}
public interface ICustomerRepository{
void Save(Customer customer);
}
域外:
public class CustomerRepository:ICustomerRepository{
public void Save(Customer customer){
_voodoo.StoreItSomehow(customer);
}
}
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}