领域驱动设计 (DDD) 和数据库生成的报告

Domain Driven Design (DDD) and database generated reports

我仍在研究 DDD,但我很想知道一个潜在的陷阱。

根据 DDD,聚合根不应该知道持久性,但这是否意味着整个聚合根最终会在内存中实例化?

例如,如果聚合根不应该知道持久性,它如何要求数据库对大量数据进行分组和求和?

According to DDD an aggregate-root shouldn't know about persistence, but doesn't that mean the entire aggregate-root ends up being instantiated in memory?

聚合根是一致性边界,所以是的,您通常会将整个聚合加载到内存中以强制执行不变量。如果这听起来像是一个问题,则可能暗示您的聚合太大并且可能需要重构。

How could the aggregate-root, for instance, ask the database to group and sum a lot of data if it's not supposed to know about persistence?

聚合不会要求数据库对数据进行分组和求和 - 通常您会在应用程序服务/命令处理程序中加载聚合。例如:

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 实现 not 无知,因此可以做任何必要的事情来完全加载聚合。所以你 可以 在加载聚合时有你的持久性实现 group/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 在这里应用

According to DDD an aggregate-root shouldn't know about persistence, but doesn't that mean the entire aggregate-root ends up being instantiated in memory?

哦不,比那更糟;整个聚合(根和所有从属实体)在内存中加载实例化。从本质上讲,根据定义,您需要加载所有状态才能验证任何更改。

How could the aggregate-root, for instance, ask the database to group and sum a lot of data if it's not supposed to know about persistence?

你不需要聚合根来做到这一点。

域模型的主要作用是通过确保所有写入都尊重您的业务不变性来确保记录簿的完整性。读取,如数据库报告,不会更改记录簿,因此您无需加载域模型。

如果领域模型本身需要报告,它通常会定义一个服务提供者接口来指定它需要的报告,而您的持久性组件负责确定如何实现该接口。