11436 SSO

API-First Development with Apigee-127 (and Swagger-Node)

Chapter 2: Closing the loop between API design and implementation
Gregory Brail
Oct 29, 2015

This is the second in a series of posts examining the considerations that went into building an API to power our intelligent API management platform solution.

In the previous installment of this series, I explored why and how Apigee set out to build an API to power its platform product. Here I’ll describe how we started to close the loop between API design and implementation, the role Swagger played, and alternative frameworks for building APIs.

We set out to create a way to build APIs that solved for a broken design-to-code workflow. Design and code needed to happen in parallel, but we also needed to adhere to our central tenets of API design:

  1. API design is important; it’s the language that developers use to communicate with the API.
  2. The style of APIs that we design is centered around well-known URIs and verbs.
  3. Documentation is important and should be a first-class citizen.

We also saw an opportunity to close the gap between the API design and the implementation.

At the same time, we expanded our use of Node.js. We saw Node.js as an opportunity to quickly build APIs for a variety of situations, so we used it for internal projects and incorporated it into the Apigee product stack. We learned that while it’s not the right choice for everything, it’s ideal for quickly building network-oriented code that performs well.

Finally, and possibly most importantly, we began to engage with the Swagger community, and started to work with version 2.0 of Swagger. Swagger is a community-driven way to design APIs. A Swagger document describes, in a formal way, all the URI paths for an API, all the query parameters, the request and response bodies, and basically everything that a client needs to know in order to successfully make API calls.

Swagger grew out of a company called Wordnik, which was having similar API challenges. They created Swagger to meet their own needs, opened it up to the community, and enthusiastically worked with us to create the Swagger 2.0 working group. This led to a description format that is designed to be more “writable,” because the API may be specified in YAML as well as in JSON.

One alternative: the code defines the API

Most existing frameworks for creating APIs fall into one of two basic categories: either the code defines the API, or the API generates the code.

The first category is represented by Java-based frameworks such as JAX-RS, and extensions such as the original Swagger for Java. In these frameworks, the developer writes code and annotates the code to specify additional attributes of each API call (such as specific names and types of various parameters, descriptions, and additional validation rules).

For instance, here's an example of an API call written in Java using the Swagger framework:

    description="Rest api for do operations on admin",
@Produces({ MediaType.APPLICATION_JSON })
class MyResource{
   @ApiOperation(value = "Get specific element",
     httpMethod = "GET",
     notes = "Fetch the element of the collection",
     response = Response.class)
   @ApiResponses(value = {
  @ApiResponse(code = 200, message = ”Element found"),
  @ApiResponse(code = 404, message = “Element not found"),
   @ApiResponse(code = 500, message = “Server error due to encoding"),
   @ApiResponse(code = 400, message = "Bad request: decoding error"),
   @ApiResponse(code = 412, message = ”Prereq: Required data not found")
   public Response get(
  @ApiParam(value = "UUID of the element", required = true)
  @PathParam("uuid") String uuid) {

Then, a separate tool is run which introspects the code to generate documentation, client-side code, and other artifacts from the source code. Sometimes this tool happens at runtime, as with the original Swagger, and sometimes it happens at deployment time or compile time—but the effect is the same.

The advantage of this approach is that the code and documentation are never out of sync, as long as the documentation is always re-generated (and updated on the web site, or wherever) whenever the code changes.

However, with this approach, there is no formal mechanism for the developer of the code to have a “conversation” with other parties regarding the API, other than via the source code itself.

There’s also not a great mechanism for the technical writer to tie quality documentation to the structure of the API. If the writing team wants to use the generated documentation as the basis of the “real” documentation, then that means that the tech writers need access to the code base in order to update the bits of documentation that are kept in the code.

The only real option is to have all parties collaborate on the code base itself, and to keep abreast of any changes (and, if necessary, to stop them before going live). This works particularly badly in closed-source situations, or even in open-source situations when the code that runs the API is sufficiently large or complex that the average “user” cannot be expected to keep track of it. It is similarly cumbersome if the technical writers don’t want to have to learn how to build and test the codebase in order to check in documentation changes.

Also, what if you don’t want the documentation to match the code? Perhaps there are parts of the API that you don’t want to document, at least not right away. Or perhaps there is a need to change the docs without doing a code release. All of these things end up driving us to the conclusion that, for “real products” at least, the API docs can’t simply be generated from the code and then put up on the web site for everyone to see.

The next installment in this series explores another existing framework for creating APIs, in which the API generates the code.

Photo: Matthew Powell/Flickr

Scaling Microservices