バージョン管理API


9

APIベースでサポートされている大規模なプロジェクトがあるとします。このプロジェクトには、エンドユーザーが使用できるパブリックAPIも含まれています。

場合によっては、プロジェクトをサポートするAPIベースに変更を加える必要があります。たとえば、APIの変更や新しいメソッドを必要とする機能を追加したり、APIとの間でやり取りされるオブジェクトの1つまたはオブジェクトの1つの形式を変更したりする必要がある機能を追加する必要があります。

パブリックAPIでこれらのオブジェクトも使用していると仮定すると、パブリックオブジェクトもこれを実行するたびに変更されます。これは、クライアントが解析コードを機能させるために同一のままであるAPIオブジェクトに依存する可能性があるため望ましくありません。(咳C ++ WSDLクライアント...)

したがって、解決策の1つは、APIをバージョン管理することです。しかし、APIの "バージョン"と言うと、これは、変更されたメソッドシグネチャごとに重複したメソッド呼び出しを提供するだけでなく、APIオブジェクトをバージョン化することも意味しているように思えます。したがって、APIのバージョンごとにプレーンな古いclrオブジェクトを作成しますが、これもまた望ましくないようです。そして、たとえこれを行っても、膨大な量の重複したコードが作成されることになるため、各オブジェクトを最初から構築することはありません。むしろ、APIはベースAPIに使用しているプラ​​イベートオブジェクトを拡張する可能性が高いですが、追加のプロパティが想定されていないときにパブリックAPIでも使用できるため、同じ問題が発生します。

では、この状況に通常適用される正気とは何でしょうか?Git for Windowsなどの多くのパブリックサービスがバージョン管理されたAPIを維持していることは知っていますが、バージョン管理されたさまざまなメソッドや入出力オブジェクトをカバーする膨大な量の重複コードなしでこれをサポートするアーキテクチャを想像するのに苦労しています。

セマンティックバージョニングなどのプロセスはパブリックAPIのブレークが発生したときに何らかの健全性を提供しようとすることを知っています。問題は、オブジェクトが分離されていない場合、多くの変更またはほとんどの変更でパブリックAPIを解除する必要があるように見えることですが、コードを複製せずにそれを行うには良い方法がありません。


1
I don't see a good way to do that without duplicating code-新しいAPIは常に古いAPIのメソッドを呼び出すことができ、その逆も可能です。
Robert Harvey、

2
AutoMapperが役に立ちます。残念ながら、各コントラクトの異なるバージョンが必要です。コントラクトによって参照されるすべてのオブジェクトがそのコントラクトの一部であることを忘れないでください。その結果、実際の実装には独自のモデルの単一バージョンが必要であり、単一バージョンをさまざまな契約バージョンに変換する必要があります。AutoMapperは、内部モデルを契約モデルよりもスマートにするだけでなく、ここでも役立ちます。AutoMapperがない場合、拡張メソッドを使用して、内部モデルと契約モデルの間の単純な変換を作成しました。
ジミーHoffa

このための特定のプラットフォーム/コンテキストはありますか?(つまり、DLL、REST APIなど)
GrandmasterB

.NET、MVCおよびWebforms ui、dllクラス。REST APIとSOAP APIの両方があります。
ケース

回答:


6

サードパーティが使用するAPIを維持する場合、変更を加える必要があることは避けられません。複雑さのレベルは、発生している変更の種類によって異なります。これらは出てくる主要なシナリオです:

  1. 既存のAPIに追加された新機能
  2. APIから廃止された古い機能
  3. 何らかの形で変化するAPIの既存の機能

既存のAPIに追加する新機能

これは、サポートする最も簡単なシナリオです。APIに新しいメソッドを追加しても、既存のクライアントを変更する必要はありません。これは、既存のクライアントに対する更新がないため、新機能を必要とするクライアントに対して安全に展開できます。

APIから廃止された古い機能

このシナリオでは、機能が長期的にサポートされないことをAPIの既存のコンシューマーに伝える必要があります。古い機能のサポートを終了するまで(またはすべてのクライアントが新しい機能にアップグレードされるまで)、新旧のAPI機能を同時に維持する必要があります。それが提供されているライブラリである場合、ほとんどの言語には古いメソッドを廃止/非推奨としてマークする方法があります。それが何らかのサードパーティのサービスである場合は、通常、新旧の機能に異なるエンドポイントを設定するのが最善です。

何らかの形で変化するAPIの既存の機能

このシナリオは、変更のタイプによって異なります。入力パラメーターを使用する必要がなくなった場合は、サービス/ライブラリーを更新して、現在余分なデータを無視することができます。ライブラリでは、オーバーロードされたメソッドが、必要なパラメーターが少ない新しいメソッドを内部的に呼び出すようにする必要があります。ホストされたサービスでは、エンドポイントに余分なデータを無視させ、両方のタイプのクライアントにサービスを提供し、同じロジックを実行できます。

既存の機能で新しい必須要素を追加する必要がある場合は、サービス/ライブラリに2つのエンドポイント/メソッドが必要です。クライアントが更新されるまで、両方のバージョンをサポートする必要があります。

他の考え

Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.

ライブラリ/サービスを通じて内部プライベートオブジェクトを公開しないでください。独自のタイプを作成し、内部実装をマップします。これにより、内部の変更を行い、外部クライアントが実行する必要がある更新の量を最小限に抑えることができます。

The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.

サービスであれライブラリであれ、APIはクライアントとの統合ポイントで安定している必要があります。入力と出力が何であるかを特定し、それらを別々のエンティティとして保持するために時間がかかるほど、将来の多くの頭痛の種を節約できます。APIコントラクトを独自の独立したエンティティにし、実際の作業を提供するクラスにマップします。内部実装が変更されたときに節約される時間は、追加のインターフェースを定義するためにかかった余分な時間を相殺するよりも多くなければなりません。

このステップを「コードの複製」と見なさないでください。これらは類似していますが、作成する価値がある別個のエンティティです。外部APIの変更では、ほとんどの場合、対応する内部実装への変更が必要ですが、内部実装の変更によって外部APIが変更されるとは限りません。

支払い処理ソリューションを提供しているとします。あなたはPaymentProviderAを使用してクレジットカード取引を行っています。その後、PaymentProviderBの支払いプロセッサを介してより良いレートを取得します。APIがPaymentProviderAの表現ではなく、タイプのクレジットカード/請求先住所フィールドを公開した場合、インターフェイスは同じままであるため、APIの変更は0です(とにかく、PaymentProviderBがPaymentProviderAで必要とされなかったデータを必要とする場合、どちらかを選択する必要があります両方をサポートするか、PaymentProviderAでより低いレートを維持します)。


この非常に詳細な回答をありがとう。既存のプロジェクトがこれをどのように行ったかを知るために私が精査するかもしれないオープンソースプロジェクトの例を知っていますか?共有メソッドを呼び出す場合は分割する必要があるため、さまざまなPOCO構築コードをさまざまなバージョンのオブジェクトにコピーするだけでこれを実行できるようにするコードを組織化した具体的な例をいくつか見てみたいバージョン付きオブジェクトのオブジェクトを編集できるようにするための共有メソッドの。
ケース

1
I "私の頭の上から任意の良い例を認識していないメートル私はいくつかの時間この週末を持っている場合、私はこれらの事のいくつかを実装する方法を示すためにGitHubの上で投げるためにテストアプリケーションを作成することができます。。
フィル・パターソン

1
トリッキーな部分は、高レベルから、クライアントとサーバー間の結合を最小化しようとする非常に多くの異なる方法があるということです。WCFにはIExtensibleDataObjectと呼ばれるインターフェイスがあり、クライアントからコントラクトにないデータを渡して、ワイヤー経由でサーバーに送信できます。Googleは、システム間の通信用にProtobufを作成しました(.NET、Javaなどのオープンソース実装があります)。さらに、動作するメッセージベースのシステムが多数あります(プロセスを非同期で実行できると仮定した場合)。
Phil Patterson、

削除しようとしているコードの重複の特定の例を(新しいスタックオーバーフローの質問として)示し、コミュニティがどのようなソリューションを考え出すかを確認することは、悪い考えではないかもしれません。一般的な用語で質問に答えることは困難です。したがって、特定のシナリオの方が適している場合があります。
Phil Patterson、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.