【翻译】在 Javascript 中使用 DTO

原文: dev.to/tareksalem/...

引言

在我们讨论实际实现之前,让我们先介绍一下DTO,它的含义是什么,何时使用以及 javascript/nodejs 项目中对它的真正需求。

什么是DTO

DTO 英文是 data transfer object 的缩写,意思为"数据传输对象",它是指定义了一个包含一组值或字段的容器,而不是解释如何在层之间传递数据的方法。有些人混淆了定义数据库模型(Modal)和DTO,记住这句话:

DTO 是用来操作和数据传输的,而模型则是用于数据持久性的。

什么时候使用DTO?

很多开发人员在用 typescript/nodejs 开发复杂的应用程序时,都会使用 DTO 来表示他们的数据以及数据是如何传输到应用程序的各个层的。这实际上是正确的,也是必需的。

但我今天来告诉你,这也是javascript/nodejs 开发中所必需的,这样做可以防止你的代码变得糟糕!!

为什么要在 Javascript 中使用 DTO?

想象一下,你用 javascript 开发动态页面,并使用 nodejs 开发rest API,你开始创建模型,做数据验证,例如使用"express-validator",并定义了你的路由、中间件,一起工作正常。

随着需求的变化和代码的频繁更新,会有多个服务和多个 API 以不同的方式使用同一个模型,并且在每个服务中复制一些字段,以将它们从控制器(Controller)层传递到服务(Service)层,然后传递到负责将数据持久化到数据库中的层。当一段时间后再看代码,如果已经看不明白什么数据应该传递给服务层,什么数据应该从这个服务返回,那么你就需要 DTO 了。

再想象一下,如果你在没有严格的 schema 的情况下,连接到一个作为持久性数据库或文档数据库的firebase,并且你将 json 数据作为端点,使用"express-validator"进行一些验证,并将这些数据传递到服务层,然后这个服务层将这些数据传输到持久性层,你需要的字段如下所示:

json 复制代码
{
    username: String,
    email: String,
    password: String
}

你如何保证 API 消费者可以发送更多的字段而不是定义的字段?例如,API 的消费者可以发送以下数据:

json 复制代码
{
  "username": "test",
  "email": "test@gmail.com",
  "password": "specificPass",
  "birthDate": "2022-05-09T20:12:13.318Z"
}

你看,我可以发送验证中未定义的字段birthDate,这将违反服务的约定,这些数据也会被传递到持久层,并将保存在数据库中。

同样,假设有一个使用相同服务层的 API 和 web socket 连接,要如何定义两者的验证?你最终可能会在两者中重复定义公开的数据!

在所有这些情况下,您都需要DTO。其背后的想法很简单,它使你能够描述如何在层中接收数据和公开数据。

实施和示例

最初,我们将 express js 路由定义如下:

arduino 复制代码
router.post("/user/register", validations, registerController);

我们将使用express验证器进行如下验证:

vbscript 复制代码
const validations = [
  body("username").exists().isString().notEmpty(),
  body("email").exists().isEmail(),
  body("password").exists().isString().notEmpty(),
]

然后,控制器/处理程序如下所示:

ini 复制代码
const registerController = (req, res) => {
  const result = await userService.registerUser(req.body);
  return res.status(200).json(result);
}

简单服务层如下所示:

ini 复制代码
const registerUser = (userData) => {
  userPersistenceLayer.add(userData);
}

现在,让我们定义我们的基本DTO,但在此之前,让我确保两个事实:

  • DTO用于数据传输,数据库模型用于数据持久性。
  • 将DTO视为一种约定,您可以使用此约定规范与其他人进行处理。约定规范是其中定义的字段
kotlin 复制代码
class RegisterUserDTO{
  username;
  email;
  password;
​
  constructor(data) {
    this.username = data.username;
    this.email = data.email;
    this.password = data.password;
  }
}

然后我们可以回到服务层并使用我们定义的DTO:

csharp 复制代码
const registerUser = (userData) => {
  userPersistenceLayer.add(new RegisterUserDTO(userData));
}

正如您在这个模式中看到的那样,我们正在控制传递数据的方式,并确保哪些字段被传递到其他层,我们还可以在这个DTO中设置一些getter和setter,以根据需要序列化/转换一些数据。

希望你能清楚、顺利地了解DTO模式。

相关推荐
mldong11 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60611 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角2 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi4 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒6 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端