如何使用DDD和SRP实现可维护且松散耦合的应用程序?

时间:2012-11-27 20:57:11

标签: c# wcf design-patterns architecture domain-driven-design

提出这个问题的原因是我一直想知道如何将所有这些不同的概念拼接在一起。有很多关于DDD,依赖注入,CQRS,SOA,MVC的例子和讨论,但没有那么多关于如何以灵活的方式将它们组合在一起的例子。

我的目标:

  1. 开发很少或根本没有修改的模块可以独立完成
  2. 更改或重新设计用户界面应该尽可能简单(即用户界面尽量少做,并且是“愚蠢的”
  3. 使用记录的模式和原则
  4. 为了更容易提出具体问题,主要的结构现在看起来像这样:

    Employee management example

    该示例显示如何向员工添加备注。员工管理是一个有限的背景。员工有几个属性,其中包括ICollection<Note>

    绑定上下文是我理解分离代码的逻辑位置。每个BC都是一个模块。大多数时候,如果需要,我发现每个人都可以保证自己的UI(即某些模块可能用于Windows手机)。

    包含所有业务逻辑。

    基础架构包含存储库实现,以及用于发送邮件,保存不属于域的文件和实用程序的服务。我正在考虑制作一些常见的服务功能,我必须在几个领域(例如发送电子邮件)中使用它作为一种API,我可以参考这些API来保存一些代码在几个BC中实现相同的东西。 / p>

    查询图层包含除了GetById之外的所有查询,我需要在存储库中获取对象。查询层可以查询其他持久性实例,并且可能需要为每个UI更改一些。

    Wcf或Web Api是我的应用层,它可能属于基础设施,而不属于外部。此服务还设置依赖项,因此所有UI需要做的是询问信息并发送命令。

    该过程以蓝色箭头开始。阅读模型,因为它有大部分信息。

    在第1步中,此示例中的EmployeeDto只是一些员工属性,用于向用户显示他们需要记录员工的信息(如关于新体验或类似内容的说明)。

    所以问题是:

    1. 实现这样的分层结构真的涉及到这么多的映射,还是我错过了什么?
    2. 建议(甚至智能)使用Wcf服务来运行这样的主逻辑(它实际上是我的应用服务)
    3. 在我的UI图层中没有我的域对象,是否有替代Wcf?
    4. 此实施有什么问题吗?任何摔倒坑都需要注意?

    5. 你有什么好的例子可以帮助我理解所有这些概念应该如何协同工作。

    6. 更新 我已经阅读了大部分文章(相当多的阅读),除了付费书(需要更多时间)。所有这些都是非常好的指针,并且更多作为适配器的Wcf的思考方式似乎是对问题2的一个很好的答案。如果我计划走这条路线,JGauffins对他的框架的工作也很有意思

      然而,正如下面的一些评论中提到的,我觉得有些例子倾向于推荐或实施事件和/或命令源,消息总线等。对我来说,现在规划这种级别的扩展是不合适的。对于许多业务应用程序而言,这是一个“大型”(就内部应用程序而言,最多可以考虑几千个)处理大量数据的用户数量,而不是需要实现事件和命令的高度协作域队列经常与CQRS联系以应对。

      根据以下答案,我将首先采用的方法将基于上述模型以及类似的答案:

      1. 我只需要处理映射。 Thoe pros胜过缺点。

      2. 我会将应用程序服务拉回到基础架构中 将Wcf视为“适配器”

      3. 我将使用命令对象并发送到应用程序服务。不 使用域对象污染我的域。

      4. 为了降低复杂性,我尝试在没有事件/命令的情况下进行管理 现在采购,消息总线等。

      5. 此外,我只想链接到this blog post by Udi Dahan关于CQRS,我认为这样的事情会降低复杂性,除非真的需要它们。

2 个答案:

答案 0 :(得分:9)

  1. 在映射和图层之间进行权衡。存在某些映射的一个原因是因为没有适当的抽象可行或不可行。因此,通常在层之间进行显式映射比尝试实现推断映射的框架更容易,但我离题了;这取决于对该问题的哲学讨论。

  2. WCF或WebAPI服务应该非常薄。可以将其视为hexagonal architecture中的适配器。它应该将所有内容委托给应用程序服务。服务一词存在混淆,导致混淆。总的来说,WCF或WebAPI的目标是将您的域“适应”到特定的技术,如HTTP。可以将WCF视为在DDD术语中实施开放主机服务

  3. 您提到了WebAPI,如果您需要HTTP,则可以选择它。最重要的是,要注意这个适应层的作用。正如您所述,最好让UI依赖于DTO,通常是使用WCF或WebAPI或其他任何东西实现的服务合同。这使事情变得简单,并允许您改变域的实现,而不会影响开放主机服务的消费者。

  4. 你应该始终注意不必要的复杂性。分层是一种权衡,有时它可能是矫枉过正。例如,在主要是CRUD的应用程序中,不需要对此进行分层。此外,如上所述,不要将WCF服务视为应用程序服务。相反,将它们视为传输技术和应用程序服务之间的适配器。反过来,无论您的域是使用DDD还是使用事务脚本方法实现,都可以将应用程序服务视为您域的外观。

  5. 真正帮助我理解的是六边形体系结构中引用的文章。通过这种方式,您可以将您的域视为核心,并将您的域分层,使您的域适应基础架构和服务。你所拥有的似乎已经遵循这些原则。 Vaughn Vernon Implementing Domain-Driven Design是一个很好的,深入的资源,特别是关于建筑的章节。

答案 1 :(得分:2)

  

实现像这样的分层架构是否真的涉及到如此多的映射,还是我错过了什么?

是。问题是它不是同一个对象。它是同一对象的不同表示,但专门针对每个用例。视图模型包含更新GUI的逻辑,DTO专门用于传输(可能被规范化以便于传输)。它们可能看起来一样,但它们确实不是。

您当然可以尝试将所有修改都放在一个单独的类中,但在应用程序增长时使用它并不是一件非常有趣的事。

  

是否建议(甚至智能)使用Wcf服务来运行这样的主逻辑(它实际上是我的应用程序服务)

您需要某种网络层。我不会让所有客户端应用程序都触及我的数据库。如果你搞乱数据库模式(如果某些客户端仍然运行旧版本),它会造成维护噩梦。

通过使用服务器,可以更轻松地维护版本差异。

请注意,一旦使用,WCF服务定义应被视为常量。应在新界面中定义任何更改(例如MyService2)。

  

如果在我的UI图层中没有我的域对象,是否有替代Wcf?

你可以看看我的框架。发布帖子:http://blog.gauffin.org/2012/10/writing-decoupled-and-scalable-applications-2/

  

这个实现有什么问题吗?

不是我能看到的。看起来你对这些概念及其使用方法有很好的把握。

  

任何需要注意的摔倒坑?

不要试图对查询和命令保持懒惰。不要使它们更适合几个用例。当应用程序增长时,它会回来并咬你。较小的类更容易维护。

  

你有什么好的例子可以帮助我理解所有这些概念应该如何协同工作。

我关联的博文和该系列中的所有其他文章。