Designing a good API is much like designing a light switch. You don’t want to design a switch that turns ON the T.V instead of switching off the light!
I will be using the acronym
API to refer to any programmable interface for any piece of software, be it a
button, a Web Service, a React component, a
class or anything that has an interface for other people to write their programs depending on it.
If you tried to write an API for any piece of software for other developers to use you must have asked your self a lot of questions.
What is the best way to build it? Will the user be surprised if I returned
null instead of
Or maybe not. maybe you didn’t think about it until you tried to use someone’s API and it got you thinking “Seriously, What made them build the API this way?”
When I first started writing APIs I made a lot of crazy mistakes. I expected people to understand what I meant. I wrote functions that performed more jobs than what they should be doing.
Sometimes I started writing the API too early before it’s requirements are clear. other times I waited for perfect requirements that take forever to gather.
Fast forward, I kept learning in small steps on how to build an API. One that your colleagues do not need you beside them to explain how it works.
def active_vehicles(organization): # return active vehicles
Is better than
def get_vehicles(org): # calculate 3 + 7 # play soduko # return active vehicles
Good API characteristics:
To call it a good API it should be designed to be
- Easy to learn.
- Easy to use, even without documentation.
- Hard to misuse.
- Easy to maintain the code using it.
- Powerful enough to satisfy requirements.
- As small as possible but not smaller. (It allows for better testability)
The idea of making programs small enough but not smaller is an old great concept mentioned in the UNIX philosophy.
It means that a function (or an API) should do a specific task best described by its name, for example, an API named
activate_account should not be sending a request to google maps asking for the distance between two coordinates after activating the account. It should only activate the account.
But, How can I proceed into building a good API?
3 steps for Designing a good API
Gather requirements with a healthy degree of skepticism.
Be sure that sooner than you think, any amount of gathered requirements will be updated and changed. But you still need requirements before writing any code!
Start with a short description.
When I started trying the requirements gathering game, I want to do all the cool charts of the software engineering book before writing any code. but this will only waste enough time before those requirements are outdated.
Start with a 1-page specification description. It should be enough to get you to know your initial direction.
Write your API early and keep iterating
Similar to the previous point. You don’t want a gigantic specification to implement then after the implementation you find out it’s not the case anymore. Tough luck baby! Natural Selection!
Start before you even have a proper specification.
I can’t remember how many times I wrote unnecessary code to come back a few months later to delete it and write “code cleanup” in my git commit message.
Do not try to catch exceptions that are not going to happen. Adding two numbers cannot cause ConnectionError!
Have a Platform-first mentality: if you’re not thinking of the bigger picture and building small features instead, you’re most likely going to refactor those features when the requirements start shifting more toward being a platform. To change this you have to think of software engineering as a way of delivering solutions to problems instead of features.
Don’t violate the principle of least astonishment (The user should not be surprised by the result of the API call) Surprises can mean bad naming convention or side effects. If it returns a list, it shall never return a dictionary instead sometimes!
Names matter a lot!! Names should be largely self-explanatory and consistent, the same name should always mean the same thing. (Please don’t go half the system using “remove” and the other half using “delete” in naming functions that are basically going to delete something.
def recently_activated(): # is way better than def get_last_week_activated():
Because sooner or later, the assumption for the “last week” will not be the case for recently activated.
I still have a few points about designing a good API such as the impact of implementation on the API, I will write about it in a separate post.
For now, let me know if you found this useful and surely, don’t forget to share the useful stuff xD!