The awesome API design rules for Logistic Engineer
Tags: architecture, api
Published: 2021-05-22 17:43:45

When you create API design, what design policies do you have in mind?

There is no absolute correct answer to this.

I think there is a lot of points that give your a headache, such as, how to design a system that is easy to understand, to implement, and without technical liabilities.

I also got a headache deciding what policy to adapt in API design for this project.

I'm proud to say that I created a great API design policy and all of my hard work was worth it.

When I told about it to a friend of mine who live in Spain, she was very interested in it.

For this reason, I decided to put together a structure of the API design policy.

I would like to thank R, an engineer living in Spain, for her help in writing this article.

I'm not good at writing English.
She give me great advice and collections that helps me a lot.

I would like to take this opportunity to once again thank R.

While the title of this article is "The awesome API design rules for Logistic Engineer", 
it is not specific to logistic but it can be perfectly suitable for all web development.
(I'm backend engineer. but when I introduce myself, I call myself a "logistic engineer." it's easier to leave a lasting impression.)

In addition, this is not API definition documentation, but API design policy.

## About API rules
The API design rules I came up with are as follows.

You might be surprised by some of the rules.

But, there are explicit reason.

I will explain them later.

We have adapted Laravel in this project.

That's why, some of the rules are influenced by Laravel and PHP.

For those rules, you might need to redefine some of them so, I will explain later.

_______________________________
# API rules

## URL Naming standards
Camel case is used.

### ex)
```
/webApi/comboItem
```

## URL design standards
URL design standards are as follows.

Controller name is singular. It's following [Laravel best practice](https://github.com/alexeymezenin/laravel-best-practices#follow-laravel-naming-conventions).

This table is based on Laravel official document about "[Actions Handled By Resource Controller](https://laravel.com/docs/8.x/controllers#actions-handled-by-resource-controller)".

cf) In this document, action name of delete is "destroy". But I personally prefer "delete". So, you can use whichever you like.

|  function           |  HTTP method  |  URL                    |  Method name in controller layer    |
|:--------------------|:--------------|:------------------------|:------------------------------------|
|  show list          |  GET          |  /(controller)/index    |  index                              |
|  show 1 record      |  GET          |  /(controller)/show     |  show                               |
|  create new record  |  POST         |  /(controller)/store    |  store                              |
|  update 1 record    |  PUT          |  /(controller)/update   |  update                             |
|  delete 1 record    |  DELETE       |  /(controller)/delete   |  delete                             |


## basic concepts
#### URL rule
```
(object)/(operation in verb)
```
last path of URL should be a verb.  
Also, the verb should match the method name of the controller layer unless there is a specific reason not to follow the rules.  


#### rule of operation name
Don't omit operation name.
By doing so, URL hierarchy is unified.

You might often see the URL structure such as "product/{id}".
In this structure the operation name "reference" is a unspoken agreement.
Therefore, I have avoided to use such unspoken agreement, and tried to always clearly state operation names.
In addition, I have decided not to use any part of URL as GET parameters.


#### Additional rules
In the case that you want to get only child contents, when you handle parent-child relationship data.
describe target model name after controller.

When you want to view the list of children in parent function view, please state the model name below the controller name.

please use  "_"(under bar) for concatenation which is expected to have the hierarchy below the controller.

This is an exception to the coding standard that specifies to use camel case for method names.

##### ex) parent:comboItem, child:item

|  function       |  HTTP method  |  URL                    |  Method name in controller layer  |
|:----------------|:--------------|:------------------------|:----------------------------------|
|  show list      |  GET          |  /comboItem/item/index  |  item_index                       |
|  show 1 record  |  GET          |  /comboItem/item/show   |  item_show                        |


### routing example (Laravel 8)
```php
Route::get('comboItem/index', [\App\Http\Controllers\Api\ComboItemController::class, 'index']);
Route::get('comboItem/show' , [\App\Http\Controllers\Api\ComboItemController::class, 'show']);

Route::get('comboItem/item/index', [\App\Http\Controllers\Api\ComboItemController::class, 'item_index']);
Route::get('comboItem/item/show' , [\App\Http\Controllers\Api\ComboItemController::class, 'item_show']);
```

_______________________________

What do you think?
Some of the rules may seem odd to you.

I will explain the reason behind the definition of these rules.


### Use verb in URL last path
Let's start with this.
```
(object)/(operation in verb)
```

last path of URL should be a verb.

Also, the path just before the verb represents object of operation target.

This makes it possible to figure out what to do with target object only by looking at the URL.


## Don't let specify only HTTP method
In addition, HTTP methods are not used to control API actions.

For example, sometime you might see something like this in the API document.

![the-awesome-api-design-rules-for-logistic-engineer-01](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xecr47rtv0hqat4osh0z.png)
 
Adapting this rule, this is the result.

![the-awesome-api-design-rules-for-logistic-engineer-02](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6vw9jm4xidjl2ogzjc4.png)

You can figure out actions only from HTTP methods. So, you might think that including the name of actions is not required.

But, there is a wide range of actions you want to achieve with the API. On the other hand there are far too few methods in HTTP.

In the example above, There are only few actions such as select, update and delete.
However, a practical API will be required much more sophisticated operations.

For example, if you want to "extract items in a specific status" or "get number of item by categories", it is impossible to express these actions only with HTTP methods.

For this reason, A verb is necessary in URL to express.

So what happen as a result?

Two pattern exits:
 - No verb in URL because the action is predictable from HTTP methods.
 - The actions are unpredictable only from HTTP methods, so verbs are required in URL.

As I defined the rules API design, I wanted to standardize them.

It's not only matter of perspective for entire API design.

The purpose is to make developers easy to decide,
whether the function's behavior is specified by HTTP methods or writing operation in the URL.


Therefor, I defined to make action explicit even if the behavior is predictable from HTTP methods.

For this reason, I would like to suggest these rules.


|  function           |  HTTP method  |  URL                    |  Method name in controller layer    |
|:--------------------|:--------------|:------------------------|:------------------------------------|
|  show list          |  GET          |  /(controller)/index    |  index                              |
|  show 1 record      |  GET          |  /(controller)/show     |  show                               |
|  create new record  |  POST         |  /(controller)/store    |  store                              |
|  update 1 record    |  PUT          |  /(controller)/update   |  update                             |
|  delete 1 record    |  DELETE       |  /(controller)/delete   |  delete                             |


You might feel odd about delete operation, because HTTP method and action name are same.

However, It has a advantage of standardizing URL hierarchy.

Also, you can understand these behaviors only by URL without reading the API document.


## Match the last path in URL with the method in controller layer
This is not the only reason for making the rules that specifies the operation name.

The specified URLs will often be processed in controller layer.

Many methods are defined in controller layer, but sometimes it is not intuitive to link to API's endpoint.

The rules "specify the operation name at the end" makes it possible to "match the last path in URL with the method in controller layer"

For example, this API will be able to be related with this method.

```
/item/show
/item/store
```
```php
class ItemController extends Controller
{
    public function show(ShowRequest $request)
    {
        // your coding here
    }

    public function store(StoreRequest $request)
    {
        // your coding here
    }
```

How about this?

It is possible to link to method name in controller layer by simply looking at API's endpoint. so that it can improve  the readability of the source code.

Not only that, it helps developes to name method in controller layer without thinking too much.

But, there is room for further consideration about action names in URL.

In this project, we have adapted laravel, which is a PHP framework, and used a camel case for the PHP method names in accordance with coding standards.

The rule was defined to match rule of backend language.

But, it is important to consider whether the rule is suitable.

Because, The naming rule shouldn't be dependent on backend languages.

For example, what if Go lang is adapted in the project.

If you replace the backend language with Go Lang, the API design rule will have unnatural part.

Because, it usually use upper case for method name.

So, for the URL, it is also possible to separate by hyphen instead of uppercase

But, when it comes to concatenating multiple words, there is a lot of variation, and no standard rule.

This list of example is according to the book "Web API The Good Parts", which I have.


|  Servece   |  Rule        |  Example                               |
|:-----------|:-------------|:---------------------------------------|
|  Twitter   |  snake case  |  /statuses/user_timeline               |
|  YouTube   |  camel case  |  /guideCategories                      |
|  LinkedIn  |  dot case    |  /me/books.quotes                      |
|  Bit.ly    |  chain case  |  /v1/people-search                     |
|  Disques   |  camel case  |  /api/3.0/applications/listUsage.json  |


None of them is conclusive. But, many people prefer using hyphen to concatenate.

The reason for this, some people believe Google recommend using hyphen to concatenate and it is more beneficial to SEO.

According to this book, Google search engine consider hyphen is word break, but under bar isn't.

But I haven't found any officinal statement from Google as of May 2021.

Nonetheless, concatenation with hyphen is quite popular, unless you have a particular reason, it is good idea to adapt the rule.
(Obviously as I mentioned at the beginning, it is OK to match backend language rule if the language is highly unlikely to replace.)


### Don't use part of URL as GET parameter

I would like to explain why any part of URL shouldn't be used as GET parameters.

Assume that the URL structure looks like this:

![the-awesome-api-design-rules-for-logistic-engineer-03](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hkv0ac4b9fm84770o5rx.png)

Everything seems to be fine.

But, what if there are multiple values to pass in the GET parameter.

To run API, it often requires several parameters.

In such case, some parameters are passed as part of URL, and others are passed with "?" and "&"

I think this structure is too confusing.

Because, architects have to consider which parameters should be given by URL or "?" and "&".

Also, developers have to know "what the parameter is in URL"

The rule "Don't use part of URL as GET parameter" allows team to share where GET parameters are as a common knowledge.

_______________________________

## summary
What do you think about it?

You might be surprised by some of the rules, and it might be difficult to take in.

But, this rules was accepted in actual project by team member. And it went well.

There is no absolute correct answer for API design.

I hope you will find my idea to be helpful.