Tag*_*Tag 10 c# domain-driven-design repository repository-pattern
刚刚在SO上创建了一个acc来问这个:)
假设这个简化示例:构建Web应用程序来管理项目......
应用程序具有以下要求/规则.
1)用户应该能够创建插入项目名称的项目.
2)项目名称不能为空.
3)两个项目不能具有相同的名称.
我使用的是4层架构(用户界面,应用程序,域,基础架构).
在我的应用层上,我有以下ProjectService.cs类:
public class ProjectService
{
private IProjectRepository ProjectRepo { get; set; }
public ProjectService(IProjectRepository projectRepo)
{
ProjectRepo = projectRepo;
}
public void CreateNewProject(string name)
{
IList<Project> projects = ProjectRepo.GetProjectsByName(name);
if (projects.Count > 0) throw new Exception("Project name already exists.");
Project project = new Project(name);
ProjectRepo.InsertProject(project);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的域层,我有Project.cs类和IProjectRepository.cs接口:
public class Project
{
public int ProjectID { get; private set; }
public string Name { get; private set; }
public Project(string name)
{
ValidateName(name);
Name = name;
}
private void ValidateName(string name)
{
if (name == null || name.Equals(string.Empty))
{
throw new Exception("Project name cannot be empty or null.");
}
}
}
public interface IProjectRepository
{
void InsertProject(Project project);
IList<Project> GetProjectsByName(string projectName);
}
Run Code Online (Sandbox Code Playgroud)
在我的Infrastructure层,我有IProjectRepository的实现,它执行实际的查询(代码无关紧要).
我不喜欢这个设计的两件事:
1)我已经读过存储库接口应该是域的一部分,但实现不应该.这对我来说没有任何意义,因为我认为域不应该调用存储库方法(持久性无知),这应该是应用程序层中服务的责任.(有些东西告诉我,我非常错.)
2)创建新项目的过程涉及两个验证(非空且不重复).在我上面的设计中,这两个验证分散在两个不同的地方,这让我们更难以看到最新情况.
那么,我的问题是,从DDD的角度来看,这是正确的建模还是你会以不同的方式做到这一点?
我认为对(1)的部分困惑是您缺少一个层——在您的架构中插入一个服务层,您的问题就会像魔术一样消失。您可以将服务和存储库实现放在服务层中——即,您有一个使用存储库的具体实现的服务。如果需要,其他服务可以自由选择存储库的替代实现。您的应用程序可以自由选择它喜欢的任何服务接口。话虽如此,我不确定在大多数情况下这是否真的重要。在我的几乎所有应用程序中,我都有一个基本上已修复的“域/数据层”。我可能会在其上分层存储库,也可能不分层,具体取决于业务逻辑的复杂程度。与服务相同——如果项目不是很复杂,则可能根本没有必要。如果以后变成这样,我随时可以重构。通常,我会将存储库放在与数据上下文相同的项目中(使用 LINQ),如果有服务,它将位于单独的项目中(因为通常它也会作为 Web 服务公开)。
对于(2),你需要从并发的角度来思考问题。如果可能的话,最好通过数据库约束来检查重复名称。我认为这是执行此逻辑的最简单方法。您当然可以在尝试插入之前检查是否存在重复项,但除非您在事务中执行此操作,否则无法保证另一个进程不会出现并在您的检查和插入之间插入一个重复项。数据库约束解决了这个问题。将检查移至插入逻辑(同一事务)也可以解决问题,但无论如何,我认为您需要准备好将其作为插入失败以及(或代替)验证错误来处理。
| 归档时间: |
|
| 查看次数: |
1006 次 |
| 最近记录: |