最佳实践 – 多层架构和DTO

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

  • 假设持久层将使用类myproject.persistence.domain.UserEntity (基于JPA的实体)来存储数据库或从数据库加载数据。 要在视图中显示数据,我将提供另一个类myproject.service.domain.User 。 我在哪里转换它们? 用户的服务是否负责在两个类之间进行转换? 这真的有助于改善耦合吗?
  • User类应该如何? 它应该只包含不可变的getter吗? 编辑现有用户的视图(创建新用户 ,使用现有用户对象的getter等)不是很麻烦吗?
  • 我应该使用相同的DTO类( 用户 )向服务发送请求以修改现有用户/创建新用户还是应该实现其他类?
  • 通过使用myproject.service.domain中的所有DTO,表示层不会非常依赖于服务层吗?
  • 如何处理我自己的例外? 我的当前方法重新抛出大多数“严重”exception,直到它们由表示层处理(通常记录它们并且用户被告知出现了问题)。 一方面我有一个问题,我再次hava共享包。 另一方面,我仍然不确定这可以被视为“最佳实践”。 有任何想法吗?

谢谢你的任何答案。

松耦合确实是推荐的方法,这意味着你最终将会遇到巨大的,无聊的写入,难以在业务逻辑中维护转换器。 是的,它们属于业务逻辑:DAO和视图之间的层。 因此,业务层最终将取决于DAO DTO和视图DTO。 并将充满Converter类,稀释您对实际业务逻辑的看法……

如果您可以使用不可变的视图DTO,那就太棒了。 用于序列化它们的库可能要求它们具有setter。 或者,如果他们有安装人员,您可能会发现他们更容易构建。

对于视图和DAO使用相同的DTO类,我已经完成了。 这很糟糕,但老实说,我并不觉得系统更加分离,因为业务逻辑,最重要的部分,无论如何都必须依赖于一切。 这种紧密耦合提供了极好的简洁性,并使视图和DAO层更容易同步。 我仍然可以通过使用合成来使某些特定于其中一个层而不会在另一个层中看到。

最后,关于例外情况。 它是最外层的一个职责,即视图层(控制器,如果你使用Spring)来捕获从内层传播的错误,无论是使用exception,还是使用特殊的DTO字段。 然后,这个最外层需要决定是否通知客户端错误,以及如何。 事实是,在最内层,您需要区分最外层需要处理的不同类型的错误。 例如,如果DAO层中发生了某些事情,并且视图层需要知道是否返回400或500,则DAO层将需要为视图层提供决定使用哪一个所需的信息,并且此信息将需要通过所有中间级别,谁应该能够添加自己的错误和错误类型。 将IOException或SQLException传播到最外层是不够的,内层还需要告诉外层这是否是预期的错误。 伤心但真实。