YASE - Yet Another Software Engineer
To figure out which endpoints you need, there are a few different approaches you can take:
In the first scenario, you’d have an ER model where the entities roughly correspond to the tables in your database. These tables then become the entities for your REST APIs.
You could model the database, or just the entities you want to expose, using a UML class diagram:
This image clearly shows how entities are mapped (almost one-to-one) to objects in the UML diagram. These objects then serve as the inputs/outputs for the functions, or routes, of your REST endpoints.
In this specific case, some common UML stereotypes for REST API engineering are used:
code
: likely a numeric code (like an HTTP status code or an application-specific error code) indicating the operation’s outcome.type
: a string that could categorize the response type (e.g., “success”, “error”, “validation”).message
: a human-readable string providing details about the operation’s outcome or any errors. # <<Application>> SomeAPI
-----------------------------------------------------------------
code: int # HTTP return code
type: str
message: str
items: dict # iterable with all data
...
Even the envelope itself requires coding a specific object, which, however, doesn’t belong to the database entities but is exclusive to the application, particularly the APIs.
user/balance
. # <<Resource>> Order
+ GET(order_id: int): Order
- POST(order_id: int, order_name: str, amount: float): Order
This is an example of a possible implementation for the Order resource:
The «Resource» blocks can be extended by adding attributes to specify properties calculated internally by the function handling that endpoint, which aren’t part of the object returned by the route itself. In other words, these attributes are additional metadata surrounding the data returned by the route, fields of the envelope itself, similar to what was done with the «Application» block:
# <<Resource>> Order
----------------------------------------------------------------------------------
n_orders: int # total orders
----------------------------------------------------------------------------------
+ GET(order_id: int): Order
+ GET(): List[Order]
- POST(order_id: int, order_name: str, amount: float): Order
Resource attributes, being calculated by the route-handling function rather than taken directly from the database, generally don’t have a state; they aren’t saved or tracked. They are just data pre-calculated by the server for convenience and are useful on the client side. They act as on-the-spot “statistics” for the just-returned data; saving them would be redundant in the database.
Next, let’s look at how to structure the names of APIs and resources, and what naming conventions to follow.