At the moment I spend almost all of my time at work modeling and designing APIs. While reading through Josh's list, I could immediately identify with a couple of items, which I experienced myself.
When designing an API, first gather requirements...Code the use-cases against your API before you implement it, even before you specify it properly. This will save you from implementing, or even specifying, a fundamentally broken API.
Designing an API without knowing how it'll be used is virtually impossible. I say virtually, because in theory you have an idea of how you would use the API, that you designed. You know what it needs to provide and how the client would program against it. The problem, most of the time, is that you are not the consumer of the API and thus you don't really know how your API will be used.
I was in the same position with a particular interface I had designed. It provided a method that would return a java.util.Set implementation, containing certain Objects. I though returning a Set implementation would be a reasonable choice, since it doesn't contain any duplicates, which was a requirement. Unfortunately I didn't know, that the client of the API could only work with arrays. So with each call to my API you could find a subsequent statement converting the Set into an array.
It was not that I couldn't return an array or didn't want to. I was simply not aware of how the client would use the API. I only noticed the flaw in my design after a while, when I had to refactor the name of the method. The conversion code was polluting every call to the API and it was annoying to refactor all parts of the code. The client assumed the API was set in stone. He didn't notify me of the design flaw, which was a mistake. I think working together with the client during designing the API would have precluded the trouble altogether.
All programmers are API designers. Good programs are modular, and intermodular boundaries define APIs....API design is not a solitary activity. Show your design to as many people as you can, and take their feedback seriously.
All programmers might be API designers, even if they are not aware of it. However, not all programmers are good API designers. Why? Because coming up with reasonable contracts and interfaces is tough. You shouldn't design APIs in the dark, but rather discuss your ideas with your peers and get your client's input.
I'm reading the book Practical API Design: Confessions of a Java Framework Architect at the moment. The author claims that design by committee does work and that a group of developers on a project is able to create a reasonable API. I'm still reading through chapter one, so I'm really excited to see how to ensure consistency in terms of naming, usage model and error handling, which are some of the problems I'm struggling with at the moment. I think a certain level of consistency is crucial, especially when you think of evolving the API in the future.
In my opinion the usage model of an API is one of the most important aspects. It should be simple to use and above all, the usage should be consistent across all APIs. My prime example is the handling (or therefore not handling) of good old null. Eclipse has some good guidelines on how to use and evolve their APIs. Among others, it also covers the null problem:
- Do not treat null as an object. Null is more the lack of an object. Assume everything is non-null unless the API specification says otherwise.
- Do not return null as a result from an API method unless the result is explicitly documented (on the specifying interface or superclass) as allowing null.
- Do not return an irreplaceable array, collection, or other mutable object as the result from an API method. Always return a copy to avoid trouble from callers that might modify the object.
This is only one instance where consistency is essential. There are many others like documentation, parameter ordering or package naming. In my opinion this is where you can distinct a good API from a bad one.
API design is an art, not a science. Strive for beauty, and trust your gut.
I claim that if API design was solely an art, we would evaluate our API quality by beauty and elegance only. Maybe we even do that, at least to some extend. However, as soon as you get your hands dirty with an API and you notice, that it's not working the way you expect it, all the beauty and elegance doesn't help you get your job done. Just like in real life, beauty isn't the only quality that matters.