The characteristic HATEOAS is, in the words of its author, "design on the scale of decades" and "many of its restrictions are directly opposed to efficiency in the short term". That is, it is something applicable to software/platforms of more general purpose, destined to survive for a long period of time, despite the evolutions of technology.
The best example of practical application of HATEOAS is the HTTP protocol, in which a variety of servers can communicate with a variety of clients, and both can evolve independently of each other. In a web application, for example, not only page structures are reported by the server (and rendered on browser) as also comes the indication of what actions are possible from that page - represented by means of Urls to be consulted (whether hyperlinks, form destinations, or something else). A change in the server (say, the inclusion of a new field on the page) does not require a change in the client, as any actions related to it will be represented in the form of hypermedia, and the browser knows how to invoke them via the HTTP protocol itself.
You are right when you say that the links should represent what can be done next. The meaning of this, however, is that it is the key point: this data + link combination represents the state system, or resource within the system. Using the same example cited, if the bank account is in the negative, then you cannot withdraw from it or transfer from it, just deposit more money into it:
<?xml version="1.0"?>
<account>
<account_number>12345</account_number>
<balance currency="usd">-25.00</balance>
<link rel="deposit" href="/account/12345/deposit" />
</account>
This has at least two practical meanings:
- The server does not need to keep track of who the client is accessing, nor what state it is in: the client itself knows that the only possible transitions are those for which a link is available;
- Client does not need to implement any custom logic to find out which actions are possible based on the current state of the resource (ex.: check whether the balance is positive or not, and on that basis determine whether or not the withdrawal or transfer links should be displayed/enabled). The links themselves already say - by their presence or absence - what can or cannot be done.
As for their claim that "the client will not decide for itself which calls to make based on these links", in fact, it will not, at least not without some action being taken by the user. But isn’t that the only reason the server communicated with the client, to allow the user to do something? If the next call could already be determined according to some automated logic, did not need the control come to the client and he make a new request after that, it would be enough for the server itself to decide and do it right there...
hardcoding
That question of what to put hardcoded And what you leave generic is just what differentiates a long-term design from a short one. If you are developing a single server to communicate with a single [client type], then it makes no sense to use REST in principle, let alone use HATEOAS! Only if you predict that multiple clients will be developed over time, and all have to be compatible with your server, does this methodology apply.
The whole question is of evolution: whether in the specification of its client you determine that "there must be a screen to represent a bank account, with a pro number and another pro balance field, and buttons for the 'deposit', 'withdraw', 'transfer' and 'close' actions, nothing prevents multiple implementations of your client be done. However, if in the future you decide to include an "agency" field, or you will have to make it optional (not to break the clients existing) or will need to update the specification of the client (automatically making all existing ones incompatible with your version of server). The evolution of the server is linked to the evolution of the clients...
In the case of a field, as in the example above, there is no easy solution: after all, the semantics behind the represented data still needs to be agreed between clients and servers, and this has to be done "out-of-band" (as an example, each HTML tag has a precise semantics, and it is so expected that the browsers render/implement it correctly when the servers send it with a correct expectation of what will be presented to the user).
But in the case of actions, in the sense of "things that may be required later from the server", it is simpler to establish them in a generic way than to put them also hardcoded in the specification. Of course, this presumes some way to communicate to the user what the semantics of it is (a new link appeared, but what exactly does it do?). This can be done either in a generic way (a text, icon or tooltip accompanies the link) or also require a change in the client (if it is an automated tool that is consuming your REST API, there is no way out but to adapt it to benefit from the new possibility that has emerged).
Importance and Benefits
Unfortunately, I don’t have enough knowledge or experience to comment on that. The vast majority of the software we do seeks short-term efficiency, and the most common form of evolution is "throw it away and start from scratch"... Not only is it rare to have term and budget to design for the long term, but it is also relatively rare to have interest in interoperability with third party systems (my company’s server has to be accessed by client of my company! ). And when the need for an API arises, it is usually intended to power an automated process, which needs to make a decision regarding the next step to execute, and therefore a "knowledge" of the semantics behind the available actions.
For these reasons, me I personally do not see much benefit in following the REST and HATEOAS principles to the letter; perhaps with more experience in larger projects, my opinion will change, and I can give a more complete and informed answer. At the moment, I can only answer with another question: are you prepared for the moment your service evolves? How do you want to prevent all clients break even when it happens?
At the moment I cannot give a comprehensive answer, but think of a simple web page: the client (browser) may not decide for itself which calls to make, but the user can - just click on the links! The fact that web pages use HATEOAS allows both servers (i.e. the one that implements application logic, and that serves web pages according to this principle) to vary (no matter if it is Java, . NET, PHP, Python...) how much customers who consume them can also (no matter if it’s Firefox, Chrome, IE...), independently of each other. The general idea is this.
– mgibsonbr