MVC模型对象,域对象和DTO之间有什么区别

时间:2010-10-04 08:44:48

标签: model-view-controller model architecture dto

MVC模型对象,域对象和DTO之间有什么区别?

我的理解是:

MVC模型对象:

为相应视图显示的数据建模。它可能不直接映射到域对象,即可能包括来自一个或多个域对象的数据。

  1. 客户端
  2. 可能包含业务逻辑。例如。验证,计算属性等
  3. 没有持久性相关的方法
  4. 域对象:

    对问题域中的现实世界对象进行建模的对象,如预订,客户,订单等。用于保存数据。

    1. 服务器端
    2. 没有业务逻辑
    3. DTO(数据传输对象):

      当层处于不同的进程中时,用于在层之间传输数据的对象,例如,从数据库到客户端应用程序。在获取与多个域对象相对应的数据时,允许跨线的单个事务而不是多个调用。 DTO仅包含数据和访问器方法,并且不存在逻辑。数据用于特定的数据库事务,因此它可能会也可能不会直接映射到域对象,因为它可能包含来自一个或多个域对象的数据。

      1. 在层之间传递时,在服务器端和客户端使用
      2. 没有业务逻辑
      3. 没有持久性相关的方法
      4. 所以,问题:

        1. 以上理解是否正确?我错过了一些关键点吗?

        2. 是否有任何理由不将Domain对象用作MVC模型,假设Model对象不需要额外的业务逻辑?

        3. 是否有任何理由不使用DTO作为MVC模型,假设Model对象不需要额外的业务逻辑?

7 个答案:

答案 0 :(得分:16)

域和模型对象本质上是相同的,可能包含业务逻辑。根据实现,如果将业务逻辑从模型中移除到服务类中,则域和DTO对象可能是等效的。

DTO的一个关键变体通常是视图模型,它纯粹用于在域模型和视图之间传输数据,尽管View模型通常可能包含逻辑,尽管这应该是纯粹的UI逻辑。

答案 1 :(得分:8)

Domain和DTO也可以是您的“模型”对象 - 您可以拥有一个视图来呈现“Customer”域对象的详细信息。

域对象可以具有业务逻辑来强制执行域实体的属性。验证就是这样一种情况。域对象本身不包含与持久性相关的方法,但它可以具有支持持久性的元数据(如注释)

POJO编程模型可以使用与您的域,DTO和模型对象相同的对象 - 实际上,您不会实现任何只应用于一个层但不适用于其他层的无关接口。

答案 2 :(得分:3)

A DTO = is an object that carries data between processes.

但最有趣的是,它除了存储和检索自己的数据外没有任何行为!!!

坚持使用MVC方法......

Domain = subject of your entire application.

Model = contains the (programming languages objects : EX: C# objects) to make up the universe of your application.

他们可以明显地拥有行为和属性(参见与DTO的不同)。

通常,应用程序(轻量级)可以有一个模型 - 您的模型正是您的域。  另一个模型可以是完全不同的对象类型,即处理另一个模型。在这种情况下,它们都是您域的一部分,并被命名为“域模型 - 对象”。

希望这个答案是详尽无遗的,让你一切都清楚!

答案 3 :(得分:1)

大多数对象的任何定义都是基于对象的使用位置而变化的:

  

Model一般定义,用于在客户端服务器中使用对象。< / p>      

      
  1. Model View:大部分时间都在client使用对象
  2.   
  3. Domain Object:在servertransfering data to the database中使用对象
  4.   
  5. Data Transfer Object(DTO):是将数据从一个对象传输到另一个对象的对象,特别是在API Call中获取数据时(例如:在api GET方法中) 要求获取数据,您不得将数据库模型提供给客户端,为此您使用dto)。
  6.         

    注意:the definitions are true most of the time但在某些情况下并不实际。

答案 4 :(得分:0)

1)不,这是ViewModel的定义。 MVC模型对象和域对象都是相同的 2)域模型(对象)始终存在,业务逻辑是可选的 3)如果域对象中没有业务逻辑,则自动成为DTO。

答案 5 :(得分:0)

我的建议(简而言之)如下:

(MVC)模型对象:

  • 在某些用法上下文中表示某些事物,例如。 PersonEditModelPersonViewModel或仅PersonModel
  • 没有业务逻辑
  • 可以接受某些验证逻辑等。
  • 用于从一个应用程序层向另一应用程序层提供数据。 MVC控制器<-> MVC视图

域对象:

  • 代表一些业务对象(问题域中的现实世界对象)
  • 具有业务逻辑
  • 不允许无效的对象状态,具有正确更改对象状态的方法
  • 用于封装与其相关的业务逻辑
  • 不必用来保存数据(甚至不应该)

DTO(数据传输对象):

  • 类似于Model对象,但应具有扁平结构
  • 仅简单类型的属性/字段(字符串,数字,日期时间,布尔值)
  • 用于跨应用程序边界传输数据,例如在网络服务器和网络浏览器之间

答案 6 :(得分:0)

MVC 和 DDD 可以一起使用。我们在 DDD 和 MVC 中所谓的“模型”实际上是相同的:抽象。使用伪代码,我们可以举例说明。

模型视图控制器 (MVC)

模型视图控制器架构将软件分为三个部分:

模型层

MVC 架构中的模型层是逻辑所在的地方。在这一层,我们有我们的模型和业务逻辑。

class Car {

  String color;
  String year;  

  Cat(color, year) {
    this.color = color;
    this.year = year;
  }

  //getters & setters
}

一个简单的 Car 抽象。

class CarService {

  save(car) {
    if(car.getColor() != null && car.getYear() != null) {
      methodToSave(car);
    } else {
      throwsException();
    }
  }

  find(car) {
    return methodToFind(car);
  }

  update(car) {
    assertThatExists(car);
    methodToSave(car);
  }

  delete(car) {
    assertThatExists(car);
    methodToDelete(car);
  }
}

一个简单的汽车使用服务的 CRUD

视图层

View 层是用户界面所在的地方。用户可以在这里与系统交互,然后触发控制器执行操作,然后通知模型层并请求数据。视图层可以驻留在应用程序的客户端或应用程序的服务器端(即:JSF(Java Server Faces)作为服务器端,ReactJS 作为客户端)。无论如何,即使View层驻留在客户端,客户端也需要向服务器端请求发送请求。这可以通过对基于 Web 的应用程序的 HTTP 请求来完成。

<theCarPage>
  <theCar>
    getTheCarOnLoad();
  </theCar>
</theCarPage>

汽车的伪页面。

控制器层

控制器层基本上接收来自视图的输入,然后将数据转换并发送到模型层,反之亦然。

class CarController {
  
  @OnLoadingTheCarPage
  getTheCarOnLoad() {
     return theCar();
  }

}

加载 Car 的方法。

领域驱动设计 (DDD)

领域驱动设计是一个概念: DDD 的基础是类、类变量和类方法必须与其核心业务领域相匹配。

领域驱动设计存在于“M”中

在这种情况下,当应用 MVC 时,领域驱动设计驻留在 MVC 架构的模型层中。如前所述,模型层是应用程序业务逻辑所在的位置。

无论您是否有实体,它们仍然是模型。模型只是现实世界中某些事物的抽象。如果抽象了,猫可以是模型:

class Cat {
  
  String color;
  String age;  

  Cat(color, age) {
    this.color = color;
    this.age = age;
  }

  //getters & setters
}

简单的 Cat 抽象。这是猫的模型。

DDD 实体

在领域驱动设计中,我们有实体,它们也被归类为模型。它们之间的区别在于实体是可识别的。如果您有一个可识别且可以持久化的类,那么它就是一个实体。实体仍然是模型。

@AnEntity
@ThisCanBePersisted
class Cat {
  
  @ThisIsAnId
  @ThisValueIncrementsAutomatically   
  @PersistentProperty
  Long id;
  @PersistentProperty
  String color;
  @PersistentProperty
  String age;  

  Cat(color, age) {
    this.color = color;
    this.age = age;
  }

  //getters & setters
}

一个简单的实体。实体就是模型。

数据传输对象 (DTO)

数据传输对象内部没有逻辑,它们的唯一用途是作为将数据从一个端点传输到另一个端点的容器。通常企业实体本质上是不可序列化的,所以我们需要一种方法来只发送我们需要发送给客户端的数据。 例如,由于模型可能具有合理的数据或我们不想在获取请求中共享的简单数据,因此考虑到我们的 Cat 模型,我们可以创建一个不共享 Cat ID 的 DTO:

class CatDTO {

  String color;
  String age;  

  //getters & setters
}

Cat 的数据传输对象。我们只需要它的属性和一些东西来获取和设置属性。我们不想分享它的 ID。

因此,例如,如果我们必须使用 REST 从我们的客户端请求所有猫的列表,那么我们将请求使用 CatDTO 而不是 Cat 实体进行响应的端点:

[
  Cat {
    "color": "yellow",
    "age": "1"
  },
  Cat {
    "color": "black",
    "age": "4"
  }
]

这就是我们的客户可以看到的所有数据。