Tuesday, March 31, 2009

Intentional API Design

I've mentioned before that APIs are a critical component of large enterprise software offerings. The largest vendors realize this and treat API design very seriously. Some vendors, of course, actually productize their APIs via SDKs with their own installers, release notes, etc. That's often the case when the product has a well-defined plug-in architecture, for example.

Many systems have multiple APIs these days, to accommodate various abstraction levels (programmatic vs. SOAP, for example), as well as to expose different kinds of functionality offered by different subsystems. There's also the (unfortunately) common situation where a vendor has chosen to expose programmatic functionality through a proprietary, non-standard scripting language. This becomes an API of its own as well.

If there were such a thing as a middleware API maturity model, "design-by-intention" would surely be one of the principal stages. APIs run the spectrum from those that have a fully project-managed development cycle of their own (complete with requirements-gathering, design docs and specifications, dev, QA testing, usability testing, documentation, etc.) to those that are put together on an ad-hoc basis by a few developers who happen to have the time to do it.

Quite a few APIs are what I would call accidental. They've been "built out on" organically over a period of years. They are what they are. They aren't intentionally designed; rather, their structure shadows that of the product's existing codebase, thus the API inherits from the product-development processes that preceded it, rather than having arisen through any well-defined design process of its own.

Ideally, it should be the other way around. If anything, the API should precede the software. At the very least, however, APIs need to be intentionally designed. There's too much riding on them to allow them to "just happen."

Of course, once an API is in place, it's hard to redesign it or refactor it. Legacy classes that follow legacy patterns have to be left in place for backward-compatibility reasons, lest any changes break customer code. New classes and methods get added, but few are removed.

An API that's been added onto incrementally over a period of many years may have accumulated a staggering design debt. After a point, reducing the debt becomes prohibitively painful. When that point has passed, it doesn't make sense to try to refactor the API unless the product itself is rewritten.

Alas, in the software world, there's no Magic Bailout to help with design debt.

My advice? If you're one of those software vendors who've built out on existing APIs in ad hoc fashion over a period of many years, now might be a good time to assess the state of your APIs. If nothing else, ask customers and partners (maybe even your own engineers) whether your APIs are doing the job as well as they could be. Consider doing usability studies. Do your APIs promote the use of accepted design patterns? Are classes and methods as self-explanatory as they could be? Do experienced developers need to go to classroom training for a week in order to become productive? Or can a competent developer become productive on his or her own, in a reasonably short period of time?

Take a stab at coming up with some metrics, and score your APIs as to usability (fitness to purpose). Put together a business case: How much extra ROI would your customers realize if your APIs were even, say, 10% or 20% more usable than they are now? How much ROI would your company realize?

Bottom line: Don't underestimate the importance of having good APIs. And don't assume that if the product design is good, APIs will take care of themselves. That's like saying if an airplane's design is good enough, it will fly itself. That's almost true. The problem is the word "almost."