如何建模和处理演示文稿DTO从复杂的领域模型中抽象出来?

arr*_*ges 9 java architecture spring-mvc n-tier-architecture

嗨,我正在开发一个需要使用Hibernate处理复杂域模型的应用程序.这个应用程序使用Spring MVC并且在表示层中使用域对象非常混乱,所以我认为我应该使用DTO来往于我的服务层,以便这些匹配我在视图中所需的内容.现在假设我有一个CarLease实体,其属性不是简单的java原语,但它与Make,Model等其他实体组成

    public class CarLease {
        private Make make;
        Private Model model;
        .
        .
        .
    }
Run Code Online (Sandbox Code Playgroud)

大多数属性都是以这种方式使用,并且可以使用jsp视图上的下拉选项进行选择,每个属性都会将ID发回控制器.

现在考虑一些标准用例:创建,编辑,显示

您将如何建模演示文稿DTO用作表单支持对象以及表示层和服务层之间的通信?

你会为每个案例创建一个不同的DTO(创建,编辑,显示),你会为复杂属性制作DTO吗?如果是这样,您将ID转换为实体?

如何以及在何处处理验证,DTO /域组装,您将从服务层方法返回什么?(创建,编辑,获取)

正如您所看到的,现在我将通过将我的视图与域对象分开来获益(非常复杂,有很多我不需要的东西.)但是我很难找到任何真实世界的例子和最佳实践.我需要从上到下的一些架构指导,请记住我将使用Spring MVC,以防可能利用你的anwser.

提前致谢.

Adr*_*n K 3

对于它的价值(我正在 C# .net 中进行开发 - 但希望这些原则仍然对您有帮助),我定义了一堆类型(DTO),用于在业务层和数据层之间交换数据;每个域对象/实体有不止一种类型。这些被定义为简单的类。

其中每一个都是根据特定任务构建的,例如:

  • 我有一个轻量级类型,旨在填充列表视图(很多“行”,但不是很多“列”)。我还有一个相应的集合类型,可以容纳任意数量的这些集合。
  • 我有一个“大”获取副本,通常具有相关实体的所有属性 - 但仅适用于它的一个实例。我可能有不止一个,具体取决于实体的大小和复杂性与使用情况;还取决于您是否想要立即返回与实体实例关联的所有数据,或者在以后的请求中延迟加载一些数据。
  • 我通常还为实体设置单独的“保存”(新)和“更新”类型。

每种类型都旨在仅保存与给定任务相关的信息。例如,“big”将返回上次修改的日期,但我不希望在我的保存和更新类型中出现这种情况,因为我在数据访问层中填充了这些类型。

此外,对于我的应用程序,这些类型存在于通用程序集中 - 因此它们可以在任何层之间重用,而不仅仅是在业务层和数据层之间重用。

建筑风格

这种方法没有什么特别之处,它有自己的优点和缺点;这些到底是什么以及它们如何影响你将取决于很多因素——我想你的里程会有所不同——但多年来它确实对我很有帮助。

人们常常在“关注点分离”上大惊小怪——这确实是一个明智之举;这与 DTO 相关,因为它们在层(以及服务、组件等)之间交换,因此对于到底在哪里划清界限总是存在一些模糊性。

我采取的方法是,如果一些信息适合在不同层之间交换,那么它可能适合在任意数量的层之间交换——那么为什么不让所有人都可以访问它呢?如果您只是传递信息,它还可以节省重新传递信息的必要性。

就复杂性而言,有两种处理方法:

  1. 对所有人使用详细/人类可读的命名约定;类型,以便您知道事物是什么;有多少并不重要 - 这就是智能感知(和文档)的用途。越直观越好。
  2. KISS——如果可以的话,让事情变得简单;您必须平衡合理的重用和单一职责原则(SRP)。

您会创建主实体的复杂属性的 DTO 吗?

我发现自己制作 DTO 的原因有两个:

  1. 我知道我需要公开(推送)一些数据,并且 DTO 的设计是显而易见的:它是由我想要公开的数据驱动的。
  2. Pull:消费者知道自己想要什么,DTO 就是为了满足这些需求而设计的。

因为它们都在一个公共程序集中定义,没有一个组件“拥有”它,所以它有助于迫使您从“领域”的角度而不是以组件为中心的角度进行思考;在某种程度上,这将影响 DTO 的设计(平衡重用与 SRP)。

在这两种情况下,DTO 的设计可以是专门针对特定需求的,也可以是通用的;例如,只有一个 int 和一个字符串的 DTO 并不罕见,它就是您用来发送到下拉列表的那种东西。

我发回的大多数 DTO 集合(从 DAL 到 BL)都是特定于某个概念的,而不是通用的。我通过我提供的构造函数对这些强制执行非常非常基本的规则:每个参数都是必需的。我不确定这是否回答了您的问题“如何管理组装和验证”。