最佳实践 - 多层架构和DTO [英] Best Practice - Multi Layer Architecture and DTOs

查看:122
本文介绍了最佳实践 - 多层架构和DTO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在stackoverflow上阅读了一些Q / As之后,我仍然对在我的Web应用程序中正确实现DTO感到困惑。我当前的实现是一个(基于Java EE的)多层体系结构(具有持久性,服务和表示层),但是所有层都使用公共包,包含(以及其他)域对象。在这种情况下,层不能真正被认为是独立的。
我打算逐步删除常用软件包,但遇到各种挑战/问题:

After reading some of the Q/As here on stackoverflow, I am still confused about the correct implementation of DTOs in my web application. My current implementation is a (Java EE based) multi-tier architecture (with persistence, service and presentation layer) but with a "common" package used by all layers, containing (amongst others) domain objecs. In this case the layers can not really be considered as independent. I am planning to remove the common package step by step, but I encounter various challenges/questions:


  • 假设持久层将使用类 myproject.persistence.domain.UserEntity (基于JPA的实体)来存储数据库或从数据库加载数据。要在视图中显示数据,我将提供另一个类 myproject.service.domain.User 。我在哪里转换它们?用户的服务是否负责在两个类之间进行转换?这真的有助于改善耦合吗?

  • 用户类应该如何?它应该只包含不可变的getter吗?编辑现有用户的视图(创建新的用户,使用现有用户对象的getter等)不是很麻烦吗?

  • 我应该使用相同的DTO类(用户)向服务发送请求以修改现有用户/创建新用户还是应该实现其他类?

  • 使用 myproject.service.domain 中的所有DTO,表示层不会非常依赖服务层吗?

  • 如何处理我自己的例外?我的当前方法重新抛出大多数严重异常,直到它们由表示层处理(通常记录它们并且用户被告知出现了问题)。一方面我有一个问题,我再次hava共享包。另一方面,我仍然不确定这可以被视为最佳实践。有什么想法吗?

  • Assume the persistence layer would use a class myproject.persistence.domain.UserEntity (a JPA based entity) to store and load data to/from the database. To show data in the view I would provide another class myproject.service.domain.User. Where do I convert them? Would the service for the users be responsible to convert between the two classes? Would this really help to improve the coupling?
  • How should the User class look like? Should it contain only getters to be immutable? Wouldn't it be cumbersome for the views to edit existing users (create a new User, use the getters of the existing User object etc.)?
  • Should I use the same DTO-classes (User) to send a request to the service to modify an existing user/create a new user or should I implement other classes?
  • Wouldn't the presentation layer be very dependent on the service layer by using all the DTOs in myproject.service.domain?
  • How to handle my own exceptions? My current approach rethrows most "severe" exceptions until they are handled by the presentation layer (usually they are logged and the user is informed that something went wrong). On the one hand I have the problem that I hava again a shared package. On the other hand I am still not sure that this can be considered "best practice". Any ideas?

感谢您的回答。

推荐答案

在不同层中包含一些包并不罕见,但通常只针对日志记录等横切关注点。您的模型不应由不同的图层共享,或者对模型的更改需要在所有这些图层中进行更改。通常,您的模型是一个较低的层,靠近数据层(上方,下方或交织在一起,具体取决于方法)。

Having some packages among different layers is not uncommon, however it is usually done only for cross-cutting concerns such as logging. Your model should not be shared by different layers, or changes to the model would require changes in all those layers. Typically, your model is a lower layer, close to data layer (over, under, or intertwined, depending on the approach).

数据传输对象,顾名思义,是用于传输数据的简单类。因此,它们通常用于层之间的通信,特别是当您拥有通过消息而非对象进行通信的SOA体系结构时。 DTO应该是不可变的,因为它们仅仅是为了传递信息而不是改变它而存在。

Data Transfer Objects, as their name imply, are simple classes used to transfer data. As such, they are usually used to communicate between layers, specially when you have a SOA architecture which communicates through messages and not objects. DTOs should be immutable since they merely exist for the purpose of transferring information, not altering it.

你的域对象是一回事,你的DTO是另一回事,而且您在表示层中需要的对象是另一回事。但是,在小型项目中,实施所有这些不同的集合并在它们之间进行转换可能不值得。这仅仅取决于您的要求。

Your domain objects are one thing, your DTOs are a different thing, and the objects you need in your presentation layer are yet another thing. However, in small projects it may not be worth the effort of implementing all those different sets and converting between them. That just depends on your requirements.

您正在设计一个Web应用程序,但它可能有助于您的设计问自己,我可以通过桌面应用程序切换我的Web应用程序吗?我的服务层真的不知道我的表示逻辑吗?用这些术语思考将指导您建立更好的架构。

You are designing a web application but it may help your design to ask yourself, "could I switch my web application by a desktop application? Is my service layer really unaware of my presentation logic?". Thinking in these terms will guide you towards a better architecture.

关于您的问题:


假设持久层将使用类myproject.persistence.domain.UserEntity(基于JPA的实体)来存储数据库或从数据库加载数据。要在视图中显示数据,我将提供另一个类myproject.service.domain.User。我在哪里转换它们?用户的服务是否负责在两个类之间进行转换?这真的有助于改善耦合吗?

Assume the persistence layer would use a class myproject.persistence.domain.UserEntity (a JPA based entity) to store and load data to/from the database. To show data in the view I would provide another class myproject.service.domain.User. Where do I convert them? Would the service for the users be responsible to convert between the two classes? Would this really help to improve the coupling?

服务层知道它的类(DTO)和它下面的层(让我们说持久性)。所以是的,该服务负责在持久性和自身之间进行转换。

The service layer knows its classes (DTOs) and the layer below it (let's say persistence). So yes, the service is responsible for translating between persistence and itself.


User类应该如何?它应该只包含不可变的getter吗?编辑现有用户的视图(创建新用户,使用现有用户对象的getter等)不是很麻烦吗?

How should the User class look like? Should it contain only getters to be immutable? Wouldn't it be cumbersome for the views to edit existing users (create a new User, use the getters of the existing User object etc.)?

DTO背后的想法是您只使用它们进行传输,因此不需要创建新用户等操作。为此你需要不同的对象。

The idea behind DTOs is that you only use them for transfer, so operations like creating a new user are not required. For that you need different objects.


我是否应该使用相同的DTO类(用户)向服务发送请求以修改现有用户/创建新用户还是应该实现其他类?

Should I use the same DTO-classes (User) to send a request to the service to modify an existing user/create a new user or should I implement other classes?

服务方法可能表示操作,DTO是其参数只包含数据。另一种选择是使用代表操作的命令并且还包含DTO。这在SOA体系结构中很流行,其中您的服务可能仅仅是一个命令处理器,例如只有一个执行操作,需要 ICommand interface as parameter(与每个命令只有一个操作相对)。

The service methods might express the operation, the DTOs being its parameters containing just the data. Another option is using commands which represent the operation and also contain the DTOs. This is popular in SOA architectures where your service may be a mere command processor for instance having one single Execute operation taking a ICommand interface as parameter (as opposed to having one operation per command).


表示层不会非常依赖于服务层通过使用myproject.service.domain中的所有DTO?

Wouldn't the presentation layer be very dependent on the service layer by using all the DTOs in myproject.service.domain?

是的,服务层上的图层将依赖于它。这就是主意。好处是只有该层依赖于它,没有上层或下层,因此更改只会影响该层(与您从每个层使用域类时不同)。

Yes, the layer over the service layer will be dependent on it. That is the idea. The upside is that only that layer is dependent on it, no upper or lower layers so changes only affect that layer (unlike what happens if you use your domain classes from every layer).


如何处理我自己的异常?我的当前方法重新抛出大多数严重异常,直到它们由表示层处理(通常记录它们并且用户被告知出现了问题)。一方面我有一个问题,我再次hava共享包。另一方面,我仍然不确定这可以被视为最佳实践。有什么想法?

How to handle my own exceptions? My current approach rethrows most "severe" exceptions until they are handled by the presentation layer (usually they are logged and the user is informed that something went wrong). On the one hand I have the problem that I hava again a shared package. On the other hand I am still not sure that this can be considered "best practice". Any ideas?

每一层都有自己的例外。它们从一层流到另一层,封装成下一种异常。有时,它们将由一个层来处理,这将执行某些操作(例如,记录),然后可能抛出一个上层必须处理的异常。其他时候,他们可能会被处理,问题可能会得到解决。考虑一下连接数据库的问题。它会引发异常。您可以处理它并决定在一秒钟后重试,然后可能会成功,因此异常不会向上流动。如果重试也失败,则会重新抛出异常并且它可能一直流到表示层,您可以优雅地通知用户并要求他重试图层。

Each layer can have its own exceptions. They flow from one layer to another encapsulated into the next kind of exception. Sometimes, they will be handled by one layer which will do something (logging, for instance) and maybe then throw a different exception that an upper layer must handle. Other times, they might be handled and the problem might be solved. Think for instance of a problem connecting to the database. It would throw an exception. You could handle it and decide to retry after a second and maybe then there is success, thus the exception would not flow upwards. Should the retry also fail, the exception would be re-thrown and it may flow all the way up to the presentation layer where you gracefully notify the user and ask him to retry layer.

这篇关于最佳实践 - 多层架构和DTO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆