分離の 2 つの方法

カーソン・グロス

REST 建築スタイルを他のネットワークベースのスタイルから区別する中心的な特徴は、コンポーネント間の統一インタフェースの強調です。汎用性のソフトウェア工学原則をコンポーネントインタフェースに適用することで、全体的なシステムアーキテクチャは簡素化され、インタラクションの可視性が向上します。実装は、提供するサービスから分離され、独立した進化が促進されます。

-ロイ・フィールディング、https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5

このエッセイでは、Web アプリケーションのコンテキストにおける 2 つの異なるタイプの分離について見ていきます

アプリケーションレベルでは、ハイパーメディア API はフロントエンドとバックエンドを緊密に結合することがわかります。この事実にもかかわらず、驚いたことに、ハイパーメディア API は実際には変化に対してより回復力があります。

#カップリング

カップリングは、システムの 2 つのモジュールまたは側面が高度な相互依存関係を持つソフトウェアシステムの性質です。ソフトウェアのデカップリングとは、関連しないモジュール間のこの相互依存関係を低減し、互いに独立して進化できるようにすることです。

カップリングとデカップリングの概念は、凝集性と密接に(そして逆相関で)関連しています。非常に凝集性の高いソフトウェアは、コードベース全体に広がるのではなく、モジュールまたは概念的な境界内に関連するロジックを持ちます。(関連する概念は、独自の発案である動作の局所性です)

広義には、経験豊富な開発者は分離された凝集性の高いシステムを目指しています。

#JSON データ API - アプリケーションレベルの分離

今日、Web アプリケーションを構築する一般的なアプローチは、JSON データ API を作成し、React などの JavaScript フレームワークを使用してその JSON API を消費することです。このアプリケーションレベルのアーキテクチャ上の決定により、フロントエンドコードとバックエンドコードが分離され、モバイルアプリケーション、サードパーティのクライアント統合など、他のコンテキストで JSON API を再利用できます。

これはアプリケーションレベルでの分離であり、分離の決定と実装はアプリケーション開発者自身が行うためです。JSON API は、2 つのソフトウェアパーツ間の「ハード」インターフェースを提供します。

お気に入りの例を使用して、https://example.com/account/12345GETエンドポイントを持つ銀行のシンプルな JSON を考えてみてください。この API は次の内容を返す可能性があります

HTTP/1.1 200 OK

{
    "account": {
        "account_number": 12345,
        "balance": {
            "currency": "usd",
            "value": -50.00
        },
        "status": "overdrawn"
    }
}

このデータ API は、Web アプリケーション、モバイルクライアント、サードパーティなど、任意のクライアントによって消費できます。したがって、特定のクライアントからは分離されています。

#実務における JSON API による分離

ここまで、順調です。しかし、この分離は実際にはどのように機能するのでしょうか。

エッセイデータとアプリケーション API の分割: その先へでは、次の引用が見つかります

最近、私の仕事の最悪の部分は、フロントエンド開発者向けの API を設計することです。会話は必然的に以下のように進みます

Dev – それで、この画面にはデータ要素 x、y、z などがあります。{x: 、y: 、z: }のレスポンス形式でAPIを作成していただけますか?

私 – かしこまりました

Jean-Jacques Dubray - https://www.infoq.com/articles/no-more-mvc-frameworks

この引用は、フォークを使って結合から逃れたとしても (あるいは、この場合では、JSON API を使用しても)、Web アプリケーションに特化した JSON API エンドポイントに対する要求を通じて、結合が戻ってきたことを示しています。この種の要求は、フロントエンドとバックエンドのコードを再結合することになります。JSON API は、一般的な JSON Data API を提供するのではなく、フロントエンドのニーズのための特定の API を提供するのです。

さらに悪いことに、これらのフロントエンドのニーズは、アプリケーションが進化するにつれて頻繁に変更されることが多く、そのため JSON API の変更が必要になります。他の非 Web アプリケーションクライアントが元の API に依存するようになった場合はどうでしょうか。

この問題は、Web アプリケーションと非 Web アプリケーションクライアントの両方をサポートする多くの JSON Data API 開発者が直面する「バージョニング地獄」につながります。

#ソリューション: GraphQL

この問題に対する解決策の 1 つとして考えられるのが、GraphQLを導入することです。これにより、さらに表現力豊かな JSON API を作成できます。つまり、API クライアントのニーズが変わるたびに頻繁に変更する必要がなくなります。

これは上記の解決策に対処するための合理的なアプローチですが、問題がないわけではありません。私たちが The API Churn/Security Trade-off エッセイで概説しているように、最大の課題はセキュリティです。

明らかに Facebook は ホワイトリストを使用して、GraphQL によって引き起こされるセキュリティ問題に対処していますが、GraphQL を使用している多くの開発者は、それに伴うセキュリティの脅威を理解していないようです。

#別のソリューション: アプリケーションと一般的なデータ API の分割

この記事で Max Chernyak が推奨するもう 1 つの方法 Don’t Build A General Purpose API To Power Your Own Front End は、2 つの JSON API を構築することです。

これは、Web アプリケーションのフロントエンドと、それをサポートするバックエンドコードの間にある本質的な結合と思われるものを解決するための実用的なソリューションであり、汎用 GraphQL API に伴うセキュリティ上のトレードオフとは無縁です。

#ハイパーメディア - ネットワークアーキテクチャの結合解除

では、ハイパーメディア APIがどのようにソフトウェアの結合を解除するかを考えてみましょう。

上記で見た、https://example.com/account/12345に対する同じGETに対する潜在的なレスポンスを検討します。

HTTP/1.1 200 OK

<html>
  <body>
    <div>Account number: 12345</div>
    <div>Balance: $100.00 USD</div>
    <div>Links:
        <a href="/accounts/12345/deposits">deposits</a>
        <a href="/accounts/12345/withdrawals">withdrawals</a>
        <a href="/accounts/12345/transfers">transfers</a>
        <a href="/accounts/12345/close-requests">close-requests</a>
    </div>
  <body>
</html>

(はい、これは API レスポンスです。たまたまハイパーメディア形式のレスポンス、つまりこの場合は HTML になっています。)

ここでは、アプリケーションレベルで、このレスポンスは「フロントエンド」に密結合する以上のことはありません。実際、API レスポンスはリソースのデータだけでなく、ユーザーにこのデータをどのように表示するかについてのレイアウト情報も指定するため、「フロントエンド」そのものなのです。

このレスポンスにはハイパーメディア制御、この場合はエンドユーザーが選択してこの ハイパーメディア駆動アプリケーションが提供するハイパーメディア API のナビゲーションを続けることができるリンクも含まれます。

それで、この場合の結合解除はどこにあるのでしょうか?

#REST と均一インターフェイス

このケースでは、カプリングは低レベルで発生しています。ネットワークアーキテクチャレベル、つまりシステムレベルで発生しています。ハイパーメディアシステムは、ハイパーメディアクライアント(Webの場合はブラウザ)をハイパーメディアサーバーから分離するように設計されています。

これは主に REST の Uniform Interface 制約、特に Hypermedia As The Engine of Application State (HATOEAS) を使用することによって実現されます。

このスタイルのカプリングにより、高いアプリケーションレベルでのより密接なカップリング(本質的なカップリングである可能性があります)が可能になると同時に、全体的なシステムのカプリング解除の利点を維持できます。

#実際におけるハイパーメディアを使用したカプリング解除

実際には、この種のカップリング解除はどのように機能するのでしょうか。自分たちの銀行から他の銀行にお金を振り込む機能と、口座を閉鎖する機能を削除したいとしましょう。

今、このGETリクエストに対するハイパーメディア応答はどうなるでしょうか。

HTTP/1.1 200 OK

<html>
  <body>
    <div>Account number: 12345</div>
    <div>Balance: $100.00 USD</div>
    <div>Links:
        <a href="/accounts/12345/deposits">deposits</a>
        <a href="/accounts/12345/withdrawals">withdrawals</a>
    </div>
  <body>
</html>

この応答では、これら 2 つのアクションのリンクが HTML から削除されていることがわかります。ブラウザは新しい HTML をユーザーに表示するだけです。古い API を使用しているクライアントはほとんどいません。API はハイパーメディア内にエンコードされ、ハイパーメディアを通じて検出されます。

つまり、クライアントを壊すことなく、API を劇的に変更できます。

この柔軟性が REST フルなネットワークアーキテクチャ、特に HATOEAS の要諦です。

おわかりのように、フロントエンドとバックエンドの間のアプリケーションレベルのカップリングが大幅に強化されているにもかかわらず、REST フルなUniform Interface の側面によってネットワークアーキテクチャのカップリングが解除されることで、柔軟性が向上しています。ハイパーメディアシステム

#ひどい(データ)APIだ!

多くの人は、確かに、このハイパーメディア API は Web アプリケーションに柔軟性があるかもしれないが、汎用 API としてはひどいものだと反論するでしょう。

これはまったくその通りです。このハイパーメディア API は、特定の Web アプリケーションに合わせて調整されています。この HTML をダウンロードして、構文解析して、そこから情報を抽出するのは面倒でエラーが発生しやすいでしょう。このハイパーメディア API は、適切なハイパーメディアクライアントによって使用される、より大きなハイパーメディアシステムの一部としてのみ意味を持ちます。

これが、データとアプリケーション API の分割: さらなる調査でハイパーメディア API とともに汎用 JSON API を作成することを推奨する理由です。Web アプリケーションの柔軟性をハイパーメディアで活用しつつ、モバイルアプリケーション、サードパーティアプリケーションなどに汎用 JSON API を提供できます。

(ただし、ハイパーメディアベースのモバイルアプリケーションも適切な選択である可能性があることに注意する必要があります!)

#結論

本エッセイでは、2 種類のカプリング解除について検討しました。

そして、ハイパーメディアベースのアプリケーションで発見されるアプリケーションレベルのカップリングがより緊密であるにもかかわらず、変化により柔軟に対処するのはハイパーメディアシステムであることがわかりました。

</>