REST和数据库的对象命名约定

问题描述

在使用Java的REST API构建CRUD应用程序时,我一直在不断创新,我正在寻找某种适用的标准。

让我们以示例的方式进行。假设我有一个用户”表和这些REST端点:

GET  /users/{user_id} // returns a user
POST /users           // creates a user
PUT  /users/{user_id} // updates a user

在每种方法中,我必须选择,插入或更新数据库中的用户

对于这六个操作中的每个操作(REST操作3个,数据库操作3个),我需要通过REST传入或发送到数据库的“用户” POJO的不同属性集。

例如,在REST端,创建用户时,我不需要user_id(因为它是由数据库创建的),但是我确实需要密码获取用户时,我确实需要user_id,但我永远不想将密码返回给客户端。更新用户时,我可能要忽略一些字段,因为它们是只读的(例如用户名或创建日期)。

数据库方面,我可能需要不同的字段,这些字段不会在REST API中传递回去,例如“ is_approved”或“ some_secret”。而且我经常需要创建派生字段,例如“ password_hash”。

因此,正如我所说,同一件事的六个不同表示形式。在Java中,我通过制作六个不同的POJO类来做到这一点。并不总是需要那么多独特的类,但有时却需要。

在REST API中,我不想对所有端点使用相同的类,而只是忽略某些字段,因为该类已传递给我们的api文档工具并且其属性已发布。

这六个类是否有标准的命名约定?

过去,对于REST,我曾使用过createuser,GetUser和UpdateUser。我不喜欢这些名称,因为它们是动词,应该是名词。

UserForCreation和UserForUpdate很尴尬。 NewUser和ModifiedUser可能不错,但是我不知道如何调用GET用户

数据库端,我还需要另外一套完整的名称

对于这种事情,肯定有一个标准或约定。有人知道这是什么吗?

解决方法

我认为您通常对每个请求和响应都具有特定对象的想法是正确的;但是,根据API的设计,您实际上只需要一个User类。您可以使用构建器来抽象出创建逻辑(例如生成用户ID),并将请求对象传递到位于REST端和数据库之间的DAO中。 DAO将仅接受请求,检索用户数据,构建并返回User对象。

一旦创建了用户对象,便可以将其用于创建响应对象,该对象将被序列化并放入响应数据中。最好编写两个用户类(类似UserInternalUser),以便更明确地向客户端公开哪些数据,尤其是在写入客户端的情况下。与API相同的库。您无法实现额外的InternalUser并无法在响应对象构建器,工厂或构造器中处理字段过滤;但是,如果客户端是在同一库中编写的,则可能会泄漏敏感或必要的信息。

您可能希望查看Swagger个文件。该标准提供了一个很好的REST Api规范,该规范非常简单,并提供了一种模板化API结构的好方法,即使它们经常看起来像json或xml的墙一样。

tl;博士 (根据@Turing85

的建议
  • CreateUser [请求|响应]
  • GetUser [请求|响应]
  • UpdateUser [请求|响应]
  • 用户
  • InternalUser
,

此方法受到HexagonalArchitecture / Clean Architecture / Ports and Adapters的借鉴/启发。由于我们已经将DTO和业务对象完全分开,因此我们非常接近上述架构。在“干净架构”中,鲍伯叔叔谈到了“用例”。每个用例都有一些输入和一些输出。我们可以将输入想象成对用例的 request ,将输出看作对给定请求的 response 。因此,对于业务实体User以及creategetupdate等的用例,...其中一个这样的实体,我建议使用以下命名模式:

<use-case><Business-entity>[Request|Response]

对于给定的示例,这意味着我们将创建类

  • CreateUserRequestCreateUserResponse
  • GetUserRequestGetUserResponse
  • UpdateUserRequestUpdateUserResponse

更重要的是:对于CreateUpdate之类的复杂操作,我们可以提取公共字段并将它们放在超类中(如果只有Java具有多重继承性,我们可以使用mixins ... ),只留下实际的用例请求数据来定义我们真正需要的数据。在许多情况下,响应是相同的,因此有意义的是使用通用的UserResponse类而不是许多不同的响应。这提供了一致的API响应的额外好处,例如如果要返回用户列表,则可以返回List<UserResponse>(可能还有一些分页信息)。