刚刚创建了一个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# – 在DDD方法中,这个例子是否正确建模?的更多相关文章

  1. DDD框架落地实战

    这篇文章主要为大家介绍了DDD框架落地实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  2. zend-framework – DataMapper模式是否打破了MVC?

    我一直在阅读多个PHP框架,特别是Zend框架,但我对前进的正确方法感到困惑.ZendFramework不使用ActiveRecords,而是使用表数据网关和行数据网关模式,并使用DataMapper将行数据网关的内容映射到模型,因为ActiveRecord在模型没有1时发生故障:1映射到数据库表.Zend快速入门指南中有一个exampleofthis.对我来说,他们的例子看起来非常臃肿,到处都是

  3. ubuntu14.04 安装 ddd 以及运行 ddd 遇到的问题

    1.安装ddd遇到的问题1.ubuntu下可以直接sudoapt-getinstallddd即可.2.源码安装时,首先下载ddd最新的源码,http://ftp.gnu.org/gnu/ddd/,一般的过程如下1).在./configure过程中遇到如下错误提示解决方法:sudoapt-getinstalllibmotif-devlibmotif-common注意,不同的linux版本可能moti

  4. centos ddd 安装,注意版本

    开始安装,问题很多,后来发现是版本太旧,用了下边的版本就可以了:1.下载DDD源码:http://ftp.gnu.org/gnu/ddd/.现在的最新版本:ddd-3.3.12.tar.gz2.解压缩源码:tarxzfddd-3.3.12.tar.gz3.进入ddd-3.3.12目录,运行./configure报错:configure:error:TheMotifincludefile'Xm/Xm

  5. Ubuntu16.04下安装DDDData Display Debugger

    第一步,下载安装包并解压我们可以从http://ftp.gnu.org/gnu/ddd/下载我们需要的版本,我下载的是最新版本ddd-3.3.12.tar.gz#wgethttp://ftp.gnu.org/gnu/ddd/ddd-3.3.12.tar.gz#tarzxvfddd-3.3.12.tar.gz#cdddd-3.3.12/注意:解压时我们可以解压到任何地方。第二步,配置#./configure--prefix=/usr/local/ddd执行完这个后我们一般会遇到两个问题:第一个错误提示出现这

  6. java – DDD实体及其标识符

    我的系统中有一个实体,它自然需要一个标识符,以便可以唯一标识.假设数据库用于使用Hibernate生成标识符,使用本机策略,那么显然应用程序代码没有分配标识符的可靠性.现在,该实体的实例在被持久化并获取其标识符之前是否可以被认为是有效的?

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

    刚刚创建了一个acc在SO上问这个:)假设这个简化的例子:构建一个Web应用程序来管理项目…

  8. c# – 实现域驱动设计

    有人使用域驱动设计技术吗?我最近阅读了埃里克·埃文斯的同名书,并且有兴趣听到任何在项目中实现全部/部分内容的人我已经把这个问题开放了,我想尽可能多地看到意见,但我有几个问题:1–如果语言支持,值类型是真实的“值类型”吗?例如C#中的一个结构2-C#中有什么功能可以使语言和模型之间的关联更加清晰解决方法是!我在项目中使用DDD(但是I’mbiased!“领域驱动”方面,还是实施方面?

  9. c# – DDD – 服务层和存储库之间的重复

    如果我们只是让服务层直接调用ORM,那么生活会不会更容易?但是,如果SL还包含一些具有复杂业务逻辑的方法,那么它们应该通过存储库吗?

  10. c# – 工厂模式这应该存在于DDD中?

    我已经讨论了一段时间了,但仍然没有得出结论.虽然我看到大多数示例都在应用程序层中有工厂代码,但我倾向于认为它应该在域层中.原因:我有时会在我的工厂进行初始验证,我希望所有对象的创建都能通过.我希望此代码可用于我的对象的所有实例化.有时,操作需要感觉不自然的参数信息传递给构造函数.还有一些不那么重要的原因.有没有理由说这是一种不好的做法?

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部