There is an expanding market of companies, software, and services to help organizations provide APIs. One such company, Apigee Corporation (http://apigee.com/), surveyed 200 marketing and IT executives in U.S. companies with annual revenue of more than $500 million in 2013, with 77% of respondents rating APIs "important" to making their systems and data available to other companies, and only 1% of respondents rating APIs as "not at all important."12 Apigee estimated the total market for API Web middleware was $5.5 billion in 2014.
The following letter was published in the Letters to the Editor in the August 2016 CACM (http://cacm.acm.org/magazines/2016/8/205034).
I doubt many software developers were surprised by Brad A. Myers's and Jeffrey Stylos's conclusions in their article "Improving API Usability" (June 2016). I anecdotally suspect most poor API designs are based on what the implementation does rather than what the user needs.
API designers know the implementation too well, suffering from the curse of knowledge. The API makes sense to them because they understand the context. They do not consider how an API can be confusing to users without it. Worse yet, implementation details could leak into the API without the designer noticing, since the delineation of the API and feature implementation might be blurred.
I agree with Myers and Stylos that the API should be designed first. Design and code operational scenarios to confirm API usability before diving too deeply into feature design and implementation. Spend time in the mind-set of the user. The scenario code used to confirm the API can also be reused as the foundation of test code and user examples.
Myers and Stylos recommended avoiding patterns. Creation patterns involve API complications beyond usability. Gamma et al.(1) defined creation-method names that suggest how the returned object was constructed; for example, factory-, singleton-, and prototype-created objects are acquired through create, instance, and clone, respectively. Not only do these different object-acquisition-method names create more API confusion, they violate encapsulation, since they suggest the creation mechanism to a user. This naming constraint limits the designer's ability to switch to a different design-pattern mechanism. Gamma et al. also failed to define creation-pattern clean-up mechanisms that are critical in C++, one of their example languages.
I prefer to unify my creation-pattern objects by defining acquire to acquire an object and release to release an object when it is no longer being used. These unification methods encapsulate the creation pattern and provide for clean up, as well. They yield a consistent API based on user need rather than on an implementation-creation mechanism.
They also affect usability, however, since they are not standard nomenclature, so I take it one step further for APIs used by others. I use the Pointer to IMPLementation, or PIMPL, idiom to create a thin API class that wraps the functionality. The API class calls acquire in its constructor and release in its destructor. Wrapping the unification methods within the constructor and destructor results in an API that uses the source language's natural creation syntax yet still offers the advantages of the creation design patterns within the underlying implementation.
(1) Gamma, E., Helm, R., Johnson, R., and Vlissides, J. Design Patterns. Addison-Wesley, Reading, MA, 1995.
Displaying 1 comment