I could describe the topic in terms of "Hypermedia as the Engine of Application State". The "State Engine" directly relates to the issue. But I prefer to use more familiar dictionary.
Consider yet another project tracker. There is a domain rule: only Project Owner is able to delete a user story AND only stories in "initial" state can be deleted. With the "traditional" REST approach the rule gets duplicated several times: on the server side and for each client app. Without such duplication a client cannot reason about visibility of the "delete story" control. Even worse, the rule is implemented in several languages, increasing the likelihood of errors.
# Server side def deletable_by?(user) user.owner? @project && initial? end
// Android client
private boolean isDeletableBy(User user, Story story) {
return user.isOwner(story.getProject()) && story.isInitial();
}
...
if (isDeletableByUser(user, story)) {
renderDeleteWidgetFor(story);
} else ...
// JavaScript client
function isDeletableBy (user, story) {
return user.isOwner(story.project) && story.isInInitialState()
}
...
<% if (isDeletableBy(user, story) { %>
<%= renderDeleteWidgetFor(story) %>
<% } %>
With HATEOAS the rule is implemented once and only once. It doesn't spread domain logic across clients. They become fairly "silly".# JSON generation on the server side if story.deletable_by? current_user json_builder.delete_link_for story end
// Android client
if (story.hasDeleteLink()) {
renderDeleteWidgetFor(story);
} else ...
// Javascript client
<% if (story.hasLink('delete') { %>
<%= renderDeleteWidgetFor(story) %>
<% } %>
See, clients don't "figure out" or "calculate" button visibility. They render the button only if the "delete" link is present. That's all. It simplifies the iterative development process: changes in domain logic require only server code to be rewritten.# Changed rule def deletable_by?(user) user.owner? @project endJavaScript, Android, iOS clients remain untouched. They still rely on absence/presence of the "delete" link. The "traditional" REST approach requires to rewrite/recompile/redestribute ALL client applications!
Summing up: Hypermedia API keeps domain logic on the server side. It reduces cost and encourages improvements.



