APIs and Abstraction - Programmer's Best Friends
Every time we build programs, we have to define some form of structures, abstractions. These structures form the building blocks of our program. The structure of a program may resemble a shanty town or something more rigid like in the image above.
I like to think program design as organic work. You do whatever you can to find constraints affecting your work and then try to come up with a decent compromise within these constraints. The constraints give you limits within you should stay. Now the question is, how to reach a decent result? Which guidelines to follow?
I will provide a few of these next. I'm sure there are more of these out there. These just happen to be ones I tend to favor in my work.
Sensibility
I guess this is kind of obvious. A good API has to make sense to someone. If the API happens to represent something physical object it should use commonly used verbs to define its methods.
To some extent sensibility is subjective. Just consider the APIs various programming languages provide for their basic data structures. I might append in Python while I have to push in JavaScript to do the same thing. Both of these verbs make sense and are somewhat interchangeable.
This brings me to my next guideline, explainability.
Explainability
If an API is sensible, it's most probably explainable. It should be easy to explain what the API is all about. If it's not, there's probably something weird going on.
A nice side benefit of this is that the API should be easy to document. Or perhaps you might to explain what the API does before actually writing it. Do whatever happens to work for you! :)
There are three more guidelines that are directly related to this one: compactness and predictability. I will take a closer look at these next.
Compactness
A compact API is simple to understand. This does not mean it cannot be expressive, on the contrary. Sometimes a verbose API yields less power to the user than a compact, well designed one.
The concept of abstraction is closely related to compactness. If you abstract and split up your API correctly, you should end up with a compact yet powerful result that yields to this guideline and the ones mentioned before.
As you split up your API to smaller segments it's important that you stick by some more global rules. The guideline of predictability caters this need.
Predictability
When you are using an API you expect it to show similar behavior all around it. It really doesn't inspire confidence when you have to check out the API documentation for possible side effects (ie. does list.sort() sort the list in place or does it return a reference to a sorted list?).
This applies for naming as well. Mixing various naming notations haphazardly is a good way to confuse the user of your API, avoid it. Set a rule and stick by it.
Conclusion
The "guidelines" I mentioned just provide a few examples of what I think good API design is all about. To summarize I try to design small and think big. I rather have a compact and powerful API than a big clunky one.While researching for this post I came by this presentation by Joshua Bloch (presentation slides). There's also a whole wiki devoted to API design.
Those links should give you a bit more perspective to API design. I guess there's no silver bullet to it. You just have to figure out how you define a good API, come up with some rules and follow them in your design work consistently.
References
The construction image was taken by Jakob Montrasio. doozzle is responsible for the hand one. David Carmack Lewis painted the one with the astronaut and the dinosaur. The car photo was taken by Mozul. Thomas van Ardenne took the glass photo.All of the images are available under permissive Creative Commons license.