1. ホーム
  2. rest

[解決済み] バージョン管理されたAPIのコードベースはどのように管理されていますか?

2022-09-05 11:30:18

質問

私はReST APIのバージョニング戦略について読んできましたが、どれも基礎となるコードベースをどのように管理するかということに触れていないようです。

たとえば、Customer リソースを変更して、個別の forenamesurname フィールドの代わりに、1つの name フィールドの代わりに (この例では、関係する概念を理解しやすいので URL バージョン管理ソリューションを使用しますが、質問はコンテンツ ネゴシエーションまたはカスタム HTTP ヘッダーにも同様に当てはまります)

これでエンドポイントが http://api.mycompany.com/v1/customers/{id} に、また別の互換性のないエンドポイントが http://api.mycompany.com/v2/customers/{id} . 私たちはまだv1 APIに対するバグフィックスとセキュリティアップデートをリリースしていますが、新しい機能開発はすべてv2に集中しています。 どのようにAPIサーバーへの変更を書き、テストし、デプロイすればいいのでしょうか?私は少なくとも2つの解決策を見ることができます。

  • v1 と v2 を別々に開発し、デプロイし、必要に応じてリビジョン コントロール マージを行って、両方のバージョンに同じバグフィックスを適用します。これは、ネイティブ アプリケーションのコードベースで、以前のバージョンをサポートしながら新しいメジャー バージョンを開発する場合の管理方法と同様です。

  • コードベース自体に API バージョンを認識させ、v1 の顧客表現と v2 の顧客表現の両方を含む単一のコードベースを作成するようにします。おそらく、名前空間とルーティングの組み合わせを使用して、リクエストが正しいバージョンによって処理されることを確認します。

ブランチモデルの明らかな利点は、古い API バージョンを削除するのが簡単であることです - 適切なブランチ/タグのデプロイを停止するだけです。統一コードベース(quot;unified codebase")モデルはこの問題を回避しますが、(私が思うに)非推奨のリソースやエンドポイントを必要なくなったときにコードベースから削除するのはずっと難しくなります。単純な正解がありそうもないので、これはおそらく主観的なものだと思いますが、複数のバージョンにわたって複雑な API を維持する組織がこの問題をどのように解決しているかを理解することに興味があります。

どのように解決するのですか?

私は、おっしゃる両方の方法を使用したことがあります。この 2 つのうち、私は、サポートするユースケースにおいて、よりシンプルな 2 番目のアプローチを支持します。つまり、バージョン管理のニーズが単純であれば、より単純なソフトウェア デザインを使用します。

  • 変更回数が少ない、複雑度の低い変更、または変更頻度の低いスケジュール
  • コードベースの残りの部分とほとんど直交する変更: 公開 API は、コードの分岐を必要とせず、スタックの残りの部分と平和的に存在することができる (その用語の定義がどのようなものであれ)。

このモデルを使用して、非推奨のバージョンを削除することが過度に困難であるとは思いませんでした。

  • 良好なテスト カバレッジにより、廃止された API と関連するバック コードを削除することで、リグレッションがない (まあ、最小である) ことを確実にしました。
  • 適切な命名戦略 (API バージョンのパッケージ名、またはより醜い API バージョンのメソッド名) により、関連するコードの場所を特定するのが簡単だった
  • 複数の API をサポートするためにコアとなるバックエンドシステムを修正することは、非常に慎重に検討する必要があります。ある時点で、バックエンドのバージョン管理のコスト (上記の "excessive" のコメントを参照) は、単一のコードベースの利点を上回ります。

最初のアプローチは、共存するバージョン間の競合を減らすという観点からは確かに単純ですが、別々のシステムを維持するオーバーヘッドは、バージョンの競合を減らすという利点を上回りがちでした。とはいえ、新しいパブリックAPIスタックを立ち上げて、別のAPIブランチでイテレーションを始めるのは至って簡単なことだった。もちろん、世代交代はすぐに始まり、ブランチはマージ、マージの競合解決、その他で混乱するようになった。

第三のアプローチは、アーキテクチャ層です。Facadeパターンの変種を採用し、APIを、適切なFacadeインスタンスと対話する、バージョン管理された公開レイヤーに抽象化し、次に、独自のAPIのセットを介してバックエンドと対話します。Facade(私は以前のプロジェクトでAdapterを使用しました)はそれ自身のパッケージになり、自己完結し、テスト可能で、バックエンドや互いに独立してフロントエンドのAPIを移行することが可能になります。

これは、フルネーム/姓/名の例のように、APIのバージョンが同じ種類のリソースを、異なる構造的表現で公開する傾向がある場合に機能します。バックエンドの計算が異なる場合、少し難しくなります。例えば、"私のバックエンド サービスは、公開 API v1 で公開された複利計算を誤って返しました。したがって、バックエンドでその計算を更新して、v2まで適用させることはできません。幸いなことに、このようなことは滅多にありません。現実的には、RESTful API の消費者はバグとバグの互換性よりも正確なリソース表現を好みますし、たとえ理論的にべき乗である GET というリソースに対する非破壊の変更であってもです。

最終的な決断を聞いてみたいものです。