What is the Role of an API Contract
API-First development has gained traction in the last couple of month. On its face its nothing new: Contract-First design is an old concept and even in the old SOA(P) days, it was considered best practice to design the interface of the service first and then do the backend implementation.
With the rise of HTTP/REST many proponents argued that you don't need an interface at all and thus interface description languages like Swagger only appeared much later leading now to a resurrection of the proven idea of designing your API via a contract, i.e., an interface description, first.
Figure 1: Relationships between API Clients, API Contracts, and API Providers
An API contract breaks the explicit dependency between an implementation by an API provider and the API clients as shown in Figure 1: All arrows, i.e., all types of dependencies point to the API contract. Thus, the API Client and the API Provider are as independent as possible because both depend on the contract and not on each other.
The API Contract obviously must contain technical details. For example, you need to defined URLs and verbs for an HTTP service. However, thinking about the API contract allows us to step back from technical details, legacy implementations, and - most importantly - switch to the client point of view. Very often API providers design the API contracts. Too often developers will just do what is convinient for them. If provider-side developers happen to design the API Contract they will think about how easy the API Contract is to implement and to offer the desired services. However, the client needs might be different, which manifests itself in different data structures and operation granularities.
Focusing on the API Contract allows to shift from thinking about the implementation to think more about concepts and business solutions. From my experience that is the greatest advantage of using API Contracts and an API-First design process.
Builds and Artifacts
While many developers (and API designers and software architects) have learned to take a business and client point of view and design their APIs first, they somehow need to manage the API contracts, e.g., the OpenAPI files. In larger organizations there might be central infrastructure - with its own advantages and drawbacks - but usually developers need to somehow manage the (organization-internal) API contracts as part of their version control system, i.e., usually git. Developers also need to package the OpenAPI contract somehow. One frequently used idea is to re-use existing infrastructure and settle on the build tool of choice, e.g., Apache Maven.
Figure 2: Sloppy Artefact Relationships between API Clients, API Contracts, and API Providers
Unfortunately, many projects will create projects like shown in Figure 2: Because it is some effort to create a new project, the API Contract (e.g., the OpenAPI files) are put in the provider implementation project. Thus, the clients need to reference (depend on) the API implementation. The dependency structure is very different from our envisioned one shown in Figure 1.
Figure 3: Improved Artefact Relationships between API Clients, API Contracts, and API Providers
As such, it is very important to take the extra step and create a dedicated project and build artefact for the API contract. This way, we have the structure and the de-coupling that we want to achieve. This sounds easy but it takes some discipline. This is especially important if a single person or a single team has both the role of a software developer and API designer.
The same considerations apply if you as an API Provider generate and/or offer API client libraries to your API Clients. These should be managed in a dedicated project and be referenced as its own (Maven) artefact.
Conclusion
But isn't this just an academic excercise? One of the principles that appeared with Microservice designs was that a service is designed to be replaced (in contrast to the reuse that was promoted before). But how can you replace a service when all your API Clients depend on your implementation project?
The answer is you can't (or only with other nasty shortcuts and bad design) and as such you should think about the dependency graph of your clients, your contract, and your provider implementation. Decouple your services by using API Contracts and making them the only interface: interfaces cut your system in pieces but they allow to plug your components together later on. Interface and as such API Contracts are at the heart of divide and conquer design strategies!
<<< Previous Blog Post Asynchronous Continuations in Camunda 7 |
Next Blog Post >>> BPMN’s Most Undervalued Elements? Start and End Events |