简体   繁体   中英

Domain Driven Design (DDD) and database generated reports

I'm still investigating DDD, but I'm curious to know about one potential pitfall.

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?

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?

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?

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. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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