我知道这可能是一个古老的问题,但是更好的做法是什么?在应用程序的所有层中使用域模型对象,甚至在JSP上直接将值绑定到它们(我正在使用JSF)。或将域模型对象转换为DAO或服务层中的DTO,并将轻量级DTO发送到演示层。

有人告诉我使用DTO是没有意义的,因为对数据库的更改将导致所有DTO的更改,而到处使用模型对象只需要更改受影响的模型对象即可。但是,DTOS的易用性和轻巧的性质似乎超过了这一点。

我应该注意,我的应用程序使用Hibernate模型对象,并使用其自己的自定义创建的模型对象(这意味着不绑定到任何DB会话,始终分离)。上述方案中的任何一个都对严格的模型对象模式更有益吗?对于懒惰初始化例外,使用Hibernate是一个巨大的PITA。

我正在编辑这个问题,以期进一步讨论(不确定我是否正确这样做):

我对模型对象的问题是它们根本不灵活。下面的评论说,应该设计应用程序,以便可以在所有层中使用模型对象。为什么?如果用户想要一个荒谬的功能,我应该告诉他们:“那不适用于模型对象”吗?

简单而简单,有时候模型对象无法正常工作。你可能有:

public class Teacher {
    List<Student> students;
    [tons of other Teacher-related fields]
}
public class Student {
    double gpa;
   [tons of other Student-related fields]
}

但是也许您不需要所有这些信息。您只需要老师的姓氏,他们今年的学生人数以及所有学生的平均GPA。在这种情况下,您会怎么做?检索完整的教师信息和学生关系,然后您的代码会在学生列表上获得统计,然后计算内部所有GPA的总平均水平?这似乎比简单地使用“字符串lastname”,“ int numstudents”和'double CombinedGPA创建DTO更重要。

听起来我的思想已经弥补了这些,但是我还没有在一个应用程序中工作,在该应用程序中,模型对象在每种情况下都可以完全干净地使用。带有非凡用户需求的常规现实应用程序只是这种方式无法正常工作。

有帮助吗?

解决方案

这实际上取决于您应用程序的复杂性。将域对象混合到视图层有两个可能的含义:

  1. 您将很想修改您的域对象以适应您在视图层中所需的东西
  2. 您的视图层将包含由于域对象提供的内容和您的视图真正需要的不匹配而引起的额外复杂性。您可能无法解决此复杂性,但它可能不属于视图层。

如果您的域对象很简单,并且您的视图很少,那么跳过DTO可能是最简单的事情。

另一方面,如果您的域模型可能会发展并变得复杂,并且如果您的观点可能很多并且有多样化,那么拥有特定对象可能是一个好主意。在MVC世界中,使用ViewModels很普遍,对我来说很有意义。

其他提示

对域对象的另一票投票。就域驱动设计而言,域模型是国王,应在可能的情况下使用。该应用程序应以大多数层(条基础架构层)可以使用域对象的方式设计。

我认为DTO仅在需要序列化的情况下才有用。如果在电线上没有传输或进入不兼容的体系结构,我将不会使用它们。 DTO模式可用于将序列化排除在域对象之外。考虑到UI/域交互不需要序列化,保持简单并使用实际对象。

我认为拥有DTO通常不是一种反模式。有很多人和系统使用它们,您获得的好处是可以独立于域模型设计和模块化的脱钩视图层。尽管我同意,您应该在可能的情况下使用域对象,但在将视图层直接连接到域模型时,您可以在某些情况下遇到问题。

我已经通过一个视图模型获得了很好的体验,该模型只包裹域对象并将大部分操作委派给了它们。此脱离型视图和域层允许灵活地组成域对象,并且由于IDES支持而没有太多工作。委托模式。

域对象有问题的情况:

  1. 您可能需要发送到UI层的汇总信息或其他类型的“计算字段”(例如Flex / GWT),并且不想弄乱域对象
  2. 您可能遇到需要序列化循环对象图的需要(在您的示例中,如果学生有列表关系),则某些协议有问题
  3. 处理框架序列化器时的休眠懒惰化exception(Flex / GWT Serialializer的燃料)

我不确定这是那些cirumcstances的明确答案

我认为,在每一层中使用域模型对象根本没有问题。您说您不需要所有信息。当您进入JSP时,仅使用所需的数据。没有人强迫您获取每个属性。您还说您需要进行与对象属性相关的计算,以获取GPA,学生#等。和整洁;在控制器或服务层中进行计算,并通过适当的捕获器暴露它们;或将其全部处理在您的JSP中。无论如何,您都需要检索/编译/纠缠数据,因此为什么还要在DTO中添加更复杂的功能。

此外,在每个DTO中,您都可以创建一个。)您现在必须维护的额外类,b。)在某些类中至少有1个额外的方法来构建和填充DTO(DAO,出厂方法等) 。更多维护= 6个月后不快乐的开发人员。

因此,有我反对DTO的论点。我确实使用它们,但是只有在某些情况下,例如当我真正需要优化速度和/或内存使用情况时,以及对完整域模型对象的水化成本太多了。 Web服务是我更喜欢使用DTO的一个很好的例子。

班级或其内部方法的行为不应暴露于与其行为无关的层次。传输数据,而不是行为。在域内使用域对象。 Web不是受控的域,UI开发人员不必关注域行为,只有数据。

必须封装该域,并保护不关心域名的人进行修改。

泄漏行为不是最好的习惯。

如果这是一个小项目,也可以用正确的原理构建。这样一来,我们总是牢记为什么要做我们做的事情,而不仅仅是如何做。

我认为首先在这里应该考虑的是引入新层的成本。以DTO为例 - 这样做我们需要映射。正如某人所说,翻译是邪恶的,应尽可能避免。

另一方面,我认为您通常不应该做的事情很少。那些说所有DTO都是邪恶的人都是错误的 - 这总是取决于用例!他们真的是合理的吗?

最后,我个人认为应该放开域对象本身。想象一下检票口集成是什么样的。但是以Spring MVC为例 - 域将停留在应用程序层中...

如今,DTO被广泛认为是反对意见的,通常“不惜一切代价避免它们”。

Hibernate这样的ORM框架的主要优点之一是您可以在所有级别上使用域对象,并且实际上不需要DTOS。当然,需要注意的是,您必须有些奉献来思考这些关系:何时使用懒惰,何时使用急切的方式,等等。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top