14

我尊敬的一位导师建议,一个简单的 bean 是浪费时间 - 值对象“必须”包含一些有用的业务逻辑。

另一个人说这样的代码很难维护,所有的业务逻辑都必须外部化。

我意识到这个问题是主观的。无论如何都要问——想从更多的角度知道答案。

4

6 回答 6

29

将数据和业务逻辑放在一起的想法是促进封装,并尽可能少地将内部状态暴露给其他对象。这样,客户端可以依赖接口而不是实现。请参阅“告诉,不要问”原则和得墨忒耳法则。封装使得更容易理解数据可以处于的状态、更容易阅读代码、更容易解耦类并且通常更容易进行单元测试。

将业务逻辑外部化(通常为“服务”或“经理”类)会产生诸如“这些数据在哪里使用?”之类的问题。和“它可以处于什么状态?” 更难回答。这也是一种程序性的思维方式,包裹在一个对象中。这会导致领域模型贫乏

外化行为并不总是坏事。例如,服务层可能会编排域对象,但不会接管它们的状态操作职责。或者,当您主要对能够很好地映射到输入表单的数据库进行读/写时,也许您根本不需要域模型——或者它所带来的痛苦的对象/关系映射开销。

传输对象通常通过提供调用层所需的最少状态信息来将架构层彼此(或与外部系统)解耦,而不暴露任何业务逻辑。

这可能很有用,例如在为视图准备信息时:只为视图提供它需要的信息,而不是其他任何东西,这样它就可以专注于如何显示信息,而不是显示什么信息。例如,TO 可能是多个数据源的聚合。

一个优点是您的视图和域对象是分离的。在 JSP 中使用你的域对象会使你的域更难重构,并促进了对 getter 和 setter 的不加选择的使用(因此破坏了封装)。

但是,也存在与拥有大量传输对象相关的开销,并且通常也会产生大量重复。我参与的一些项目最终得到了 TO,它们基本上反映了其他域对象(我认为这是一种反模式)。

于 2008-09-21T09:18:16.227 回答
7

您最好将它们称为传输对象数据传输对象 (DTO)

早些时候,同样的 j2ee 模式被称为“值对象”,但他们更改了名称,因为它与此混淆

http://dddcommunity.org/discussion/messageboardarchive/ValueObjects.html

为了回答您的问题,我只会将最少的逻辑放在我的 DTO 中,即出于显示原因所需的逻辑。

更好的是,如果我们谈论的是基于数据库的 Web 应用程序,我会超越核心 j2ee 模式并使用HibernateJava Persistence API创建一个支持延迟加载关系的域模型并在视图中使用它。

请参阅视图中的打开会话

通过这种方式,您不必编写一组 DTO,并且您可以在视图/控制器等中使用所有业务逻辑。

于 2008-09-21T07:13:02.410 回答
6

这取决于。

哎呀,我只是脱口而出陈词滥调吗?

设计对象时要问的基本问题是:当其他对象使用/消费时,控制对象数据的逻辑会不同还是相同?

如果不同的使用领域需要不同的逻辑,请将其外部化。如果无论对象到哪里都相同,则将其与类放在一起。

于 2008-09-21T05:46:38.263 回答
4

我个人的偏好是将所有业务逻辑放在域模型本身中,即“真正的”域对象中。因此,当创建数据传输对象时,它们大多只是域对象的(不可变)状态表示,因此不包含业务逻辑。虽然它们可以包含用于克隆和比较的方法,但业务逻辑代码的核心仍保留在域对象中。

于 2008-09-21T05:43:29.677 回答
3

科罗斯所说的。

Value Object := 一个小的简单对象,例如金钱或日期范围,其相等性不基于身份。

DTO := 在进程之间携带数据以减少方法调用次数的对象。

这些是 Martin Fowler 提出的定义,我想普及一下。

于 2008-09-21T07:19:18.633 回答
2

我同意 Panagiotis 的观点:视图模式中的开放会话比使用 DTO 好得多。换句话说,我发现如果您从视图层一直向下传输域对象(或其组合),应用程序会简单得多。

也就是说,这很难实现,因为您需要使 HttpSession 与持久层的工作单元一致。然后您需要确保所有数据库修改(即创建、更新和删除)都是有意的。换句话说,您不希望视图层具有域对象、字段被修改并且修改被持久化而应用程序代码没有故意保存更改的情况。另一个需要处理的重要问题是确保您的事务语义令人满意。通常获取和修改一个域对象将在一个事务上下文中进行,并且使您的 ORM 层需要一个新事务并不难。什么具有挑战性的是嵌套事务,您希望在打开的第一个事务上下文中包含第二个事务上下文。

如果您不介意研究非 Java API 如何处理这些问题,那么值得看看 Rails 的 Active Record,它允许 Ruby 服务器页面直接使用域模型并遍历其关联。

于 2008-09-21T18:19:09.313 回答