クライアント側のHATEOASのポイントは何ですか?


35

私が現在理解しているように、HATEOASは基本的に、次に何をすべきかについての情報を各応答リンクと共に送信することに関するものです。簡単な例の1つは、インターネット上で簡単に見つかります:銀行システムとアカウントリソース。この例は、アカウントリソースへのGET要求後のこの応答を示しています

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">100.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
    <link rel="withdraw" href="/account/12345/withdraw" /> 
    <link rel="transfer" href="/account/12345/transfer" /> 
    <link rel="close" href="/account/12345/close" /> 
</account>

データとともに、次に何ができるかを示すリンクがあります。残高がマイナスの場合、

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">-25.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
</account>

入金のみできるように。Fiddlerを使用している場合、またはブラウザーで要求を行っている場合、何ができるかを簡単に確認できます。この種の情報は、APIの機能を発見するのに役立ち、サーバーはクライアントから切り離されます。

ただし、ポイントは、Javascriptを使用したSPAやAndroidアプリなど、クライアントを構築するときに、HATEOASがどのように関連し続けるかを見ることができないということです。つまり、SPAをJavaScriptでコーディングしている場合、コードを記述するためにAPIで何ができるかを知る必要があります。

そのため、サーバーにajax呼び出しを記述し、さらにはUIを構築するために、リソース、サポートされるメソッド、受信するもの、返すものを知る必要があります。UIを構築するとき、アカウントをリクエストした後、たとえば、アカウントにデポジットすることができます。そうしないと、UIでこのオプションを提供できません。また、Ajax呼び出しを構築するためのデポジットを行うには、URIを知る必要があります。

つまり、APIにリクエストを行うと、リンクによってAPIの検出と使用が改善されますが、クライアントを作成すると、作成するアプリは単にリンクを見てからそれ自体をレンダリングしません正しいUIを作成し、適切なAjax呼び出しを行います。

それでは、クライアントにとってHATEOASはどのように重要ですか?とにかくHATEOASに悩まされるのはなぜですか?


1
あなたは正しいですが、それはポイントではありません。HATEOASにより、クライアントのページ内のリンクのURIを作成する必要がなくなります。
ジェームズマクラウド2015

回答:


24

作成しているアプリは、単にリンクを見てから、正しいUIをレンダリングして適切なAjax呼び出しを行うだけではありません

実際、これはまさに HATEOAS UIに与えるものです。可能なことではなく可能なときに。HALのような正式なHATEOAS は、質問が述べているように、可能なことを示すリンクを提供します。ただしこれらのリンクが表示されるタイミングは、アプリケーションの状態によって異なります。そのため、リンクは、リソース上で(既に実行されたアクションに基づいて)時間とともに変化する可能性があります。

これにより、可能なすべての状態を含むUIを構築できますが、それらの状態がいつアクティブになるかは気にしません。たとえば、の存在によりrel="deposit"make depositフォームをレンダリングしてもよいかどうかをUIに直接伝えることができます。これにより、ユーザーは値を入力し、リンクを使用して送信できます。


2
UIを構築するとき、APIが提供するすべてをまだ知る必要があり、それらのリンクを見ることで、サーバー上の情報の状態を知ることができますか?たとえば、UIは、入金、引き出し、転送、または閉じることができることを認識し(可能なrelsを認識します)、状態を確認するために戻ってきたものをチェックしますか?
user1620696

1
はい、できます。繰り返しますが、それはあなたがそれをどの程度動的にしたいかによって異なります。他の人が述べたように、サーバー上のリンクを変更できる(そしてクライアントを壊さない)機能は別の利点です。そして、APIにiPhone、Android、Windows Phone、モバイルWeb、およびすべてを使用するWebクライアントがあれば、これは非常に興味深いものになります(APIが他のクライアントを構築するために公開されているかどうかは言うまでもありません)。
ダビントライオン

@ user1620696いずれにせよ、クライアントとサーバーの両方を介して、これらすべてを知っておく必要があります。コンテンツタイプは、ダムxmlやJsonだけではありません。クライアントが操作する方法を理解している「銀行預金」コンテンツタイプが必要です。
CormacMulhall

1
@Nik は、応答でリンクがどのように提供されるかの例についてHALを調べます。
ダビントライオン

1
はい、下位互換性の問題がまだあります。これは、URLにバージョンヘッダーまたはバージョンを含めることで解決できます。しかし、私はあなたが正しく理解していると言うでしょう。
ダビントライオン

3

私が現在理解しているように、HATEOASは基本的に、各応答リンクと一緒に次に何をすべきかについての情報を送信することです

HATEOASは単なるリンクではありません。アプリケーション状態のエンジンとしての「ハイパーメディア」です。

説明にないのは、コンテンツタイプ、つまりクライアントとサーバー間で渡されるハイパーメディアの正式な定義です。

HTMLはハイパーメディアの例であり、HATEOSが機能する理由の例です。HTMLページ自体は、クライアント(つまりユーザー)がサイト内を移動できるようにするエンジンです。ユーザーに完全にナビゲート可能なWebサイトを表示するHTMLをレンダリングする機能のみを備えたブラウザ。リンクを他のページに渡すだけでなく、リンクにコンテキストを与える意味のある方法で、ブラウザがナビゲート可能なサイトを構築できるようにリンクを渡します。

そして最も重要なことは、ブラウザーがWebサイト自体を事前にZEROで理解することでこれを実行できることです。ブラウザはHTTPとHTMLのみを知っています。その単純な理解に基づいて、ユーザーにNew York Timesを提示してナビゲートすることができます。

これは、「ユーザー」が別のコンピュータープログラムであっても保持されます。ハイパーメディア自体がナビゲーションのコンテキストを定義する必要があります。


1
これは、ブラウザと同じくらい複雑な(そしてバグを起こしやすい)クライアントを構築しなければならないという意味ではないでしょうか?柔軟性がしばしば...コストと複雑さが付属しています
アンドレス・F.

@AndresF。それはあなたがそうしなければならない、またはそうすべきだという意味ではなく、単にあなたがそれを望むか、または必要とするなら、あなたに動的にそれをするオプションを与えるだけです。
ペテルス

2
@nikもちろん。私の頭上では、安らかなAPIを介して祖先情報を提供するサービスがあると想像してください。コンテンツタイプには、さまざまな情報を持つ「人」リソースの形式を定義するだけでなく、「兄弟」、「姉妹」、「母」などとの関係を定義するコンテンツタイプがあります。別のPersonリソースへのURIがあります。HTTP動詞を使用し、この「個人」コンテンツタイプを理解しているかなり単純なクライアントは、このAPIをナビゲートできます。特定の人のすべての直接の子孫を検索するとします。
コーマックマルホール

2
@nikこのクライアントは、アクセスしたリソースのコンテンツタイプとHTTP動詞(GET、PUT、DELETEなど)を簡単に理解する必要があり、リソースを取得および更新するこのAPIをナビゲートできます。さらに重要なことに、コンテンツタイプを理解しているクライアントは、URIを介して別のサーバーに完全にジャンプし、そのまま続行できます。彼らは、どのサーバーと通信しているかを気にしません。リソースのコンテンツタイプのみを気にし、それを理解してもしなくてもかまいません。
コーマックマルホール

1
@Nikしたがって、このような状況では、元のコンテンツタイプ(Person v1など)と新しいコンテンツタイプ(Person v2)を理解するサーバーがあります。クライアントはPerson v1のみを理解します。クライアントは、HTTPのAcceptヘッダーを介して、理解するコンテンツタイプをサーバーに伝えます。コンテンツネゴシエーションを使用して、サーバーはクライアントがサポートするものを送信するかどうかを決定します。その場合、コンテンツタイプPerson v1を使用してリソースを返します。この古いコンテンツタイプのサポートを停止するだけで、クライアントに406エラーを送信できます。ただし、できる限りサポートしてみることをお勧めします。
コーマックマルホール

2

動的に生成されたインターフェイスを構築する必要はありません。いいかもしれませんが、必須ではありません。動的インターフェイスを構築できない場合は、リンクを使用するだけで完了です。欠点は、あなたが再びバックエンドにハードリンクされ、何か変更があればクラッシュすることです。

動的レイアウトの使用は非常に簡単です。

links.forEach(function(link) {

  switch(link.rel) {

    case 'deposit':
      showDepositButton();
      break;

    case 'withdraw':
      loadWithdrawForm(link.href);
      showWithdrawButton();
      break;
  }

});

次のようなクライアントコードを節約できます。

if (balance <= 0 && negativeBalanceAllowed === false) {
  showWithdrawButton();
}

クライアントを変更することなく、許可された負のポジションを実装できます(たとえば、お金を借りることによって)。


わずかに強力な例として、銀行は各口座の限度額をクライアント側に伝える必要なく、口座に変動当座貸越限度額を提供できます。
バートヴァンインゲンシェナウ

バランス制限の決定は、必要に応じて複雑にすることができ、クライアントを変更する必要はありません。コンテンツタイプのようなRESTパーツでこれをさらに進めると、さまざまなビューを表示できます。たとえば、アカウントはトランザクションとは異なります。また、興味深いのはオンデマンドのコードです(あまり実装されていません)。これは、たとえば借用見積もりに使用できます。インターフェースに単純な電卓機能を与えることができるため、クライアントは計算用の入力を実装するだけで済みます。バックエンドから最新の状態になります。
リュックフランケン

2
ただし、通常、顧客は撤回できない理由を知る必要があるため、ENUMまたはStringを別個のフィールドでクライアントに送信する必要がありますreason。これがまだ必要な場合はcanWithdraw、アクションへのリンクの代わりに別のブールフィールドを単純に送信しないのはなぜですか?別の利点は、クライアントに触れることなくアクションのURLを変更できることです。しかし.. URLを変更する理由は何ですか?ほとんどの場合、セマンティックやパラメーター、または要求/応答の形状なども多少変更されます。そのため、クライアントを変更する必要があります。だから、私はまだそれを取得しません-HATEOASのポイント。
ルスランステルマチェンコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.