【问题标题】:NestJs: Why do we need DTOs and interfaces both in NestJSNestJs:为什么我们在 NestJS 中都需要 DTO 和接口
【发布时间】:2019-05-01 01:43:17
【问题描述】:

NestJS 文档展示了如何添加 DTO 以在控制器中使用,以通过使用 class-validator 包来验证请求对象。描述的 DTO 有 TypeScript 类。现在,虽然控制器处理 DTO(TS 类),但 NestJS 提供者(或服务)另一方面,使用 TypeScript 接口。这些 DTO 和接口的形状几乎相同。

现在,我在这里看到了重复的形状定义。并且想知道是否需要这些接口?

我们不能让 DTO 成为形状和验证的真实来源吗?我们正在考虑的一种方法(使 DTO 成为事实来源)是,让一个 openapi 生成器将 DTO 作为输入并生成 openapi 定义,然后另一个 codegen 可以从那里生成一组 typescript 接口供 NestJS 本身使用并且可以与另一组消费者应用程序(如 Angular)共享。

有没有人遇到过类似的问题?你怎么看上面的?感谢您的反馈。

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    我认为了解DTO 是什么很重要。

    DTO(Data Transfer Object)Java(J2EE)设计的概念。

    它看起来像一个普通的Java Bean 对象,它是为在我们的后端,尤其是在Distributed Systems 中通过多个层(例如controllerservicedatabase)传输数据对象而创建的。

    没有DTO 模型

    我们发送大量请求来查询我们想要的一些数据,这些数据可能会重复。

    Application -> WebService -> Database

    1. 由于一些重复的请求,它消耗了大量的带宽。
    2. 不安全,它从database返回整个对象,其中包含一些不应暴露的属性。顺便说一句,我们应该手动添加一些额外的代码来限制它,这很糟糕。

    DTO 模型

    它帮助我们处理我们的数据对象。


    NestJS 的引导下,DTO 就像HTTP Request 的主体。

    在我看来,DTO 包含:

    • 我们将使用但不在Database 中的一些属性。

    DTO 掩码:

    • 我们不想公开的一些属性。

    class-validator 一起使用,DTO 还可以帮助我们以优雅的方式验证数据。

    有时它看起来与对象 interface 相同。

    我认为DTO 在我们的数据库集合庞大而复杂时很重要。

    【讨论】:

    • 这是一些很好的信息,但它真的回答了 OP 的问题吗?也许可以添加更多细节来说明为什么同时拥有 DTO 和接口很重要(OP 问题的本质)。
    【解决方案2】:

    我不是专家,但我根本没有使用 DTO。我真的看不出它们有什么用。在每个模块中,我都有一个服务、模块、实体和控制器。

    【讨论】:

    • 为什么在这里投反对票?这篇文章通过指出额外的复杂性对于较小的项目可能没有意义,为讨论增加了一些平衡。
    • 我意识到这已经超过 2 年了,但是 DTO 可以避免暴露客户不应该收到但在服务级别仍然有用/需要的实体/模型的字段。我当然可以设想不需要这样做的情况,但是对于编写企业 API,它可能是一种有用的模式。
    • @mikey 我的 Angular 客户端暴露了我的服务器端 entity.ts 中的几乎所有字段,所以我看不出 DTO 是如何阻止这种情况的。为了安全起见,无论如何我都必须将服务器锁定得很紧。也许与其他前端一起使用 DTO 会很有用,但我想不出哪些。甚至带有 .Net 或 Python 的模板也会向那些愿意破解代码的人显示这些字段。至少这是我的理解。浏览器读取的所有内容都可以通过简单的黑客来读取。你知道例外吗?
    • 如果我误解了道歉。但是考虑一个提供原始数据并且不需要自己的前端的企业 API。我们不想将某些值暴露给消费者,而客户端唯一的可见性是输入和输出的 API 契约。这就是我正在谈论的用例。在那种情况下,实体可以包含我们的私有字段,而 dto 会忽略它们,因此客户端永远不会看到这些字段。
    • 谢谢。我没有想到这一点,它可能永远不会与我的工作相关。很高兴在这篇文章中说明这一点!
    【解决方案3】:

    根据the Nestjs docs

    但首先(如果您使用 TypeScript),我们需要确定 DTO(数据传输 对象)模式。 DTO 是一个定义数据将如何存储的对象 通过网络发送。我们可以通过使用来确定 DTO 模式 TypeScript 接口,或者通过简单的类。有趣的是,我们 推荐在这里使用类。为什么?类是 JavaScript 的一部分 ES6 标准,因此它们在 编译好的 JavaScript。另一方面,由于 TypeScript 接口 在转译过程中被删除,Nest 不能在 运行。这很重要,因为管道等功能启用 当他们可以访问 运行时变量。

    【讨论】:

    • 这是从文档中复制和粘贴的。请使用引号功能或说您复制并粘贴它。
    • 另外请提供原文链接。
    【解决方案4】:

    为了扩展@Victor 对DTO 概念及其作用的回答,我想指出interfaces 允许我们设置一个代表我们应用程序中有意义的东西的合同。然后,我们也可以在需要的其他地方实施和/或扩展此合同,例如。数据库对象的实体定义 - DAOs、数据传输对象 - DTOs 和业务模型定义

    此外,DTOs 的 interfaces 可以在后端和前端之间共享,这样两个项目就可以避免代码重复和交换对象之间的差异,从而便于开发和维护。

    【讨论】:

      【解决方案5】:

      我想用最简单的例子来解释DTO 的概念,以便您更好地理解。 DTO 代表数据传输对象。现在 DTO 用于减少代码重复。它只是定义了一个模式,该模式在函数的参数中传递,以便从它们中获取所需的数据。这是DTO的示例

      export class AuthCredentialsDto {
          email: string;
          password: string;
      }
      

      现在如果我们做一个方法来检查密码是否正确

      async password_check(usercredentials: AuthCredentialsDTO)
      {
          //Destructuring in JAVASCRIPT
          const {email} = usercredentials;
          //Database Logic to find the email
          return user;
      }
      

      现在如果我们不使用 DTO,那么代码看起来会像这样

      async password_check(email: string, password: string)
          {
              //Database Logic to find the email
              return user;
          }
      

      还有一点是,这只是一个函数,在一个框架中,多个函数调用多个其他函数,需要一次又一次地传递参数。只需考虑一个函数需要 10 个参数。您将不得不多次通过它们。虽然没有DTO 也可以工作,但这不是一种对开发友好的做法。一旦你习惯了DTO,你就会喜欢使用它们,因为它们可以节省大量额外的代码和精力。 问候

      【讨论】:

        【解决方案6】:

        顺便说一句,即使 DTO 是 Java 约定,它也无法解决通用字段的问题,例如:

        @Get(url/${variable})
        @Reponse({
           [$variable: string]: $value
        })
        

        TS Interfaces 只能解决这个问题,但你不能在 DTO 中描述它 为了展示它,您将传递一些硬编码的示例

        class ResponseDto {
          @ApiProperty({
            ...
            example: [...]
          })
          [$variable]: SomeTSInterface[]
        }
        
        @Reponse({ status: 200, type: ResponseDto })
        

        【讨论】:

          【解决方案7】:

          dto 提供的不仅仅是接口。使用 dto 和类验证器,您可以在请求级别快速进行验证。但是当涉及到接口时,你不能向它添加类验证器。 dtos 是一般的类。这意味着您需要做的不仅仅是界面。

          【讨论】:

            【解决方案8】:

            我不是专家,但我不明白我们为什么使用 Dto 当我们可以使用模式模型时——Dto 和其他对象需要什么

            【讨论】:

            猜你喜欢
            • 2020-11-24
            • 2020-12-08
            • 2021-11-09
            • 1970-01-01
            • 1970-01-01
            • 2021-09-28
            • 2020-07-23
            • 2011-04-01
            • 2022-11-15
            相关资源
            最近更新 更多