usable in any place a human can be used

20091109

api design

[caption id="attachment_76" align="alignright" width="197" caption="blinkenlight interface"]blinkenlight interface[/caption]

I'm still working on my skunkworks side project, over the weekend I had the joy of integrating several third party php libraries. I got to spend a good amount of time on php.net reading over APIs and figuring out how to fit them into my project. Some of them were sublime, as though the author had read my mind and knew my exact mental model. Some of them were abominations, fighting me all the way. This got me to thinking about the design of a good API


What makes an API good? There are a few things that make an API really nice to work with.



  1. Similarity of behavior - Writing an API that does searching through a b-tree? Look at how searching is implemented for arrays or strings, and then copy the crap out of that API. This allows the developer to use all that knowledge they've built up about searching, so if I know [php]array_first($needle, $haystack)[/php] returns the first instance of $needle in $haystack or FALSE on failure to find $needle, then [php]btree_first($needle, $haystack)[/php] should work the same way.

  2. Readability - Your API should make code that is readable, the function names should be descriptive (without being overly verbose), and code written with it should flow nicely. Avoid using difficult to pronounce function names like strcspn.

  3. Minimalism - You're writing an API because you are doing something non-trivial, something complex enough that you want a simple looking API to interact with, so do exactly that, make it simple. I'm sure that reflangulating the zyffer is a complex process that involves juxtaposing the allibaster and repeppering the kilgore while making sure not to narfle the garthok, but the reason you are writing an API is to hide that complexity away, don't write a Leaky Abstraction. Allow me to write code like this
    [php]
    $zyffer = new Zyffer();
    $zyffer->reflangulate();
    [/php]
    Not like this
    [php]
    $zyffer = new Zyffer();
    $zyffer->juxtapose(Zyffer::allibaster);
    $zyffer->denarfle(Zyffer::garthok);
    $zyffer->repepper(Zyffer::kilgore);
    $zyffer->reflangulate();
    [/php]


In the course of writing the API for my side project I've found it useful to put myself in the shoes of a new programmer trying to use my API. How long would it take them to figure out X? How often would they curse my name? What is the WTFs/min ratio looking like? It has been a helpful tool to adopt that mindset and ask myself, why am I requiring this parameter, why do they have to call this function before that function, and would that be apparent, why am I making their life so difficult. It has helped my slim down my API considerably, this combined with Convention over Configuration has led to an API approaching "not terrible."


Then it hit me, I have stumbled upon a big important rule, that I've implicitly been following for years, but now my brain is aware of it.


You should write everything like it will one day be a public API

Of course, like any rule that is written in absolutes, there are sure to be exceptions. But I think on the whole, it will serve you well for a few reasons. Public APIs are written to be simple to work with, which means that after you've encapsulated all the hard complicated stuff you can interact with a nice clean API. This will make your life nice when working with your API, but the best part is maintenance. Remember that new programmer we imagined to help write the API, that will be you, intrepid API writer, just a few short months after moving on from the API. You will inevitably be called back to add a feature or fix a bug, and if your API is simple to pick up, then you will remember more of it, and relearn the parts you forgot that much quicker.


Another advantage is that a well-written API is much more likely to encapsulate well-written code. When your API is separated nicely and parsed up cleanly between well defined units of work, the code powering them will probably have well defined separation of labor and understandable flow. The API itself becomes the documentation for how a process is accomplished, the various actors nicely laid out as well defined classes and the behaviors as fancy-pants interfaces. I'm certain you can create a clean API over a horrible pile of spaghetti code, just as surely as you can create a crap API over a beautiful collection of clean OOP, but a good API encourages good code.


At then end of the day the API is the face of your code. You can write up all the pretty documentation and how-to's and promotional websites with sweet web 2.0 reflection and fun oversized graphics, but when it gets down to brass tacks the developer is going to be instantiating your objects and calling your functions. The fact that there is a pretty floating cloud icon isn't going to make a developer feel any better that she just spent 4 hours figuring out that she forgot to juxtapose the allibaster and that made shit hit the fan when she called the promulgate function on the zyffer's subclown. Make sure that your code has a pretty face, even if its only you using it, the benefits will far outweigh the minor upfront costs

1 comment:

  1. [...] been talking and teasing and hinting about my side project. Well today is the day I can finally announce my project, [...]

    ReplyDelete