Writing a new library? Sketch it out first

So you’re embarking on writing a new library. You might dive right in to the code and work straight on solving the problem or you might take a more considered approach and start thinking about how to model the problem, what classes and methods you need to create, how they interact and so on. However, rather than doing that why not start with sketching out not how the library works but how you would like it to be used. I think you’ll see pretty positive results if you try it.

Usability isn’t just for designers. If you want your co-workers or other developers to use and be productive with this code your creating its got to be as simple and fun to use as your user interfaces. Your library’s API is a user interface. History has shown that libraries and open source projects that put their API design up front are far more successful than their competitors. Take jQuery for instance, you can bet that when John sat down to create jQuery he wasn’t thinking “How do I animate CSS style?” or “How do I create and event system?” his main concern was how he wanted jQuery to be used. At least initially, the internals of jQuery were a mish mash of various libraries that came before it. What actually powered the explose growth of jQuery was the revolutionary API concepts it introduced: Method chaining, Selector-focussed API, simple plug in interface and so on. Other success stories like Ruby on Rails shared a similar focus on API design.

So, how do you write your code in such a way that it will make programmers happy and propell you into internet stardom? When you start out writing a new library or feature, start with a sketch. Cast aside any ideas that you might have already have about the implementation details and try to also cast aside any technical constraints and just start writing how you’d like your code to be used. Let’s take a DOM builder, for example. Mashing strings (or indeed using the terribly designed W3C DOM API) is no fun in JavaScript. If you were taking an implementation first approach you might start with an JSON-style data structure describing your DOM fragment or maybe even consider a set of objects that map to the various types of elements and this may well be how you implement it under the hood but put that aside for now. How would your code look when using the library? Here’s my first pass:

var fragment = build(
  div({ id: 'contact' },
    ul(
      li('Email: whatever@thing.com'),
      li('Twitter: ', a({ href: 'http://twitter.com/danwrong' }, '@danwrong')) 
    ) 
  )
);

Come up with the simplest, most aesthetically pleasing API you can and keep itterating on it until you’ve weeded out all the complexity you can. If certain arguments are optional or have a sensible defaults then make sure that the developer doesn’t have to worry about them unless they need to, is your library similar to any other library? If it is maybe its worth adopting the conventions of that library so it acts in a way that other developers expect it to. Developers dislike like reading documentation as much as your site’s users dislike read help pages. Strive for an API so simple that you can describe it in a few sentences.

Once you are happy with your sketch start building it out. You might need a little meta programming magic to realise the UI you are going for and that’s fine but use with caution. You need to weigh up whether the magic you are adding is going to make your code act in a way that is unpredictable to developers used to working with the language in question or if it will prevent developers from using their existing knowledge of the language to solve problems with your code. If you smell badness then leave the magic behind. In our example above we need to do quite a bit of work with the function arguments in order to support variable amounts of child nodes and to allow optional attribute hashes. In this case I’d make the call that this doesn’t add any extra confusion to the code so I’m happy to go with that.

Also, at this point consider how the API you are trying to design will impact real world pratical issues. For instance, in the example above it I would need to create functions for all HTML tags on the global namespace. Am I happy with my library a defining a global function called a()? No. Time to scale back on that idea a little.

Finally, when it comes to the implementation ensure that the architecture is sound and don’t try to couple the under the hood implementation with the API design to a degree that it’ll make the quality of the library suffer. I often view the API as a simple, pretty veneer over the top of a well crafted solution. Don’t hide the raw internals, make them accessable alongside the simple API. That way if the developer is on the beaten track they get a simple API but if they have specific needs they can delve right in and get stuff done.

So yeah, next time you write some code. Think about sketching out the API first rather than leaving it as an after thought. Your colleagues will thank you.

I’d love to speak more about this at JSConf. The competition is very hot but here’s my proposal if your interested. If it’s picked I’ll go in to detail on some great and poor examples of API design and also show off some nice techniques for bringing your API sketches to life.

3 Comments

A very interesting post, and while I agree with the message, I think that the code sample does not do the message justice.

It’s ONE statement. If you put it on one line, it’s completely unreadable, and indented, it’s a big staircase. Experience has taught a few of us to be skeptical of staircase codez.

But then again, the API might be aesthetically pleasing to you, and beauty is in the eye of the beholder :)

Morgan RoderickMorgan Roderick at 10.02.11 / 11AM

Totally agree that usability should be at the forefront of one’s mind – I consider the Design of Everyday Things to be a great book for programmers.

Your example is a js builder. I’d like to point out a couple existing builders – one is (the confusingly named) jaml:

https://github.com/edspencer/jaml

Which uses a dsl-function style. Very clean-looking, but unfortunately the cost of the dsl is your builder functions lose the ability to close around the surrounding state.

var x = 1 build(function(){ div(x) })

won’t work. The alternative form is something like jbob (I’m the author) which simply provides functions that return strings:

https://github.com/sconover/jbob

...I make it so you can define any builder function you want, and decorate any object you want with those functions. The trade is that the object you decorate is everywhere in your builder code.

The benefit is that programmer expectations around what’s in scope are not violated. This fits right into the UX approach to library-building – is the trade of expectations-violation worth it in order to get a cleaner builder “look”? (This dilemma WRT builder style crosses languages too…)

Steve ConoverSteve Conover at 10.02.11 / 14PM

Really nice article and good replies. I must say I agree with Morgan. Keep up the good work!

Mirko BuraMirko Bura at 01.03.11 / 22PM

About This Article