c# – 在DDD方法中,这个例子是否正确建模?

前端之家收集整理的这篇文章主要介绍了c# – 在DDD方法中,这个例子是否正确建模?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
刚刚创建了一个acc在SO上问这个:)

假设这个简化的例子:构建一个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);
    }
}

在我的域层上,我有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);
}

在我的基础架构层上,我实现了IProjectRepository,它执行实际的查询(代码是无关紧要的).

我不喜欢这个设计的两件事情:

1)我已经看到存储库接口应该是域的一部分,但实现不应该.这对我来说没有意义,因为我认为域不应该调用存储库方法(持久性无知),这应该是应用层中服务的责任. (有东西告诉我我非常错误.)

2)创建新项目的过程涉及两个验证(不为null且不重复).在我上面的设计中,这两个验证分散在两个不同的地方,使得更难(imho)看到发生了什么.

那么我的问题是,从DDD的角度来看,这个模型是正确的,还是用不同的方法呢?

解决方法

我认为(1)的一部分混乱是你错过了一层 – 在你的架构中插入一个服务层,你的问题就像魔术一样消失.您可以将服务和存储库实现放在服务层中 – 即,您具有使用存储库的具体实现的服务.如果需要,其他服务可以自由地选择存储库的替代实现.您的应用程序可以自由选择它喜欢的任何服务界面.话虽如此,我不知道这在大多数情况下真的很重要.在我几乎所有的应用程序中,我都有一个基本固定的“域/数据层”.我可能会根据业务逻辑的复杂程度来分层存储库.与服务相同 – 如果项目不是很复杂,可能根本就没有必要.如果它变得如此之后,我总是可以重构.通常,我将我的存储库放在与我的数据上下文(使用LINQ)相同的项目中,如果有一个服务,它将在一个单独的项目中(因为通常它将被暴露为Web服务).

关于(2)你需要从并发的角度考虑问题.如果可能,您的检查重复名称最好由数据库约束处理.我认为这是实施这个逻辑的最简单的方法.您可以在尝试插入之前检查是否有重复,但除非在事务中执行此操作,否则不能保证另一个进程不会出现,并在检查和插入之间插入一个进程.数据库约束解决了这个问题.将检查移动到插入逻辑(同一事务)中也解决了问题,但无论我认为您需要准备好处理它作为插入失败以及(或代替)验证错误.

猜你在找的C#相关文章