We’ve all been there: A co-worker or blog article suggests we checkout a certain module or package. A few seconds of searching Google turns up the project’s homepage. But then you start to read the docs and your eyes glaze over.
Let’s take the urllib module from Python’s standard library as an example. Presumably, you’d want to use this to grab some information from a URL. Maybe you’re interacting with a RESTful web service or want to do some web scraping.
Reading through the docs, it’s not immediately obvious what the main classes actually do:
urllib.urlopen(url[, data[, proxies]])
Open a network object denoted by a URL for reading.
urllib.urlretrieve(url[, filename[, reporthook[, data]]])
Copy a network object denoted by a URL to a local file, if necessary.
What exactly is a network object? It’s not really obvious as to where you should get started. Reading through the “Utility Functions” section, you see a few things that look promising, but then the URL Opener section has you scratching your head again.
You waste hours scrolling through docs and reading forums, hoping you’ll eventually understand. But you feel disheartened. It shouldn’t be this hard, right? You start to feel frustrated and adrift. You start questioning, “Why can’t I figure this out?” You get so far into the weeds that you start to forget what problem you’re trying to solve in the first place.
Your tools got in the way.
What is a Good API?
A good API stays out of your way. Once you use it a few times, you no longer need to refer to the documentation to prefer common tasks. A good API has sensible defaults for things, and makes common operations easy and elegant. Things that are similar behave similarly, while things that are logically different appear that way. There are no surprises.
You know a good API when you’re using it. It feels intuitive. Reading some code that uses it, you don’t need to know anything in particular about how the API works to understand how it’s being used.
Of course, when we’re talking about an API here, we’re using the term in its most general sense. While many people think of APIs as endpoints for web services, APIs are also the classes and functions in your favorite package or the methods in your company’s client library. An API is simply an interface for exposing functionality in one system to other developers who want access. Requests is a perfect example of a good API, and contrasts nicely with poorly designed urllib, used above.
Making a request is as simple as:
r = requests.get("http://www.google.com")
More complex tasks like specifying HTTP headers, performing Basic Auth and even sending cookies are all just as straightforward:
r = requests.post("https://www.twitter.com/login", auth=(username, password))
cookies = dict(logged_in=True, user_id=5)
r = requests.get("https://www.salesforce.com/home", cookies=cookies)
Why Good APIs Matter
As developers, it’s easy to get caught up in the hard science of what we’re building. Is it fast? Is it reusable, loosely coupled and abstract enough?
But we often don’t spend enough time (if any!) considering how easily someone else might pick up our work. And that’s a huge problem. In a business, those problems show up as poor cross-team collaboration and create a steep learning curve for new employees.
A good way to measure this is by asking if you can get a new hire up to speed with what you’ve built in a single afternoon. Is there well-commented example code, or are there up-to-date tutorials anywhere? If the answer to these questions is “No,” then you’ve got an API problem.
This problem is not only going to cost you time, but it will also limit the amount of code reuse. If someone can’t understand how to use code that’s already been written, they’re more likely to either hack their way around the issue or rewrite the same functionality.
In the open-source community, bad APIs can also alienate new members and keep adoption of a project from rising.
Really, when was the last time you enjoyed reading documentation for hours? Don’t force others to struggle through that pain in order to use your code. Note that having fast code or a lot of functionality doesn’t make the problems disappear. Whether you’re building a web service API or a set of classes and methods for a client library, if you want other developers to use your code, it’s important to consider the design of your API.
You have to write your code to be used by humans, not just machines.
If you’re a Python developer and want to learn more, the image above is taken from a presentation called Python for Humans by Kenneth Reitz, which I’d highly recommend.