【问题标题】:Spring MVC 3 - Binding an 'immutable' object to a formSpring MVC 3 - 将“不可变”对象绑定到表单
【发布时间】:2011-10-13 13:16:35
【问题描述】:

我有几个经过彻底的单元测试和精心制作的丰富 DDD 模型类,具有最终的不可变不变量和完整性检查。对象的实例化通过适当的构造函数、静态工厂方法甚至通过构建器进行。

现在,我必须提供一个 Spring MVC 表单来创建一些类的新实例。

在我看来(我不是专家)我必须为我想要绑定的所有表单的支持类提供空的构造函数和属性的设置器。

那么,我该怎么办?

创建专用于形成支持的贫血对象并将信息传输到我的域模型(对于 DRY 原则来说如此……)调用适当的方法/构建器?

或者有没有我错过的机制可以挽救我的一天? :)

提前感谢您的智慧!

【问题讨论】:

    标签: spring spring-mvc domain-driven-design immutability


    【解决方案1】:

    用于与表示层绑定的对象通常称为视图模型,它们是DTOs,旨在显示从域对象映射的数据,然后将用户输入映射回域对象。视图模型通常看起来与它们所代表的领域对象非常相似,但也有一些重要的区别:

    1. 来自域对象的数据可能会被展平或以其他方式转换以适应给定视图的要求。将映射放在普通对象中比在表示框架(如 MVC)中的映射更容易管理。更容易调试和检测错误。

    2. 给定的视图可能需要来自多个域对象的数据 - 可能没有一个域对象可以满足视图的要求。一个视图模型可以由多个领域对象填充。

    3. 视图模型通常在设计时考虑到特定的表示框架,因此可以利用框架特定的属性进行绑定和客户端验证。正如您所说,典型的要求是无参数构造函数,这对于视图模型来说很好。同样,与某种复杂的映射机制相比,测试和管理视图模型要容易得多。

    视图模型似乎违反了 DRY 原则,但仔细观察后视图模型的职责是不同的,因此考虑到single responsibility principle,有两个类是合适的。另外,请查看this 文章,讨论通常由 DRY 原则导致的重用谬误。

    此外,视图模型确实是贫乏的,尽管它们可能具有接受域对象作为参数的构造函数以及使用视图模型中的值作为输入来创建和更新域对象的方法。根据经验,我发现为每个将由表示层呈现的域实体创建一个视图模型类是一种很好的做法。管理域对象和视图模型的双重类层次结构比管理复杂的映射机制更容易。

    另请注意,有些库试图简化视图模型和域对象之间的映射,例如 .NET Framework 的 AutoMapper

    【讨论】:

    • 虽然我不太关心 DRY,但我也不喜欢不必要的层,如果我可以在实体与视图结构足够相似时绑定到域实体,那就太好了.对于中等复杂的场景,将视图模型与域实体分开是很好的,但对于非常简单的场景(“firstName”、“middleName”、“lastName”,在域中具有非常简单的 Name 实体)有一个额外的视图模型类似乎只是浪费的忙碌工作/样板。可悲的是,我没有看到太多选择。
    【解决方案2】:

    是的,您需要为表单创建对象以获取所有输入,并在一次操作中使用此对象更新您的模型。

    但我不会称这些对象为贫血(特别是如果您使用 DDD)。这些对象代表一个工作单元。所以这也是领域概念!

    【讨论】:

      【解决方案3】:

      我通过创建 DTO 接口解决了这个问题:

      public interface DTO<T> {
          T getDomainObject();
      
          void loadFromDomainObject(T domainObject);
      }
      
      public class PersonDTO implements DTO<Person> {
          private String firstName;
          private String lastName;
      
          public PersonDTO() {
              super();
          }
      
          // setters, getters ...
      
          @Override
          public Person getDomainObject() {
              return new Person(firstName, lastName);
          }
      
          @Override
          public void loadFromDomainObject(Person person) {
              this.firstName = person.getFirstName();
              this.lastName = person.getLastName();
          }
      
          // validation methods, view formatting methods, etc
      }
      

      这也阻止了视图验证和格式化内容泄漏到域模型中。我真的不喜欢在我的域对象中使用 Spring 特定(或其他框架特定)注释(@Value 等)和 javax.validation 注释。

      【讨论】:

        猜你喜欢
        • 2011-01-14
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-29
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        相关资源
        最近更新 更多