Number 11
June 28, 2023

A trick for your APIs

One day, I was trying to use someone’s RPC service and wasn’t having a great time with it. For nearly every use case, I needed to call several functions with many arguments, some of which were required but unused, while others had different meanings depending on what I intended to do.

The service lacked consistency in error handling: some functions would throw an exception, while others would return an object containing an “error” field. A client library was available, but it used global variables, so sometimes I needed to save and restore a variable before and after a call.

In other words: it was a disaster.

Two men operating a very strange bicycle.

RPC services, just like code libraries, have an interface. It’s not a user interface where someone can interact with a program using a window, a terminal, or a browser: it is a programming interface where a programmer calls functions to use the service. This interface is called an “API.”

It’s hard work to design a good API. It’s undoubtedly more unforgiving than programming the service that exposes that API: it doesn’t matter whether the code is good or bad, whether it’s written in Rust or Python, whether it uses O(log n) or O(2ⁿ) algorithms, or whether there is no actual program but three elderly pensioners living in a cottage in Yorkshire who get the RPC requests by fax and send the responses by letter; as long as the service works, it’s good.

However, the API itself doesn’t have an invisible implementation: what you see is what you get; if it’s designed wrong, the user will suffer.

Therefore, if you don’t have experience designing APIs and must write a service, library, or something else that exposes one, you will probably come up with a pretty bad API. Consider the sheer amount of projects on GitHub where version 1 had such a terrible API that version 2 has a radically different one.

Unfortunately, API design is another one of those things nobody teaches us so, for now, the only way to learn how to design APIs is… well, it’s to go ahead and design APIs. What a bummer.

If you are lucky, you can work with someone with experience who can review your design. If you don’t know anyone, there is an alternative: write one or two programs that use the API. Doing this will give you some first-hand experience with it, and you’ll be able to note which parts are good and bad, what is hard or easy to do, etc.

If you can’t think of a program you can write using your API, the solution is simple: write unit tests! Since unit tests are meant to test your service, using the whole API shouldn’t be too difficult.

It is a very effective method to test APIs: when I do it, I often notice that my test code becomes tough to write or understand, so I make changes in the API, and suddenly, my tests become shorter and more straightforward.

Don’t think you will be free of this problem if you never write RPC services or code libraries: not all APIs are external. The functions and classes that make up your program constitute an internal API, which requires you to ensure a good design; otherwise, your program’s code will be unnecessarily long and hard to understand.

The illustration for this Coding Sheet comes from “Cycling Art, Energy, and Locomotion.”