When you work in a microservice or a service-oriented architecture, there is a high chance that you will have more than one tech stack.
We have a lot of APIs that are consumed by our front end platforms and third-party clients. We have ruby, golang and Java.
The question here is, what's the case that you follow for parameters when you design your APIs especially when you have different stacks that differ by their case convention?
So far, when the APIs are designed, we follow the casing that's recommended in the respective languages.
For example, consider this API which creates a new user. (Simplified the API for the sake of discussion)
In golang it would look like this,
POST User(params)
params = { firstName: 'Michael', lastName: 'Scott'}
whereas in ruby,
POST user(params)
params = { first_name: 'Michael', last_name: 'Scott'}
The clients now have to use snake_casing for some APIs and camelCasing for some APIs. We wanted to fix this and follow a consistent casing throughout the organisation so that the API parameter casing is the same irrespective of the underlying language.
What are our possible options?
camelCase, snake_case, spinal-case
Let's say we follow camelCase for all the APIs. Golang and Java apps would continue to work fine. For ruby, camelCase
would be introduced in the code which is against ruby's styling convention for variables. This is because of the following reasons.
- More often the parameters will be passed to downstream services.
- If you're a fan of Service Object pattern, you would keep the controller thin and pass the camelCased parameters to the respective service.
- There will be common utilities or actions that need to work on the params. For instance, verifying if all the parameters are present for an API.
As a result of these, your ruby code will start handling camelCase.
Workaround for this:
To avoid this, there can be a simple middleware that processes all the requests parameters and converts them to snake_case, so that the rest of the code continues to follow snake_case and would never need to know what's the case that's been used by the clients. Even if we want to change the case from camelCase to spinal-case, we only need to handle at the middleware layer and the rest of the code stays the same.
To give you a rough idea, having this line of code before passing on the request to the respective controllers would solve this problem.
params.deep_transform_keys!(&:underscore)
Refer here if you want to read on what's the right way to do this in rails.
Having said these, I know that a lot of you would encounter this problem at work. I would love to know how you're handling this and the thought process behind choosing a particular case and maybe learn if there are any best practices for the same.
Top comments (2)
In our organization. We run numerous big data pipelines, where data is transmitted, stored, and processed using variety of technologies. JSON is the goto format for this and camel casing doesn't work well with a lot of big data query engines (and solutions it to work with camel casing is nasty or way too hacky ), so the natural option is to use snake casing. With that out of the picture, the next problem is that a lot of big data frameworks are JVM based, in those scenarios we use Jackson's Object mapper naming feature to convert it back to internal POJOs where camel casing is followed.
Jackson's feature:
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
Thanks for the detailed information. π
So in your case, to choose the snake case was more of a pragmatic approach. The matter of which case is easier to work with.