(1)您的服务层函数/作业/任务/工作单元是否调用工厂或实体实例上的行为方法或域服务函数?基于这些组件的责任,我对调用堆栈一无所知。
通常-顶级检索必要的聚合根并对其调用函数。有时顶级检索多个聚合根并将它们传递给域服务,但这并不常见,因为域服务是一个很强的信号,表明存在无法识别的聚合根。在端-顶层确保聚合根被持久化。
(2)实体实例是否有上述“行为方法”?例如,Post是否有p.UpdatePost(string bodyText),或者这不是域模型的问题,因此应该使用存储库实现相同的功能?或者服务层函数,在这种情况下它是否应该调用存储库,而实体实例只是具有特定于域的行为方法,而不是持久性?但是,既然这是用户的目标,为什么听起来“更新帖子”是一个域函数呢?
是的,他们有。域模型应该知道它的状态变化。从一开始看起来,这样做更有益。很好的一点是,您获得了可扩展性点。如果客户会在一周后走到你跟前,说他希望系统在用户更新帖子时检查其他内容,而不是搜索
post.bodyText="new value"
,您可以直接转到
post.UpdatePost
方法和附加必要的东西。
另一方面-CRUD与领域驱动设计并不互斥。在我的应用程序中,对用户及其角色的管理非常枯燥,以至于我甚至没有试图对其进行粒度建模。您需要识别应用程序描述和使用的业务中重要的部分。
请记住,域驱动的设计只对复杂的应用程序有意义。简单的博客应用程序不需要它。
(3)假设一个服务层(而不是域服务)应该封装一个接口如何与域层交互,我错了吗?
正如我所见,it应用服务更多的是用于协调基础设施。如果不涉及基础设施,那么应用程序服务
loses value
:
应用程序服务基本上只是门面而已。而每一个外观都是糟糕的,如果复杂性增加了它解决的超重问题。
域内:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
域外:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
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);
}
}