In response to my hypermedia opinions, Mike Kelly said:
These two seem to conflict: “In my opinion, abstract container formats aren’t useful.” and “Just use JSON”. People normally talk about “generic” media types, but they don’t have to a “container” at all, they can simply add conventions for linking. Having conventions for this stuff is useful because it allows us to build tooling around it, if everyone reinvents the wheel in their own way then we can’t build re-usable code. For a similar reason, “specifying your own custom MIME types” is not a good idea – there’s also the time cost associated with doing that. If you use something like hal+json you avoid that cost, and can concentrate on establishing your API’s workflows via link relations.
The logic behind the madness goes like this: abstract containers aren’t solving a problem I currently have. Unfortunately, this means they create problems for me. In the end, I’m building an API to provide functionality, not as advocacy.
As of summer 2012, there are ideas like HAL, JSON collections, etc. and specifications of those ideas. There are very few implementations. As a service provider, I wouldn’t actually get any benefit out of using those formats. The convention, within my own API, that fields ending in _url
are links is sufficient. I’d actually end up net negative, because I’d have to explain how e.g. HAL works and support client developers seeking to understand how to work with it. Anyone building to my API would likely end up having to write their own HAL code, so they don’t benefit much either.
I’ve decided to use JSON because providing an API that returns HTML and expects users to scrape it via selectors is extremely confusing to developers. Keep in mind, not everyone is savvy to the latest development trends. To them, an API means an HTTP service that returns XML or JSON. If I were to embrace HTML as a response type, I’m again stuck with explaining a new concept to client developers.
If it’s not obvious yet, one of my main principles in adopting hypermedia is to avoid educating developers on hypermedia as much as possible. I’m in the game of providing a useful API, not a system that shows off the possibilities of hypermedia and how deeply committed I am to its theories.
Finally, I’ve chosen to craft my own content types because I need some kind of contract with client developers that tells them what kind of data they can expect to see, plus some documentation that expresses that contract in a way that is easy for humans to understand. An RFC-style specification that states what a content type MUST/MAY/SHOULD include is exactly the right kind of abstraction. It allows me to update the specification with a version identifier and specify how each revision changes in terms of what data is available. Further, I found a content type the most tractable solution for specifying the input formats supported by PUT and POST endpoints. None of the abstract containers that existed as of August 2012 fit my needs for specifying links, structure, and how to submit data via POST
/PUT
/PATCH
.
Honestly, link traversal and machine-to-machine interaction are not the pain I’m feeling. What I want is the simplest possible API that allows potential client developers to understand what they can do via our API and how to do it. Further, I want it to be possible, even if it’s not magical or easy, to change the API in the future so I’m not constricted by its current design. I feel no need to apply all of the hypermedia principles to make something useful; I can cherrypick some of the hypermedia principles and still achieves the goal of an API that is stable but not set in stone.
Ok I disagree with a number of points:
“I’d actually end up net negative, because I’d have to explain how e.g. HAL works and support client developers seeking to understand how to work with it.”
This is illogical, how could you end up “net-negative”? Your custom media type will require the same effort to educate about its workings. In fact it’s actually worse with a custom media type, because with hal there is a chance your client developer is already familiar with it.
“There are very few implementations. As a service provider, I wouldn’t actually get any benefit out of using those formats. […] Anyone building to my API would likely end up having to write their own HAL code, so they don’t benefit much either.”
Both of these are incorrect, checkout this growing list of libraries for serving and consuming hal:
http://stateless.co/hal_specification.html#libraries_for_working_with_hal
again, if you pick a custom media type you (and your clients) will start from scratch.
“I’m in the game of providing a useful API, not a system that shows off the possibilities of hypermedia and how deeply committed I am to its theories.”
Again, this is the core philosophy behind HAL. If you read through the last 2 or 3 years of discussion around this you will find me arguing for a “middle road” approach in which the theoretical benefits that rely too much on client developer’s “getting it” are dropped in favour of producing hypermedia types that dont’ require the client to think. If you take a look at a HAL response, it is not very difficult to understand. That is on purpose.
As a concrete example: there have been many people questioning why HAL doesn’t have a notion of ‘forms’.. the reason that was not added is precisely because it would rely on more sophisticated client capability.
All HAL does is establish some very *fundamental* conventions that serve as the basics of linking. That’s all, really. You can use it, and you don’t have to worry about whether it’s right or not – the hal community has invested 2 years in distilling it down for you. That is a good thing. This has been an industry led thing. I am not a standards guy, I’m a web developer. The “spec” was a website with a github repo for at least a year and a half before I formalised it into a proper spec. I did that because people were asking for it, not because I had a burning desire to spend my time fucking around with rfc2xml.
“Finally, I’ve chosen to craft my own content types because I need some kind of contract with client developers that tells them what kind of data they can expect to see, plus some documentation that expresses that contract in a way that is easy for humans to understand. ”
Content-types are not a pragmatic way of doing this. For a start, they aren’t discoverable – you can’t just look at a content type and know where you can find the documentation. Secondly, if you want to make a new version, you have to version _your entire application_.
There is an alternative. That alternative is link relations. Link relations are granular (per link, obviously). An most importantly discoverable – which means the relation itself can be a URL, which a develop can stick in a browser and read the documentation for that relation. If you want to see how this works in practice **please** take a look at this (click one of the book icons):
http://haltalk.herokuapp.com/
There’s a lot more to say, appreciate this is a long comment. But if you take anything away, please let it be that application/hal+json was not an academic effort, it was not astranautic, it’s not complicated, in fact it omits a whole bunch of shit a lot of hard-line hypermedia wonks believe it shouldn’t, oh and I don’t worship roy fielding either.
Cheers,
Mike
Thanks for your detailed response!
When I say net-negative, what I mean is I have to take the time to understand and implement HAL, *plus* document and explain it to client developers. For the near future, HAL is going to be a strange new thing to most developers.
The list of language implementations has grown a lot since last I looked. That’s good!
I’m not trying to say that HAL, or link-relations, are academic. But they are beyond my budget for complexity, both in my service and in supporting developers. Maybe content-types will involve the same magnitude of work, but it’s work I had to do already to document my API. In return, I can reduce the number of response types my API has and re-use those types when data is submitted to the API. That feels like a win today, but ask me again a year down the road :)
Defining individual link relations is what you should be doing anyway of your linking, even if you don’t call them link relations and you call them link names or named URLs. You’re talking about media types like you need to create one for your app. You don’t if you use hal+json, instead you break down your app as a set of link relations which are URLs that serve their own unit of documentation. This is not more work as you are already documenting your links. It’s less work because you don’t have to document the media types processing rules.. Since your using hal+json and it already has a spec that’s had 2 years worth of collaborative editing put into it.
Nice post. Would be really cool to see the details on your media type designs. I am always looking for real world examples in the area. Are your types documented already? Where can I check them out?
Cheers and thanks.
Mike, the Sifter API I’ve been hand-waving is close to completion, but not yet public. I’m writing up a strawman example that demonstrates the design principles I’ve used in building that API. I’m hoping to publish that example this week.
I’d be interested in checking out your API. Do you have an update for us?
Still in progress. The client and server are done, but I need to finish the docs and write up the actual article.