“Divide each difficulty into as many parts as is feasible and necessary to resolve it.” – Rene Descartes
As I continue my journey to understand the essence of a great Application Programming Interface (API), I find it necessary to drill a bit deeper into the make-up of an API.
APIs represent the boundary between two components. Good APIs are a well-designed entrance into a component to request its capabilities. The API is not the capability itself; rather it enables and mediates access to the capability.
Much like an entrance to a building, you have to consider not only the core purpose of the entrance, but also the purpose of the building and even the purpose of the entity that owns the building. You must think about the basic utility of the entrance such as:
- easy access balanced with appropriate security
- protection from the elements
- capacity to accept the right number of visitors or materials at the same time
- intuitive directions to influence the flow of visitors
- the impression the owner would like to convey
You must also consider the desired representation of the entrance to complete the set of required characteristics. These characteristics will obviously vary greatly between a home, a retail shop, a corporate headquarters, a back-office operations center, a manufacturing facility or a warehouse. Depending upon the needs, there may be grand public entrances that convey the success and values of a corporate head office with a welcoming and inspiring atmosphere. There may be other entrances that are private, nondescript and convey the high security necessary of a back-office financial services organization. Other entrances may even be receiving and loading docks specifically dimensioned for a manufacturing or storage facility. Likewise, APIs must take many factors into account to ensure they will provide appropriate value.
By creating a model to define the landscape and anatomy of any API, we can create a common language to aid us in conceiving, designing and engineering an API that will be fit-for-purpose, durable, useful, usable and (most importantly) used – a great API.
Before we dive into the pieces and parts of APIs, we must first provide some context by setting the landscape within which APIs exist.
When we think about the lifecycle of an API, we are often drawn directly to the Software Development Lifecycle (SDLC) tied to its creation and care. After all, an API, like any technology, has a lifecycle and as such will exist in many phases each with specific needs and roles playing against it. However, APIs have other dimensions of influence that must be considered to fully appreciate the breadth of components and processes involved in successfully creating and sustaining an API.
Figure 1 Three-Interconnected Lifecycles of APIs
I have derived the Three-Interconnected Lifecycles of APIs from the Three Essential Activities for Software Product Lines created by the Software Engineering Institute at Carnegie Mellon University which describes how a set of software systems can share a common, managed set of features for different market purposes by using a set of common core assets (such as a platform). That model is driven by the three essential activities of core asset development (Create) and product development (Use) controlled by technical and organizational management (Manage). This model fits our needs nicely as APIs are a way to represent those core assets to fulfill software product lines through independently delivered products. These three activities are interdependent with a strong feedback loop between the Create and Use cycles. The model does not imply order because applications (products) and APIs (assets) often evolve in tandem and origination varies (chicken or egg) – applications may identify a need for an API first while an API may be derived from an existing system first. The key point is to understand that these perspectives exist and heavily influence one another.
API as a Domain
Most of the focus of this post will be at the individual service or resource level interface (API as an Interface), however, an API can also be seen as a collection of interfaces that encompass a specific set of needs. Organizing interfaces into logical groupings provides benefits for market-facing product management, portfolio management, consuming designer consistency and operational management. The success of an API depends upon the context that defines the domain of those collections, any conventions across each collection and the relationships between resulting resources within each collection.
API as an Interface
“API as an Interface” is the subject of the remainder of this post. It refers to the API as a single point of access to a service or resource, such as a web service end-point in SOAP or REST.
By breaking “API as an Interface” into several concepts with the landscape in mind, we can identify the scope of considerations and common terms we can use to communicate about the design of an API.
The best metaphor to decompose an API is the business service. This is not specific to the latest brand of remote APIs such as web services of Service-Oriented Architecture and REST fame, but any API. Service is the basic concept of a customer (Consumer) engaging with a supplier (Provider) to receive some Capability or resource within an agreed framework (Contract).
Figure 2 Business Service Metaphor
So, just as you contract with your local cable company to receive your favorite shows at the times you want for a specific fee, the same is true of a software API. An API also has a Consumer and Provider and is the subject of (and often enforces) a Contract to deliver an identified Capability. Lawrence Wilkes and David Sprott of Everware-CBDI provided an excellent introduction of the concept in Service Concepts 101 in their component-based design work. Similar concepts exist in Bertrand Meyer’s Design by Contract which expands the notion of contract to include invariants, defined as pre-conditions and post-conditions, as a way to describe the interaction.
Component-Based Design (CBD) was born out of the turmoil of early large software system development and evolved with Object Oriented Design (OOD) through the 1980’s. It promoted separation of concerns and formalized the concept of components as modular representations of well-scoped and assigned responsibilities connected through well-defined interfaces. It promoted the idea of substitution of a component as much as the reusability of a component to create a landscape of mix-and-match units that can be composed in many ways to provide specific solutions. This model serves us well in not only explaining “APIs as an Interface”, but also to ensure we are achieving those core objectives shared by CBD and the modern API movement. As such, I will embrace that model to expand on Wilkes/Sprott’s model to drill further into the Contract component to identify the key parts and concepts.
While the Wilkes/Sprott model explores the abstract view that everything is a service, I have focused only on software services. In this model, the Service is subject to the Contract that is the definition and agreement the Consumer accepts and the Provider will offer.
Figure 3 Service Contract Decomposition
The Contract is defined as:
- Capability: The ability and facilities/resources to perform some task/function identified by the Contract and provided by the Service. In this conceptual context, it is directly related to a business capability that will result in some outcome. In the design context, it can be directly related to software functions and resources required to produce the outcome. In either case, it is the core reason of being for the Service. Capabilities are important not only for defining a specific Service, but also for planning and managing “APIs as Domains”, especially for product and portfolio management.
- Service Level Agreements (SLA) and Policies: These are the non-functional and operational parameters in which the service will be delivered such as reliability/availability, performance/capacity, support, incident response/resolution and security.
- Specification: Defines the behavior of the service as seen through the Interface to be used by both the Consumer and Provider at design time as well as for discovery by the Consumer. The Specification can also be used by any registries or directories to provide visibility and enable that discovery. The Specification is further defined by the following:
- Interface: Defines the programmatic methods and structures by which a component will deliver its capabilities to other software units. In terms of a software service, this IS the API. It is the technical location, interaction method (e.g. request/response), request signature (structure of a call) and a description of the data structures involved.
- Invariants: Defines the context and agreed state transition of an interaction by declaring explicit assertions that can be made around the interaction as pre-conditions and post-conditions. Built-in software language assertions are not required, but could be used to programmatically verify expectations.
- Documentation & Training: Defines additional context than cannot be derived from other Specification components as well as providing necessary guidance for a Consumer to effectively use the Service. Documentation includes definition of conventions, overviews, dependencies and scenarios potentially in the form of use cases or user stories.
- Examples & References: Provides key use scenarios with actual data to demonstrate how to access and specific behavior.
- Commercial Agreement: Defines the commercial terms including any costs, terms, penalties and tiers of service where applicable.
Contracts may be applied to all Consumer/Provider pairs or may be uniquely defined for a specific Consumer/Provider pair. In that case, it is typical that the Capability and Specification will remain consistent with more variation found in the SLAs/Policies and Commercial Agreement.
At this point, you may be wondering, “Where is the code?” I have deliberately left how the code is related (the HOW) until now, not as the punchline, but to emphasize the importance of the overall conceptual structure (the WHAT) of a Service.
Figure 4 Service Provisioning Decomposition
In this model, the Service provides the Capability through an Interface, both of which are provided by the Software Component. For software services, the Service Provider implements the Software Component which is a realization of the technical Interface and the Capability through a software unit. Even if the Service is a derivation of one or more Software Components, such as through transformation, aggregation or orchestration, this model still stands as that becomes the details of the Software Component design. Likewise, additional levels of indirection may be applied within the Software Component to isolate such things as the particulars of the protocol employed by the Interface from the core software unit.
With all the parts and activities laid out in this conceptual framework, you can begin to see how they align and why such a broad set of considerations are required to plan, design, engineer and manage an API. While I have left the hard work of converting this to a working API, my goal for this model is to provide a language, structure and activities from which we can hang the ecosystem of participants, processes and technical capabilities required to deliver an API that is fit-for-purpose, durable, useful, usable and, (that’s right, most importantly) used.