What’s wrong with OpenAPI?


How we struggled with API documentation on our projects, and how we went a little crazy

Do you have an order with API documentation on your project? Most likely no. And there was no order in our company.

We will not talk about the sad consequences of erroneous, outdated or completely missing API documentation. Why, then, on most projects it is not possible to solve such a seemingly simple question?

The reason is simple: developers hate describing APIs. It’s uncomfortable, it’s painful, you never want to do it. And even if the boss one day forces (with pleas and threats) to write documentation for the first version of the API, then in the future, when the API changes, the developer will definitely not update the documentation for it.

For example, OpenAPI is the most common REST API description language. Writing in this language is so painful that a developer will never miss a chance not to do it (here is a good example relation to OpenAPI).

Let’s take the simplest API with one endpoint:

GET /users/{id}

Let this endpoint return a response with a 200 code like this:

{
  "id": 123, 
  "name": "Tom"
}

In this case, the programmer is forced to write 23 lines in the OpenAPI language (!):

openapi: 3.0.1
paths:
  /users/{id}:
    get:
      parameters:
      - name: id
        in: path
        required: true
        schema: {}
      responses:
        200:
          content:
            application/json:
              schema:
                required: [id, name]
                type: object
                properties:
                  id:
                    type: integer
                    example: 123
                  name:
                    type: string
                    example: "Tom"

Real APIs often take not 23 lines, but several thousand lines (here, for example, Twitter API for 13 thousand lines).

There are even special tools – visual OpenAPI editors that allow you to write OpenAPI code not by hand, but using a graphical user interface (for example, https://stoplight.io/). However, these tools do not help much: instead of typing many lines of OpenAPI code, now you need to click a lot with the mouse.

As a result, the following happens in real projects (we give averaged data from several studies):

  • In about half of the projects, the API is not described at all.

  • Approximately 25% of projects describe the API manually (the so-called “Spec First” approach). At the same time, in many projects, once written documentation is not kept up to date.

  • Approximately 25% of projects generate documentation from program code (the so-called “Code First” approach).

The last option, at first glance, seems like a great solution. For many frameworks, there are generators that automatically generate an OpenAPI specification based on the service code. And this is really a great way, but, unfortunately, not all projects can apply it, and here’s why:

  1. In many (especially large) projects, in addition to developers, several other people are involved in API design: architects, system analysts, QA engineers, stakeholders from other teams. Such a meeting can easily be attended by 10 people, and not all of them can or want to generate OpenAPI documents from program code. Usually you have to write OpenAPI files manually, share them, comment, make edits, etc.

  2. In many (especially large) projects, outdated languages ​​or frameworks are used, for which there are simply no OpenAPI specification generators. As a result, part of the API ends up without documentation (and as a rule, these are very important APIs that have been working in the company for many years!).

  3. OpenAPI specification generators often contain errors that sometimes do not allow you to generate what you need (here is an example of a bug in the generator). This is especially evident in large long-lived projects, when different parts of the system, as a rule, are written in different languages ​​and different frameworks. Each framework uses a different OpenAPI generator, and it’s more likely that one of those generators will fail. If the OpenAPI generator breaks, then that API remains undocumented. Of course, no one will document this API manually.

  4. OpenAPI generators are only capable of generating part of the documentation. But you still need to add detailed descriptions, usage examples, message examples (this is especially important in large projects). All this needs to be done manually and somehow pushed into the program code, so that later, based on it, the generator creates a full-fledged specification.

It is interesting that all the listed shortcomings of generators are manifested to a greater extent in large projects. That is why large systems almost always use the “Spec First” approach.

Let’s summarize (numbers are approximate):

  • More than 50% of projects suffer from missing or outdated API documentation.

  • In 25% of projects, employees suffer from the need to write OpenAPI files manually (mostly large projects).

  • In 25% of projects, the problem is solved with the help of generators. However, this solution has disadvantages and limitations that do not allow it to be used in the remaining 75% of projects.

It’s amazing how serious the consequences come from such a seemingly insignificant thing as “an inconvenient API description language”! Because of this “little thing”, developers persistently sabotage API documentation, as a result of which a huge number of existing APIs are poorly described or not described at all.

All of the above we have seen from our own experience. For several years, we have tried all possible options for documenting the API: on some projects we wrote OpenAPI documents manually, on some we created them with generators, on some we let the whole process go by itself.

One day we decided that we didn’t want to live like this anymore.

We were sure there was some other, simpler way to describe the API. However, what we ended up with surprised even us.

If you watch how programmers tell each other about the structure of an API in a typical work environment, you will never see them drawing on whiteboards or chatting with each other about something that looks like an OpenAPI specification. Instead of this they draw or send each other sample data, which need to be sent to one or another endpoint (or received in response). That is, the correspondence looks like this:

How developers share API knowledge with each other

How developers share API knowledge with each other

Showing by example is the easiest and most natural way to transfer knowledge. Apparently, this is how our brain works. You can explain something for a long time, in detail and intricately, and then show an example – and everything immediately falls into place.

Can the sample data be used to formally describe the schema of the data? Certainly! It is only necessary to agree on the formal rules for interpreting the sample data. In most cases, these rules are read quite intuitively. Let’s take the same data example:

{ 
  "id": 123, 
  "name": "Tom"
}

This example is intuitively read by us in the form of the following four requirements for the data structure:

  1. The data must be an object.

  2. This object must contain two properties “id” and “name”.

  3. The value of the “id” property must be of type “integer”.

  4. The value of the “name” property must be of type “string”.

The question arises: what if you want to add to these requirements some more “tricky” requirement that cannot be expressed using the sample data? For example, if we want to say that the property “name” in this object is optional? Again we go to the programmers and peep how they do it. In this case, they add the usual free-form comments to the data example:

Informal tagging in sample data

Informal tagging in sample data

This informal way can also be easily formalized. We decided that we would put a small json object after the comment sign with a description of all additional requirements for the corresponding property. It turned out like this:

{ 
  "id": 123, 
  "name": "Tom" // {optional: true}
}

Gorgeous!

If we knew what a huge path we have to go from the first idea of ​​​​a language to a working version that can be used in real projects, we would be horrified and understand that this is crazy. But, fortunately, we did not know about it and set to work. Here are the important principles that we have identified for ourselves:

  1. The language should be as intuitive as possible.

  2. The language should make maximum use of terms and constructions already familiar to developers.

  3. The language should be able to describe not only the REST API, but also all other popular types of API (for example, JSON-RPC). This will allow you to reuse ready-made type libraries in different types of APIs.

  4. The language must be fully compatible with the OpenAPI language (so that later there are no difficulties with creating a converter to OpenAPI and vice versa).

After a couple of years of work, we got a pretty nice language. Here, for example, is the specification of the above API (at the very beginning of the article):

JSIGHT 0.3

GET /users/{id}
  200
    {
      "id" : 123,
      "name": "Tom"
    }

The first line “JSIGHT 0.3” is the name and version of the language. Everything else should be clear without comment. Recall that on OpenAPI the same description took 23 lines.

In addition to the language, we have developed a minimal set of tools:

  • editor with syntax highlighting;

  • HTML documentation generator (to make a beautiful document);

  • message validator (so that all incoming and outgoing messages are checked against the API specification).

We tried all this in three of our projects, and here’s what we can say:

  • The API description doesn’t seem to hurt anymore. At least not a single developer wanted to return to OpenAPI 🙂

  • Hooray! Projects have 100% accurate, fresh, up-to-date API documentation (thanks to the message validator, which forces the developer to correct the API specification if it is at least a little outdated and does not correspond to reality).

  • The validator was easily integrated into all frameworks, including legacy code (we wrote adapters for C/C++, Go, PHP, Python, Java, NodeJS, Lua, and we had to tinker with it).

It also turned out that the language can be used for rough drafts right during the discussion of the structure of the future API. It happens like this:

  • one of the participants (for example, an analyst) shares his screen and opens the editor;

  • the team discusses the future API together, and the analyst immediately captures these ideas using our language, so that all participants see what happens;

  • at the end of the meeting, the analyst saves the API sketch in the cloud (yes, we made another cloud) and sends a link to this document to all participants in a general chat.

Now API design is happening with us for exactly one joint meeting. With OpenAPI, this is unimaginable – it is impossible to create quick sketches on it. Previously, meetings took place in 2-3 or more iterations, in between which the analyst fixed ideas on OpenAPI – as he understood them during the previous meeting. After that, he sent the OpenAPI file to all participants, and (well, of course!) It turned out that the participants misunderstood each other, and they needed to meet again. It turned out that the new language changed our usual API design business process.

And still.

And yet, we admit that we have gone a little crazy. Coming up with a new language in our time is, quite frankly, something extraordinary. At least for the REST API, the whole world is already using the OpenAPI language. Will people want to switch to something new if they are already used to working on the old one?

Difficult question. The entire history of the IT industry suggests that complex and machine-oriented technologies will inevitably give way to simple and intuitive ones. If it hurts a developer to work with something, then sooner or later a replacement will appear. So once there was a transition from XML to JSON. So once SOAP gave way to REST. So, most likely, it will happen with OpenAPI. But when will this happen? How will this happen? What will replace?

Can our mad attempt claim to be a successor to OpenAPI?

We sincerely believe in it! But as they say, the future will tell.

We hope this article was interesting. We have touched on complex, ambiguous questions for which there are no generally accepted answers yet. We welcome your comments and thoughts. If you’re curious, you can see our code on github, we put everything in open source.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *