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

发布于 2024-07-04 22:04:52 字数 1721 浏览 8 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

终弃我 2024-07-11 22:04:52

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

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

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

I agree with Panagiotis: the open session in view pattern is much better than using DTOs. Put otherwise, I've found that an application is much much simpler if you traffic in your domain objects(or some composite thereof) from your view layer all the way down.

That said, it's hard to pull off, because you will need to make your HttpSession coincident with your persistence layer's unit of work. Then you will need to ensure that all database modifications (i.e. create, updates and deletes) are intentional. In other words, you do not want it be the case that the view layer has a domain object, a field gets modified and the modification gets persisted without the application code intentionally saving the change. Another problem that is important to deal with is to ensure that your transactional semantics are satisfactory. Usually fetching and modifying one domain object will take place in one transactional context and it's not difficult to make your ORM layer require a new transaction. What is challenging is is a nested transaction, where you want to include a second transactional context within the first one opened.

If you don't mind investigating how a non-Java API handles these problems, it's worth looking at Rails' Active Record, which allows Ruby server pages to work directly with the domain model and traverse its associations.

一身仙ぐ女味 2024-07-11 22:04:52

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

My personal preference is to put all business logic in the domain model itself, that is in the "true" domain objects. So when Data Transfer Objects are created they are mostly just a (immutable) state representation of domain objects and hence contain no business logic. They can contain methods for cloning and comparing though, but the meat of the business logic code stays in the domain objects.

云裳 2024-07-11 22:04:52

科罗斯说的话。

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

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

这些是马丁·福勒提出的定义,我想普及它们。

What Korros said.

Value Object := A small simple object, like money or a date range, whose equality isn't based on identity.

DTO := An object that carries data between processes in order to reduce the number of method calls.

These are the defintions proposed by Martin Fowler and I'd like to popularize them.

驱逐舰岛风号 2024-07-11 22:04:52

这取决于。

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

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

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

It depends.

oops, did I just blurt out a cliche?

The basic question to ask for designing an object is: will the logic governing the object's data be different or the same when used/consumed by other objects?

If different areas of usage call for different logic, externalise it. If it is the same no matter where the object travels to, place it together with the class.

对不⑦ 2024-07-11 22:04:52

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

混淆

早些时候,这个相同的 j2ee 模式被称为“值对象”,但他们更改了名称,因为它与 http://dddcommunity.org/discussion/messageboardarchive/ValueObjects.html

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

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

请参阅在视图中打开会话

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

You should better call them Transfer Objects or Data transfer objects (DTO).

Earlier this same j2ee pattern was called 'Value object' but they changed the name because it was confused with this

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

To answer your question, I would only put minimal logic to my DTOs, logic that is required for display reasons.

Even better, if we are talking about a database based web application, I would go beyond the core j2ee patterns and use Hibernate or the Java Persistence API to create a domain model that supports lazy loading of relations and use this in the view.

See the Open session in view.

In this way, you don't have to program a set of DTOs and you have all the business logic available to use in your views/controllers etc.

旧街凉风 2024-07-11 22:04:52

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

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

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

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

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

优点之一是您的视图和域对象是解耦的。 在 JSP 中使用域对象可能会使域更难重构,并导致滥用 getter 和 setter(从而破坏封装)。

然而,也存在与大量传输对象以及通常大量重复相关的开销。 我参与的一些项目最终的 TO 基本上反映了其他域对象(我认为这是一种反模式)。

The idea of putting data and business logic together is to promote encapsulation, and to expose as little internal state as possible to other objects. That way, clients can rely on an interface rather than on an implementation. See the "Tell, Don't Ask" principle and the Law of Demeter. Encapsulation makes it easier to understand the states data can be in, easier to read code, easier to decouple classes and generally easier to unit test.

Externalising business logic (generally into "Service" or "Manager" classes) makes questions like "where is this data used?" and "What states can it be in?" a lot more difficult to answer. It's also a procedural way of thinking, wrapped up in an object. This can lead to an anemic domain model.

Externalising behaviour isn't always bad. For example, a service layer might orchestrate domain objects, but without taking over their state-manipulating responsibilities. Or, when you are mostly doing reads/writes to a DB that map nicely to input forms, maybe you don't need a domain model - or the painful object/relational mapping overhead it entails - at all.

Transfer Objects often serve to decouple architectural layers from each other (or from an external system) by providing the minimum state information the calling layer needs, without exposing any business logic.

This can be useful, for example when preparing information for the view: just give the view the information it needs, and nothing else, so that it can concentrate on how to display the information, rather than what information to display. For example, the TO might be an aggregation of several sources of data.

One advantage is that your views and your domain objects are decoupled. Using your domain objects in JSPs can make your domain harder to refactor and promotes the indiscriminate use of getters and setters (hence breaking encapsulation).

However, there's also an overhead associated with having a lot of Transfer Objects and often a lot of duplication, too. Some projects I've been on end up with TO's that basically mirror other domain objects (which I consider an anti-pattern).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文