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 对象,但在某些情况下,这是不必要的,可能会导致类爆炸。
无论如何,如果不是这种事情,为什么存储库接口存储在域中?
实体可以访问存储库吗?
不,请不要这样做。
首先,领域模型的思想是将业务逻辑与应用程序分离。将它与您的数据库、存储库和您的应用程序隔离。这允许您将业务逻辑分开,并允许它与您的应用程序分开进行测试和更改。
域应该完全不知道数据持久性,并且应该假设它是自动发生的。
ddd-the-repository-pattern.aspx
其次,还有其他更实际的原因不将您的存储库注入您的实体。
您的实体应该是可单元测试的,通过将您的存储库注入您已经创建了对存储库的依赖关系的实体。
使用 GetInstance() 方法打破了迪米特法则,您正在创建 ITaskStatusRepository 与您的实体的紧密耦合。这意味着在创建新任务和编写单元测试时,任务需要 ITaskStatusRepository 的构造并不明显。这使得对您的业务逻辑进行单元测试变得更加困难。
从 DDD 的角度来看,存储库不仅涉及与数据库的接口,还可以从内存存储中检索。或者一个列表。
您的存储库不必与表具有 1 对 1 的关系。如果您需要您的任务存储库与其他表执行内部联接以执行复杂查询,并且它返回任务项列表,那么您可以从存储库中公开一个执行该查询的方法。(我认为这是对存储库模式的常见误解)。
您的实体不应该关心对数据库执行操作。
请参阅此处发布的图片:
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)