访问存储库的域实体

Pau*_*ies 2 architecture domain-driven-design ddd-repositories repository-pattern

继续这些辩论:

DDD - 实体不能直接访问 Repositories 的规则

实体可以访问存储库吗?

在某些情况下,域访问存储库感觉更好。以这个例子为例,它假设我需要数据库中的 TaskStatus 表,其中包含用于报告目的的描述:

public class TaskStatus
{
    public long Id {get;set;}
    public string Description {get;set;}
}

public class Task
{
    public long Id {get;set;}
    public string Description {get;set;}
    public TaskStatus Status {get;set;}

    public void CompleteTask()
    {
        ITaskStatusReposity repository = ObjectFactory.GetInstace<ITaskStatusReposity>(); //Or whatever DI you do.
        Status = repository.LoadById(Constants.CompletedTaskStatusId);
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以拥有 CompletedTaskStatus 和 OpenTaskStatus 对象,但在某些情况下,这是不必要的,可能会导致类爆炸。

无论如何,如果不是这种事情,为什么存储库接口存储在域中?

Jus*_*eld 5

实体可以访问存储库吗?

不,请不要这样做。

首先,领域模型的思想是将业务逻辑与应用程序分离。将它与您的数据库、存储库和您的应用程序隔离。这允许您将业务逻辑分开,并允许它与您的应用程序分开进行测试和更改。

域应该完全不知道数据持久性,并且应该假设它是自动发生的。

ddd-the-repository-pattern.aspx

其次,还有其他更实际的原因不将您的存储库注入您的实体。

  1. 您的实体应该是可单元测试的,通过将您的存储库注入您已经创建了对存储库的依赖关系的实体。

  2. 使用 GetInstance() 方法打破了迪米特法则,您正在创建 ITaskStatusRepository 与您的实体的紧密耦合。这意味着在创建新任务和编写单元测试时,任务需要 ITaskStatusRepository 的构造并不明显。这使得对您的业务逻辑进行单元测试变得更加困难。

  3. 从 DDD 的角度来看,存储库不仅涉及与数据库的接口,还可以从内存存储中检索。或者一个列表。

  4. 您的存储库不必与表具有 1 对 1 的关系。如果您需要您的任务存储库与其他表执行内部联接以执行复杂查询,并且它返回任务项列表,那么您可以从存储库中公开一个执行该查询的方法。(我认为这是对存储库模式的常见误解)。

  5. 您的实体不应该关心对数据库执行操作。

请参阅此处发布的图片:

DDD:层应该如何组织?

public class TaskStatus
{
   public long Id { get; set; }
   public string Description { get; set; }

   public TaskStatus() {
      Description = "Incomplete";
   }
}

public class Task
{
    public long Id {get;set;}
    public string Description {get;set;}
    public TaskStatus Status {get;set;}

    public void CompleteTask()
    {        
        Status.Description = "Complete";
    }
}
Run Code Online (Sandbox Code Playgroud)

在应用层内部,您的存储库负责(或不负责)持久化。存储库是聚合根的 List<>。它在聚合根级别工作。

在 TaskService 中使用任务的示例。服务作用于应用层中的实体。

public class TaskService 
{
    private readonly ITaskRepository _taskRepository;

    public TaskService(ItaskRepository taskRepository){
      _taskRepository = taskRepository;
    }

    public List<Task> CompleteAllTasks()
    {
      List<Tasks> getTasks = _taskRepository.GetTasks();
      getTasks.ForEach(CompleteTask);
      return _taskRepository.Save(getTasks);
    }    
}
Run Code Online (Sandbox Code Playgroud)