视图层中的 DTO 还是域模型对象?
我知道这可能是一个古老的问题,但是更好的做法是什么?在应用程序的所有层中使用域模型对象,甚至在 JSP 上将值直接绑定到它们(我正在使用 JSF)。或者在 DAO 或 Service 层将领域模型对象转换为 DTO,并将轻量级 DTO 发送到表示层。
我被告知使用 DTO 没有任何意义,因为对数据库的更改将导致对所有 DTO 的更改,而在任何地方使用模型对象只需要对受影响的模型对象进行更改。然而,DTO 的易用性和轻量级特性似乎更重要。
我应该注意,我的应用程序使用 Hibernate 模型对象并使用自己的自定义创建的模型对象(意味着不绑定到任何数据库会话,始终分离)。上述两种情况是否对严格的模型对象模式更有利?对于诸如延迟初始化异常之类的事情,使用 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 的总平均值?这似乎比简单地使用“String lastName”、“int numStudents”和“double mergedGpa”创建 DTO 要花费更多的精力;
听起来我已经决定了这些,但我还没有在一个应用程序中工作,模型对象可以在每个实例中完全干净地使用。具有非常规用户需求的常规现实应用程序就不会以这种方式工作。
I know this is probably an age-old question, but what is the better practice? Using a domain model object throughout all layers of your application, and even binding values directly to them on the JSP (I'm using JSF). Or convert a domain model object into a DTO in the DAO or Service layer and send a lightweight DTO to the presentation layer.
I have been told it makes no sense to use DTOs because changes to the database will result in changes to all your DTOs whereas using Model Objects everywhere will just require changes to the affected model object. However, the ease of use and the lightweight nature of DTOs seems to outweigh that.
I should note that my app uses Hibernate Model Objects AND uses its own custom-created model objects (meaning not bound to any DB session, always detached). Is either of the above scenarios more beneficial to a strict Model Object pattern? Using Hibernate has been a huge PITA with regards to things like Lazy Initialization Exceptions.
I am editing this question in hopes of furthering discussion (not sure if I'm doing this right):
The problem I have with model objects is that they are not flexible at all. A comment below says that the application should be designed so that model objects can be used throughout all layers. Why? If a user wants a piece of ridiculous functionality, am I supposed to tell them, 'well that won't work with model objects'?
Plain and simple, there are just times when model objects won't work. You may have:
public class Teacher {
List<Student> students;
[tons of other Teacher-related fields]
}
public class Student {
double gpa;
[tons of other Student-related fields]
}
but maybe you don't need all that information. You just need the teacher's last name, the number of student's they teach this year, and average GPA for all students combined. What would you do in that case? Retrieve the full teacher information and student relationships and then your code gets a count on the List of Students, then computes a total average of all gpas inside? That seems like waaaay more effort than simply creating a DTO with 'String lastName', 'int numStudents', and 'double combinedGpa;
It may sound like my mind has been made up on these, but I have yet to work in an application where model objects can be completely used cleanly in every instance. Regular real-world applications with out-of-the-ordinary user demands just do not work that way.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这实际上取决于您的应用程序的复杂性。将域对象混合到视图层中可能会产生两个影响:
如果您的域对象很简单并且视图很少,那么跳过 DTO 可能是最简单的事情。
另一方面,如果您的领域模型可能会发展并变得复杂,并且您的视图可能数量众多且多种多样,那么查看特定对象可能是一个好主意。在 MVC 世界中,使用 ViewModel 很常见,并且对我来说很有意义。
It really depends on the complexity of your application. Mixing domain objects into the view layer has two possible implications:
If your domain objects are simple and your views are few, skipping the DTOs might be the simplest thing.
On the other hand, if your domain model is likely to evolve and become complex and if your views are likely to be numerous and varied, having view specific objects might be a good idea. In the MVC world, using ViewModels is common and makes a lot of sense to me.
对域对象的另一次投票。就领域驱动设计而言,领域模型是王道,应该尽可能使用。应用程序的设计方式应使大多数层(基础设施层除外)都可以使用域对象。
我认为 DTO 仅在对象需要序列化时才有用。如果没有通过线路传输或进入不兼容的架构,我不会使用它们。 DTO 模式对于将序列化排除在域对象之外非常有用。考虑到 UI/域交互不需要序列化,请保持简单并使用实际对象。
Another vote for domain objects. As far as Domain Driven Design is concerned the domain model is the king and should be used where possible. The application should be designed in a way where most layers (bar Infrastructure layer) can use domain objects.
I think of DTOs as useful only where the objects need to be serialised. If there is no transfer over the wire or into an incompatible architecture I would not use them. DTO pattern is useful for keeping serialisation out of the domain object. Considering that UI/Domain interaction does not need serialisation, keep it simple and use the actual objects.
我认为 DTO 通常并不是一种反模式。有很多人和系统在使用它们,您获得的好处是可以独立于领域模型进行设计和模块化的解耦视图层。尽管我同意您应该尽可能使用域对象,但在某些情况下,当您将视图层直接绑定到域模型时,您可能会遇到问题。
我在视图模型方面取得了很好的经验,该视图模型仅包装域对象并将大部分操作委托给它们。这将视图和域层解耦,允许灵活地组合域对象,并且由于 IDE 支持,因此实现起来仍然不需要太多工作委托模式。
I think having DTO is not generally an anti pattern. There are a lot of people and systems using them and the benefit you get is the decoupled view layer that can be designed and modularized independently from the domain model. Although I agree that you should use domain objects where possible there are scenarios where you can get problems when you tie the view layer directly to the domain model.
I have made good experiences with a view model that only wraps around the domain objects and delegates most of the operations to them.This decouples view and domain layer, allows for flexible composition of domain objects and still is not much work to implement since IDEs support delegation pattern.
域对象发送有问题的场景:
我不确定这是否是一个明确的答案那些情况
Scenarios when Domain Object are problematic to be sent :
I'm not sure it's a clear cut answer in those cirumcstances
在我看来,在每一层中使用领域模型对象完全没有问题。您说过您不需要所有信息。当您在 JSP 中时,仅使用您需要的数据。没有人强迫你拿走所有财产。您还说,您需要进行与对象属性相关的计算,以获得 GPA、学生数量等。您有 3 个选择:在域模型对象中创建合成属性,为您返回正确的数据,包装得很好且整洁;在控制器或服务层中进行计算,并通过适当的 getter 公开它们;或者在您的 JSP 中处理这一切。无论如何,您都需要检索/编译/整理数据,那么为什么要使用 DTO 来增加更多的复杂性呢?
此外,对于每个 DTO,您都在创建 a.) 现在必须维护的额外类,以及 b.) 在某个类中至少有 1 个额外方法来构造和填充 DTO(DAO、工厂方法等) 。更多维护 = 6 个月后开发人员不满意。
因此,我有一些反对 DTO 的观点。我确实使用它们,但仅在某些情况下使用,例如当我确实需要优化速度和/或内存使用时,并且水合完整域模型对象的成本太大。 Web 服务是我更喜欢使用 DTO 的一个很好的例子。
In my opinion, there's no problem at all with using domain model objects in every layer. You said that you don't need all of the information. When you're in your JSPs, use only the data that you need. No one is forcing you to fetch every property. You also said that you need to make calculations related to the object's properties in order to get GPA, # of students, etc. You have 3 options: create synthetic properties in your domain model object that return the right data for you, wrapped up nice and neat; do the calculations in either the controller or service layer, and expose them through the appropriate getters; or handle it all inside your JSP. You need to retrieve/compile/wrangle the data ANYWAY, so why add more complexity with a DTO.
Additionally, with each DTO, you're creating a.) an extra class you now have to maintain, and b.) at LEAST 1 extra method somewhere in some class that constructs and populates the DTO (DAO, factory method, etc.). More maintenance = unhappy developer 6 months later.
So, there are my arguments against DTOs. I do use them, but only in certain scenarios, like when I really need to optimize for speed and/or memory usage, and the cost of hydrating a full domain model object is way too much. Web services are a good example of when I prefer to use DTOs.
我认为我们首先应该考虑的是引入新层的成本。以 DTO 为例 - 为此我们需要一个映射。正如有人所说,翻译是邪恶的,应该尽可能避免。
另一方面,我认为很少有事情是你通常不应该做的。那些说所有 DTO 都是邪恶的人是错误的 - 这始终取决于用例!他们真的有道理吗?
最后,我个人认为域对象应该交给视图本身。想象一下检票口整合会是什么样子。但以 Spring MVC 为例 - 域可能会留在应用程序层......
I think what we should consider here in the first place is the cost of introducing new layer. Take DTO for instance - doing that we need a mapping. As someone said, translation is evil and should be avoided whenever possible.
On the other hand I think there are very few things that you generally should not do. Those who say all DTOs are evil are wrong - it always depends on the use case! Are they really justified?
And finally, I personally believe the domain objects should be let go to the view itself. Imagine what the wicket integration is then like. But take Spring MVC for instance - domain would stay then in the application layer probably...
类的行为或其内部方法不应暴露给与其行为无关的层。传输数据,而不是行为。在域内使用域对象。 Web 不是一个受控域,UI 开发人员不需要关心域行为,只需关心数据。
域必须被封装,并防止被不关心域健康的人修改。
泄漏行为并不是最好的习惯。
如果是小项目,也要按照正确的原则来构建。这样我们就能始终牢记为什么要做我们所做的事情,而不仅仅是如何做。
The behavior of a class, or its internal methods should not be exposed to layers not concerned with their behaviour. Transfer data, not behaviour. Use domain objects within the domain. The web is not a controlled domain, and UI developers need not be concerned with domain behaviour, just data.
The domain has to be encapsulated, and protected from modification by someone not concerned with the health of the domain.
Leaking behaviour is not the best habit.
If it is a small project, built it with correct principes as well. That way we always keep in mind why we do what we do, and not just how.
使用 DTO 的原因之一是当您需要向不同类型的用户显示信息时。例如,您有一个“帐户”域模型,并且它有一些属性,例如“created_at”。根据您的业务逻辑,您可以向管理员和用户显示帐户,但实际上不允许用户了解帐户的创建日期(出于某些公司机密原因)。为管理员和用户提供域模型可能非常危险,特别是如果您使用 JSON API,但如果您将表示形式拆分为 2 个不同的 DTO(对于管理员和用户),那么它会安全得多。我不得不说,这将需要更多的时间来处理和维护这一点,但如果您的应用程序需要这种类型的安全性和严格性,那么您别无选择。
One of the reasons to use DTOs is when you need to display information to different types of users. E.g. you have an "account" domain model, and it has some property, e.g. "created_at". Depending on your business logic, you could show account to admins and to users, but users are not really allowed to know about creation date of an account (for some company secret reasons). Serving domain model to both admin and users could be very dangerous, especially if you are using JSON API, but if you split representation into 2 different DTOs - for admins and users, then it will be much safer. I have to say that it will require much more time to deal with and maintain this, but if your app requires this type of security and strictness, then you have no other choice.
如今,DTO 被广泛认为是一种反模式,建议通常是“不惜一切代价避免它们”。
像 Hibernate 这样的 ORM 框架的主要优点之一是您可以在所有级别使用域对象,并且实际上并不需要 DTO。当然,需要注意的是,您必须花一些时间来思考这些关系:何时使用延迟获取,何时使用渴望等等。
DTO is widely considered an anti-pattern nowadays, and the advice is usually "avoid them at all costs".
One of the main advantages of an ORM framework like Hibernate, is that you can use domain objects at all levels, and don't really need DTOs. The caveat, of course, is that you have to dedicate sometime to THINK on those relationships: when to use lazy fetching, when to use eager, etc.