Now that I have moved from design to implementation, I am noticing another kind of tension. As developers begin to use the emerging API, they make enhancement requests. Often these requests are to add a method that is outside the scope of the API, or worse, to make an existing method do some additional work that isn't obvious from the method definition. As an example, I've had several requests to make methods aware of the User Interface (UI) context, but this is an API for accessing data and metadata. None of its implementations should introduce side-effects in the UI unless all of them can guarantee the same behavior. I think it is important to keep the API contract as simple as possible, so I generally decline such requests.
It strikes me the answer to both kinds of debates is the same: "Form follows function." This phrase first gained currency in the discipline of building design. The late 19th century architect, Louis Sullivan, and his disciple, Frank Lloyd Wright, were its most famous proponents. The phrase is sometimes misinterpreted as a statement of precedence. In other words, it is interpreted as, "function precedes form," but that's not really the idea. Rather, Sullivan and Wright were reacting against the conventions of the day. They thought it was silly to build Renaissance train stations, Greek Classical post offices, and English Tudor homes. There were against ornamentation for ornamentation's sake. As Wright said, "Form and function should be one, joined in a spiritual union."
"Form follows function" has been applied to lots of other design activities besides building design. I actually haven't heard it used in reference to the design of an API, but I think it makes sense. It carries with it two important ideas. When designing an API, you should:
- Resist unecessary ornamentation. Some conventions are certainly of universal importance, but others should be applied in only some circumstances and some are mere fads. Each convention should be tested against the function of the API. Does it really make sense in this context?
- Make each method as explicit as possible. To improve the usability of your API, give each method a descriptive name and make it do what it says -- no more, no less. Avoid the temptation to have methods cause side-effect in other parts of the system. This is particularily important for APIs that will have multiple implementations.