The humble restaurant menu follows a common pattern where menu items are generally separated into a logical hierarchy. At the top level, we may have breakfast items, dinner items or drinks items. Each of these could be grouped further into categories like
meat dishes, fish dishes or pasta dishes (dinner items), and again into burgers and steaks (meat dishes). Each item is then described so that we (as humans) can make a choice on what to eat.
Now, consider making that same menu available as an API (for machine consumption). Think of the challenge that becomes immediately apparent; how do we describe objects that contain similar properties? How should we model burgers for example?
The natural human tendency might be to describe each burger as an object with defined properties. We may describe the “cheeseBurger”, the “baconBurger”, the “hawaiianBurger” – this follows the menu approach (the intended business purpose). Alternatively, we
could define the “burgers” as an array and identify each burger as an element with that array based on its property values.
There are a number of pros and cons to consider for each approach.
The “Named Object” approach
- The model is easy to understand (from a human perspective – developers are sometimes human)
- Consumers can navigate directly to the object needed; e.g. json.burgers.baconBurger
- Each object (burger) can evolve in isolation
- Each object can be managed via individual API end-points; e.g. http://api.sample.com/burgers/cheeseBurger
- Renaming or removing objects will lead to contract-breaking changes – forcing a new API version
- Filtering is usually done on attribute values. Doing so on objects is not intuitive.
- The object name provides identity within the interface schema. This name may need to be translated into an appropriate UI label and also makes localization challenging. The obvious solution would be to include a “label” attribute – but wouldn’t that be
The “Array” approach
- We can add, rename or remove objects (burgers) without affecting the interface model (no potential version changes).
- We can still retrieve a defined object via an API end-point; e.g. http://api.sample.com/burgers?type=Cheese%20Burger
- Consumers may need to loop through the array to find the required object by value.
- Objects have to maintain the same structure and cannot evolve in isolation.
The choice of which approach to take depends on the domain you are modeling. However, as the domain expert, the decision is yours – just understand the consequences of your choice.