首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何建模和处理从复杂的领域模型中抽象出来的表示DTO?

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

Stack Overflow用户
提问于 2010-04-12 04:36:05
回答 3查看 2.8K关注 0票数 9

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

代码语言:javascript
运行
复制
    public class CarLease {
        private Make make;
        Private Model model;
        .
        .
        .
    }

大多数属性都采用这种方式,并且可以使用jsp视图上的下拉选择来选择它们,每个属性都会向控制器回发一个ID。

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

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

您会为每个案例创建不同的DTO (创建、编辑、显示),您会为复杂属性创建DTO吗?如果是这样,您会在哪里将ID转换为entity?

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

正如您所看到的,现在我将受益于将我的视图从域对象(非常复杂,有许多我不需要的东西)中分离出来。但我很难找到任何现实世界的例子和最佳实践。我需要一些从上到下的架构指导,请记住,我将使用Spring MVC,以防在您的应用程序上发挥作用。

提前谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-04-12 05:56:50

无论如何(我是在C# .net中开发的--但这些原则希望对您仍然有帮助),我定义了一组类型(DTO),用于在业务层和数据层之间交换数据;并且每个域对象/实体都有多个类型。这些类被定义为简单的类。

其中每一个都是考虑到特定的任务而构建的,例如:

  • I有一个轻量级的类型,用于填充列表视图(有很多“行”,但没有很多“列”)。我也有一个对应的集合类型,其中包含任意数量的属性。
  • 我有一个“大”的get副本,它通常包含有问题实体的所有属性-但只针对它的一个实例。根据实体的大小和复杂性以及使用情况,我可能会有多个这样的类型;还取决于您是要立即返回与实体的实例关联的所有数据,还是要在以后的请求中延迟加载一些数据。
  • I通常也有单独的实体“保存”(新建)和“更新”类型。

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

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

架构Fit

这种方法没有什么特别之处,它有自己的优点和缺点;这些优点和缺点到底是什么以及它们如何影响您将取决于很多东西-我猜您的里程会有所不同-但它肯定已经为我服务了很多年。

人们经常对“关注点分离”大惊小怪-这是一个非常明智的举动;这与DTO有关,因为它们是在层(和服务、组件等)之间交换的,所以在究竟应该在哪里划线时总是有一些模棱两可的地方。

我采用的方法是,如果一些信息适合在to层之间交换,那么它可能适合在任何数量的层之间交换-所以为什么不让所有人都可以访问它呢?如果您只是传递信息,它还可以省去重新转换信息的麻烦。

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

  1. 使用冗长的/人类可读的命名约定;类型让你知道事物是什么;不管有多少-这就是智能(& docs)的用途。越直观越好。
  2. KISS-尽可能保持简单;你必须在合理的重用和单一责任原则之间取得平衡。

是否要为主实体的复杂属性创建

我发现自己做DTO有以下两个原因之一:

我知道我需要公开(推送)一些数据,

  1. 的设计是显而易见的:它是由我想要的数据驱动的,目的是让消费者知道它想要的是什么,而DTO就是为了满足这些需求而设计的。

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

在这两种情况下,DTO可以是特定于特定需求的,也可以是通用的;例如,只有一个int和一个字符串的DTO并不少见,它是用来发送到dropdownlists的那种东西。

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

票数 3
EN

Stack Overflow用户

发布于 2010-04-12 06:20:10

服务层应该返回DTO而不是EJB对象的想法主要是在EJB3/JPA时代之前的想法。在CRUD过程中,您可以从使用模型对象(也称为实体)。

但是,在用于性能优化时,您可以从使用DTO中获益,例如,当模型对象太大时,或者当您使用某些智能连接聚合模型数据时。

因此,除非您是在SOA下进行工程设计,否则我不建议使用DTO进行CRUD操作。

票数 1
EN

Stack Overflow用户

发布于 2010-04-12 10:27:36

您是否考虑过命令查询职责分离(CQRS)原则?简而言之,它是一种架构原则,提倡使用单独的组件进行读取和修改操作。

修改是使用发送给域模型的命令完成的。您的NewCarLeaseDTO看起来像一个命令-- CreateNewCarLeaseCommand。它们包含特定操作所需的所有数据。

另一方面,读取(无论是列表vies还是详细vies)直接在底层数据存储(SQL数据库)上完成。这里有许多可能性,从使用相同的数据存储来支持读取和写入部分,到通过发布/订阅基础设施连接两个独立的数据存储。

当使用后一种(两个存储)方法来读取端时,许多(比如Udi Dahan)提倡使用所谓的持久化视图。这意味着将数据直接存储在视图可使用的表单中。转换(反规范化)是在模型更新后进行同步时完成的。

如果你想了解更多关于CQRS的知识,我推荐阅读Udi Dahan和Greg Young。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2618617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档