价值对象应该包含多少业务逻辑?

18

我非常尊重的一个导师认为简单的Bean是浪费时间的,即使是价值对象也必须包含一些业务逻辑才有用。

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

我意识到这个问题是主观的。不过还是想问一下 - 想从更多的角度了解答案。

6个回答

35
将数据和业务逻辑放在一起的想法是为了促进封装,并尽可能少地向其他对象公开内部状态。这样,客户端可以依赖于接口而不是实现。参见“告诉,不要问”原则和迪米特法则。封装使得更容易理解数据可能处于的状态,更容易阅读代码,更容易解耦类,通常也更容易进行单元测试。
将业务逻辑外部化(通常是到“服务”或“管理器”类中)会使得回答“这些数据在哪里使用?”和“它可以处于哪些状态?”等问题变得更加困难。这也是一种过程式思维,包装在一个对象中。这可能会导致贫血领域模型
外部化行为并不总是坏的。例如,服务层可以编排领域对象,但不承担它们的状态操作职责。或者,当您大多数时间都在对数据库进行读/写操作并且这些操作与输入表单很好地映射时,也许您根本不需要领域模型——或者它所涉及的痛苦的对象/关系映射开销。
传输对象通常通过提供调用层所需的最小状态信息而不暴露任何业务逻辑来将架构层与彼此(或外部系统)解耦。
这可以很有用,例如在为视图准备信息时:只需给视图所需的信息,而不是其他任何东西,这样它就可以专注于如何显示信息,而不是要显示什么信息。例如,TO可能是几个数据源的汇总。
一个优点是你的视图和领域对象是解耦的。在JSP中使用领域对象可能会使你的领域更难重构,并促进了getter和setter的滥用(从而破坏了封装性)。
然而,拥有大量传输对象也会带来一些开销,通常也会有很多重复。我参与过的一些项目最终都会有TO基本上镜像其他领域对象(我认为这是一种反模式)。

1
很好的总结。可惜我发现自己在这么多年后还在使用“贫血领域模型”,尽管这些信息一直都在那里。谢谢! - nyxz

7

你最好称它们为Transfer Objects数据传输对象(DTO)

早期这个j2ee模式被称为“值对象”,但是他们改变了名称,因为它与此混淆了。

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

为了回答你的问题,我只会在我的DTO中放置最少的逻辑,这些逻辑是为了显示而需要的。
更好的方法是,如果我们谈论的是基于数据库的Web应用程序,我会超越核心j2ee模式,使用HibernateJava Persistence API创建支持关系惰性加载的领域模型,并在视图中使用它。
请参见Open session in view
这样,您就不必编写一组DTO,并且在视图/控制器等中可用所有业务逻辑。

6

这要看情况而定。

哎呀,我刚才是不是说了一个陈词滥调?

设计一个对象时需要问的基本问题是:当其他对象使用/消耗该对象的数据时,控制该对象数据的逻辑是否会有所不同或相同?

如果不同的使用领域需要不同的逻辑,请将其外部化。如果无论对象前往何处都是相同的逻辑,请将其与类一起放置。


4

我个人的偏好是将所有业务逻辑放在领域模型中,也就是在“真正”的领域对象中。因此,当创建数据传输对象时,它们基本上只是领域对象的(不可变)状态表示,因此不包含任何业务逻辑。它们可以包含克隆和比较方法,但是业务逻辑代码的主体仍然留在领域对象中。


谢谢:)。你能解释一下你所说的“真实”领域对象是什么意思吗? - Vivek Kodira

3

“Korros所说的话。”

值对象 := 一个小而简单的对象,例如货币或日期范围,其相等性不基于身份。

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

这些是Martin Fowler提出的定义,我想让它们更加通俗易懂。


2
我同意Panagiotis的观点:在视图模式中使用开放会话比使用DTOs更好。换句话说,如果您从视图层到底层使用领域对象(或其组合),则我发现应用程序要简单得多。
尽管如此,这很难实现,因为您需要使HttpSession与持久性层的工作单元相一致。然后,您需要确保所有数据库修改(即创建、更新和删除)都是有意的。换句话说,您不希望视图层具有一个领域对象,字段被修改并且修改被持久化,而应用程序代码没有有意地保存更改。另一个重要的问题是确保您的事务语义是令人满意的。通常,获取和修改一个领域对象将在一个事务上下文中进行,并且很容易使您的ORM层需要一个新事务。挑战在于嵌套事务,其中您想在打开的第一个事务上下文中包括第二个事务上下文。
如果您不介意调查非Java API如何处理这些问题,那么值得看看Rails的Active Record,它允许Ruby服务器页面直接使用领域模型并遍历其关联。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接