是否可以根据服务拥有存储库?

时间:2012-11-14 10:38:14

标签: domain-driven-design

我正在开展涉及版本化实体的项目,以便存档用户修改的整个历史记录。

基本上,这个想法是当创建实体时,其内容的版本1也保存在存档表中。每当修改实体时,也会存储增量版本。

将实体的状态保存到存档表由ArchiveService处理。

当实体被持久化时,需要调用ArchiveService来创建版本1,因此最合乎逻辑的方式似乎是从存储库中调用它,从而将服务作为依赖项传递给存储库:

public class Repository {
    private ArchiveService archiveService;

    public Repository(ArchiveService service) {
        this.archiveService = service;
    }

    public void add(Entity entity) {
        // ... (persist the entity)

        this.archiveService.createVersion(entity);
    }
}

这是一个好习惯,还是有任何缺点? 到目前为止,我看到的是依赖于存储库的服务,而不是反过来。

2 个答案:

答案 0 :(得分:3)

如果按照描述对其进行建模,则会隐藏域知识并将其隐藏在存储库中,存储库本身不属于域。我认为这不是一个好主意。

您可以使用Domain Events对其进行建模,即EntityCreated。然后,事件侦听器可以获取事件并创建相应的存档条目。

更新以回答评论中提出的问题:

  

从概念上讲,存储库封装了持久化的对象集   在数据存储中以及对它们执行的操作,提供一个   更多面向对象的持久层视图。 - Martin Fowler

除了正式定义:存储库知道如何存储和检索对象。为了能够实现这一点,它需要了解持久性机制或至少下面的数据访问层。

另一方面,域模型不应该依赖于外部的任何东西。在 Ports and Adapters 体系结构(比DDD更适合DDD)中,存储库将是适配器之一。

您的域只知道其存储库的接口,实际的实现在外部。这样你只有内向的依赖。基本上这是面向对象的,而具有向下指向的级联依赖关系的分层架构更像是一种程序方法。

答案 1 :(得分:2)

归档属于您的无处不在语言的域概念?如果是,则应在域层中定义ArchiveService。否则,它可以在Infrastructure层中定义,IRepository的每个实现都将选择是否存档。

在任何情况下,我都没有看到存储库有任何问题,具体取决于ArchiveService(或任何其他服务)。您可以随后立即调用repository.add(entity)调用archiveService.createVersion(entity)的每一段代码,但这不会非常方便。