我还在调查DDD,但我很想知道一个潜在的陷阱。
根据DDD,聚合根不应该知道持久性,但这不意味着整个聚合根最终都会在内存中实例化吗?
例如,如果数据库不应该知道持久性,那么聚合根如何要求数据库对许多数据进行分组和汇总?
发布于 2016-07-19 16:46:17
根据DDD,聚合根不应该知道持久性,但这不意味着整个聚合根最终都会在内存中实例化吗?
哦,不,比这更糟;整个聚合(根和所有从属实体)都被实例化在内存中。从本质上说,根据定义,您需要加载所有状态才能验证任何更改。
例如,如果数据库不应该知道持久性,那么聚合根如何要求数据库对许多数据进行分组和汇总?
你不需要聚合根就能做到这一点。
域模型的主要作用是通过确保所有写入都尊重您的业务不变来确保记录簿的完整性。读,就像数据库报告一样,不会改变记录簿,所以您不需要加载域模型。
如果域模型本身需要报表,它通常定义一个服务提供者接口,该接口指定它所需要的报表,而您的持久性组件负责确定如何实现该接口。
发布于 2016-07-19 16:28:06
根据DDD,聚合根不应该知道持久性,但这不意味着整个聚合根最终都会在内存中实例化吗?
聚合根是一致性边界,所以是的,您通常会将整个聚合加载到内存中,以强制执行不变量。如果这听起来像是一个问题,那可能是一个提示,说明您的聚合太大了,可能需要重构。
例如,如果数据库不应该知道持久性,那么聚合根如何要求数据库对许多数据进行分组和汇总?
聚合不会要求数据库对数据进行分组和汇总--通常您将在应用程序服务/命令处理程序中加载聚合。例如:
public class SomeUseCaseHandler : IHandle<SomeCommand>
{
private readonly ISomeRepository _someRepository;
public SomeUseCaseHandler(ISomeRepository someRepository)
{
_someRepository = someRepository;
}
public void When(SomeCommand command)
{
var someAggregaate = _someRepository.Load(command.AggregateId);
someAggregate.DoSomething();
_someRepository.Save(someAggregate);
}
}
因此,您的聚合仍然忽略它是如何持久化的。但是,您的ISomeRepository实现并不无知,因此可以执行任何必要的操作来全面加载聚合。因此,在加载聚合时,您可以拥有持久性实现组/sum,但更常见的情况是,您可能会查询读取模型:
public class SomeUseCaseHandler : IHandle<SomeCommand>
{
private readonly ISomeRepository _someRepository;
private readonly ISomeReadModel _someReadModel;
public SomeUseCaseHandler(ISomeRepository someRepository, ISomeReadModel readModel)
{
_someRepository = someRepository;
_someReadModel = someReadModel;
}
public void When(SomeCommand command)
{
var someAggregaate = _someRepository.Load(command.AggregateId);
someAggregate.DoSomethingThatRequiresTheReadModel(_someReadModel);
_someRepository.Save(someAggregate);
}
}
不过,您还没有真正说出用例是什么。:)
更新
刚刚注意到标题引用数据库生成的报告-这将不会通过您的领域模型,它将是一个完全独立的读取模型。CQRS适用于
https://stackoverflow.com/questions/38463431
复制相似问题