Hypermedia APIs: Flatten those resources!

In my previous post, I discussed the need to present a Home document.  Through its presentation your API design is able to be flexible and adaptive over time, while still being easy for clients to consume and discover functionality.  In this post, I want to discuss the design and handling of the resource representations themselves.

In traditional Object Oriented design, the principles of encapsulation encourage a class designer to hierarchically wrap atomic representations in increasingly more complex representations to compose a complete model which is self-sufficient.  In the OO world, this will enhance the flexibility of the implementation as it adheres to the information hiding principle.  A class implementer is free to make any changes to the encapsulated code, and any execution of the code is bound to the interface provided by the object, and is not impacted by internal design changes.  The following json serialization might represent a good OO model for a User class, it has been truncated for brevity.

{"user":{
  "address":{
    "street":"742 Evergreen Terrace",
    "city":"Springfield",
    "state":"?",
    "zip":"doh"
  },
  "userProfile":{
    "name":{
      "first":"Homer",
      "last":"Simpson"
    },
    "accountCredentials":{
      "userName":"homers",
      "email":"homers@example.com"
    }
  }
}}

When designing the representations for resources and messages, a designer needs to abandon this long standing practice and focus on creating the least complex but semantically complete representation possible.  The value of the atomic resource and message design is the enhanced flexibility gained by the API designer to bind related resources via relationships which allows mutability of the interface over time.  This guideline can clearly be taken to an unreasonable extreme, therefor it is important to always keep an understanding of the caveat ‘semantically complete’ in mind as there will be occasions when a representation is not entirely flat.  When successfully completed, a resource model should look to the OO designer eye to be remarkably flat and in desperate need of factoring.  For example, the representation of the above OO model could be 3 separate resources with the following representations.

{
  "user": {
    "userName": "homers",
    "email": "homers@example.com"
  }
}
{
  "userProfile": {
    "name": {
      "first": "Homer",
      "last": "Simpson"
    }
  }
}
{
  "address": {
    "street": "742 Evergreen Terrace",
    "city": "Springfield",
    "state": "?",
    "zip": "doh"
  }
}

If this was the end of the process, the resulting implementation of our API design could be a disastrous and unworkable torrent of traffic for even the most minute of tasks at scale.  In order to aggregate the same collection information in a resource representation, the design must compose the related resources through embedding, transcluding, or link relation.  Through these means, and fine grained use of cache-control, a hypermedia web api can have surprisingly low overhead while still retaining the flexibility and robust nature we seek.

At this point in the discussion of these 11 guidelines for designing a hypermedia web api the reader might have noticed the heavily referential nature towards previous guidelines.  Each guideline addresses a particular constraint or sets of constraints which a designer might be inclined bypass.  However, each step is a crucial building block on the path towards a fully functional hypermedia web api.  In order to achieve the benefits of a flexible, robust, and enduring API we must focus on designing the API right the first time, and allowing it to grow as resource and affordance understanding changes.

Leave a Reply