简体   繁体   English

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

[英]Domain Driven Design (DDD) and database generated reports

I'm still investigating DDD, but I'm curious to know about one potential pitfall. 我仍在调查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? 根据DDD,聚合根不应该了解持久性,但这是否意味着整个聚合根最终都在内存中实例化了?

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? 例如,如果不知道持久性,那么聚集根如何要求数据库进行分组和汇总大量数据?

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? 根据DDD,聚合根不应该了解持久性,但这是否意味着整个聚合根最终都在内存中实例化了?

Oh no, it's worse than that; 哦,不,比这还糟。 the entire aggregate (the root and all of the subordinate entities) get loaded instantiated in memory. 整个集合 (根和所有从属实体)都在内存中实例化加载。 Essentially by definition, you need all of the state loaded in order to validate any change. 本质上,根据定义,您需要加载所有状态以验证任何更改。

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? 例如,如果不知道持久性,那么聚集根如何要求数据库进行分组和汇总大量数据?

You don't need the aggregate-root to do that. 您不需要执行聚合根。

The primary role of the domain model is to ensure the integrity of the book of record by ensuring that all writes respect your business invariant. 域模型的主要作用是通过确保所有记录都尊重您的业务不变性来确保记录簿的完整性。 A read, like a database report, isn't going to change the book of record, so you don't need to load the domain model. 读取(例如数据库报告)不会更改记录,因此您无需加载域模型。

If the domain model itself needs the report, it typically defines a service provider interface that specifies the report that it needs, and your persistence component is responsible for figuring out how to implement that interface. 如果域模型本身需要报告,则通常定义一个服务提供商接口,该接口指定需要的报告,而持久性组件负责确定如何实现该接口。

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? 根据DDD,聚合根不应该了解持久性,但这是否意味着整个聚合根最终都在内存中实例化了?

Aggregate roots are consistency boundaries, so yes you would typically load the whole aggregate into memory in order to enforce invariants. 聚合根是一致性边界,因此,是的,通常将整个聚合加载到内存中以强制不变式。 If this sounds like a problem it is probably a hint that your aggregate is too big and possibly in need of refactoring. 如果这听起来像是一个问题,则可能暗示您的集合太大,可能需要重构。

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? 例如,如果不知道持久性,那么聚集根如何要求数据库进行分组和汇总大量数据?

The aggregate wouldn't ask the database to group and sum data - typically you would load the aggregate in an application service / command handler. 聚合不会要求数据库对数据进行分组和求和-通常,您会将聚合加载到应用程序服务/命令处理程序中。 For example: 例如:

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);
    }
}

So your aggregate remains ignore of how it is persisted. 因此,您的聚合仍然忽略其持久性。 However, your implementation of ISomeRepository is not ignorant, so can do whatever is necessary to fully load the aggregate. 但是,您对ISomeRepository的实现并非一无所知,因此可以做任何必要的事情来完全加载聚合。 So you could have your persistence implementation group/sum when loading the aggregate, but more often you would probably query a read model: 因此,在加载聚合时,您可以具有持久性实现组/总和,但是更常见的是,您可能会查询读取模型:

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);
    }
}

You haven't actually said what your use case is though. 您实际上并未说出用例是什么。 :) :)

[Update] [更新]

Just noticed the title refers to database generated reports - this will not go through your domain model at all, it would be a completely separate read model. 只是注意到标题是数据库生成的报告-完全不会通过您的域模型,它将是一个完全独立的读取模型。 CQRS applies here CQRS在这里适用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM