Answers:
我最近亲自阅读了DDD。当我进入本节时,我惊喜地发现我发现了与Evans相同的4层架构。正如@lonelybug指出的那样,域层应与系统的其余部分完全隔离。但是,必须将特定于UI的值(查询字符串,POST数据,会话等)转换为域对象。这就是应用程序层发挥作用的地方。它的工作是在UI,数据层和域之间来回转换,从而有效地将域对系统的其余部分隐藏。
我现在看到许多ASP.NET MVC应用程序,其中几乎所有逻辑都在控制器中。这是实现经典3层体系结构的失败尝试。控制器很难进行单元测试,因为它们具有许多特定于UI的问题。实际上,编写一个控制器使其与“ Http Context”值不直接相关本身就是一个严峻的挑战。理想情况下,控制器应该只是执行翻译,协调工作并吐出响应。
在应用程序层中进行基本验证甚至是有意义的。域可以假设输入其中的值是有意义的(这是此客户的有效ID,并且此字符串表示日期/时间)。但是,涉及业务逻辑的验证(我是否可以保留过去的机票?)应保留给域层。
实际上,马丁·福勒(Martin Fowler)对当今大多数领域层的平坦程度发表了评论。即使大多数人甚至都不知道应用程序层是什么,他发现许多人制作了相当笨拙的域对象和复杂的应用程序层,以协调不同域对象的工作。我自己对此感到内gui。重要的不是要建立一个层,因为有一本书告诉你。这个想法是确定责任并根据这些责任分离我们的代码。就我而言,随着应用程序单元测试的增加,“应用程序层”自然而然地发展了。
从Martin Fowler的企业设计模式中,最常见的层是:
演示文稿-这些是视图,演示文稿模板,它们为您的应用程序生成交互界面(如果其他系统通过Web服务或RMI访问您的应用程序,则我可能会使用交互界面,因此可能不是用户界面)。它还包括决定如何执行动作以及如何执行动作的控制器。
域-这是您的业务规则和逻辑所在,域模型已定义等
数据源-这是数据映射层(ORM)和数据源(数据库,文件系统等)
如何绘制三层之间的界限:
不要在模型或领域对象中放入特定于演示的逻辑
不要在页面和控制器中放入逻辑,即将对象保存到数据库,创建数据库连接等的逻辑,这会使您的表示层易碎且难以测试
使用ORM,使您能够将数据源访问和操作与模型分离
遵循瘦控制器-胖模型范式,控制器用于控制执行过程而不执行它,更多信息请参见http://www.littlehart.net/atthekeyboard/2007/04/27/fat-models-skinny-controllers/和http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model 模型,视图和控制器,
该领域层模型的业务应用程序。这应该是您对其规则的清晰解释,它是组件的动态特性,并包含其在任何给定时刻的状态。
在应用层的“担心”定义需要做的工作以完成一定的应用任务。主要是,它负责授权必要的域工作并与其他(外部或非外部)服务进行交互。
对于例如,我的金融软件应用程序具有用于改变模型实体的状态的用户操作(如在DDD定义的实体[89]):
但是,作为一个应用程序过程,除了此操作的所有模型后果外,我还必须向该应用程序的其他用户发送内部通信。这种工作是在应用程序层中“安排”的。我不希望我的域层考虑引导消息服务。(当然这不是表示层的责任)。无论如何,肯定有一件事情:我需要一个新层,因为我的域层全是核心业务,而我的表示层全是解释用户命令和呈现结果。
笔记:
域层应设计为隔离层,这意味着业务逻辑和规则不应受到任何代码更改(在应用程序层,表示层和基础结构层中)的影响。
假定应将应用程序层设计为提供一些有关系统(应用程序)接口(例如API或RESTful)的功能。例如,用户可以登录系统,并且在此应用程序操作(登录)中,应用程序层代码将是域层(或基础结构层)的客户端代码,在其中检索用户域对象并应用该对象的方法来实现“登录”功能。
应用程序层还应该设计为隔离层,这意味着应用程序的行为不应受到任何代码更改(在表示层,域层和基础结构层中)的影响。
域驱动建模的重点是将基本域模型分离出来并使其存在而又不依赖于其他层和其他应用程序问题。
这使您可以专注于域本身而不会分散注意力(例如在UI和持久性服务之间进行协调)。
这些界限的主要原因是关注点分离。访问数据存储区的代码只需要担心访问数据存储区。它不应负责对数据执行规则。此外,UI应该负责更新UI中的控件,从用户输入中获取值并将它们转换为域层可以使用的内容,仅此而已。它应调用域层提供的操作以执行任何所需的操作(例如,保存此文件)。调用的Web服务应负责将传输介质转换为域层可以使用的内容,然后调用域层(大多数工具可以为您完成很多工作)。
如果正确实现了这种分离,则可以使您能够更改部分代码而不会影响其他代码。例如,可能需要更改返回的对象集合的排序顺序。由于您知道负责数据操作的层(通常是业务逻辑层)可以处理这些内容,因此您可以轻松地确定需要在哪里更改代码。不必修改如何从数据存储区或使用该域的任何应用程序中检索它的方式(上面示例中的UI和Web服务)。
最终目标是使您的代码尽可能易于维护。
附带说明一下,有些事情无法深入到域的特定层中(例如,日志记录,验证和授权)。这些项目通常称为跨领域关注点,在某些情况下,可以将其视为独立存在的一层,所有其他层都可以看到和使用。
我个人认为分层方法已经过时,并且服务方法更好。您仍然可以清楚地看出谁在做什么,但这并不会迫使您成为分层的人。例如,一个采购订单服务,一个开票服务和一个运输服务,从应用程序的角度来看,所有这些服务都代表您的域,而我上面描述的责任延期在这种情况下仍然有效,它已经被更改为您的域存在于多个地方,进一步利用关注点分离概念。