ccleve
ccleve

Reputation: 15809

Object naming conventions for both REST and database

I keep reinventing the wheel when it comes to building a CRUD app with a REST API in Java, and I'm looking for some kind of standard to apply.

Let's do this by example. Let's say I have a table of "users" and these REST endpoints:

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

Within each method, I have to select, insert, or update the user in a database.

For each of the six operations (3 for REST, 3 for the database), I need a different set of properties for the "user" POJO that comes in over REST or gets sent to the database.

For example, on the REST side, when creating a user, I don't want a user_id (because that gets created by the database), but I do want a password. When getting a user, I do want user_id, but I never want to return a password back to the client. When updating a user, I may want omit some fields because they are read-only (like username or creation date).

On the database side, I may need different fields that don't get passed back in the REST API, like "is_approved" or "some_secret". And I often need to create derived fields, like "password_hash".

So, as I say, six different representations of the same thing. In Java, I do it by making six different POJO classes. It doesn't always take that many unique classes, but sometimes it does.

In the REST API, I do not want to use the same class for all endpoints and just ignore some fields, because this class gets passed to our API documentation tool and its properties get published.

Are there any standard naming conventions for these six classes?

For REST, in the past, I've used CreateUser, GetUser, and UpdateUser. I don't like these names because they're verbs and they should be nouns.

UserForCreation and UserForUpdate are awkward. NewUser and ModifiedUser might be good, but I don't know what to call a user for a GET.

And I need another whole set of names for the database side.

Surely there is a standard or a convention for this kind of thing. Anyone know what it is?

Upvotes: 4

Views: 6843

Answers (2)

Turing85
Turing85

Reputation: 20205

This approach is borrowed/inspired by HexagonalArchitecture/Clean Architecture/Ports and Adapters. Since we already have a clean separation of DTOs and business objects, we are quite close to the aforementioned architectures. In Clean Architecture, Uncle Bob speaks about "use cases". Each use-case has some input and some output. We can imagine the input as a request given to the use-case and the output as a response to the given request. Thus, for a business entity User and use-cases to create, get, update, ... one of such entities, I would suggest the following naming pattern:

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

For the given example, this would mean we create classes

  • CreateUserRequest, CreateUserResponse
  • GetUserRequest, GetUserResponse
  • UpdateUserRequest, UpdateUserResponse

What's more: for complex operations like Create and Update, we can extract the common fields and place them in a superclass (if only Java had multi-inheritance, we could use mixins...), leaving the actual use-case requests with only the data to define we really need. In many cases, the respsonse is identical, thus it can make sense to have a common UserResponse-class instead of many different responses. This gives the added benefit of consistent API responses, e.g. if one wants to return a list of users, one can return a List<UserResponse> (plus, maybe, some pagination information).

Upvotes: 6

joshmeranda
joshmeranda

Reputation: 3261

I think you generally have the right idea having specific objects for each request and response; however, depending on the design of the API, you only really need the one User class. You can use builders to abstract out the creation logic (such as generating user ids), and pass the request objects into a DAO that sits between the REST side and the database. The DAO will simply take the request, retrieve the user data, build and return the User object.

Once the user object is created it can be used to create response objects, which will be serialized and put into the response data. It might be a good idea here to write two user classes (something like User and InternalUser) to make it more explicit about what data will be exposed to the client, especially if the client is being written in the same library as the API. You could not implement the extra InternalUser and handle the field filtering in the response object builders, factories, or constructors; however, if the client is being written in the same library, you risk leaking sensitive or necessary information.

You might want to look at Swagger files. The standard provides a nice REST Api specification that are pretty simple and provide a good way to template out the APIs structure, even if they often end up lookung like walls of json or xml.

tl;dr (as per suggestion of @Turing85

  • CreateUser[Request|Response]
  • GetUser[Request|Response]
  • UpdateUser[Request|Response]
  • User
  • InternalUser

Upvotes: 2

Related Questions