2

继续这些辩论:

DDD - 实体不能直接访问存储库的规则

实体可以访问存储库吗?

在某些情况下,域访问存储库感觉更好。以这个例子为例,假设我需要数据库中的 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);
    }
}

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

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

4

1 回答 1

5

实体可以访问存储库吗?

不,请不要这样做。

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

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

ddd-the-repository-pattern.aspx

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

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

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

  3. 从 DDD 的角度来看,存储库不仅关注与 DB 的接口,还可以从内存存储中检索。或列表。

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

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

在应用层内部,您的存储库负责(或不负责)持久性。存储库是聚合根的 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);
    }    
}
于 2011-07-04T10:12:27.090 回答