3

私は最近、データ ストアの実装をラップする API を設計し、他の開発者がこの API を使用してデータにインデックスを付け、キーワードに基づいてデータベースをクエリできるようにしました。Jaroslav Tulach が、パラメーターを追加する必要があるときに API インターフェイスを変更し続けることを回避できると述べたため、クエリ メソッドで Response/Reply パターンを使用していました (Practical API Design の 97 ページ)。他の開発者は、メソッドのオーバーロードを使用する方が優れたアプローチであると主張しています。設計で 2 つの異なるアプローチを使用した経験を共有できますか? 以下は、私と他の開発者との会話です。

私: API の進化に伴い、より多くのパラメーターを API インターフェイスに追加できるため、応答/応答パターンはクリーンな方法のように見えます。インターフェイスに 10 以上のオーバーロード メソッドがあると、他の開発者が混乱する可能性があります。彼らはどの方法を使用するかをどのように判断しますか?

別の開発者の主張: API の進化に伴い、パラメーターを追加し続けるべきではありません。API インターフェイスにパラメーターを追加し続ける場合は、API 設計に問題があります。その結果、オーバーロードするメソッドの数が少なくなり、開発者が煩わしくなることはありません。また、Java フレームワークでは、多数のオーバーロード メソッドの実装がよく見られます。

私: 以前のバージョンの API との後方互換性を簡単に管理できます。インターフェイスを変更する必要はありません。インターフェイスを変更すると、他の開発者の既存のコードが壊れます。

他の開発者の主張: 実装を変更して引数を追加すると、他の開発者は新しい API に基づいてコードを更新する必要があります。新しい引数がオプションの場合、わざわざ追加する必要はありません。

4

3 に答える 3

2

別の開発者の主張: API の進化に伴い、パラメーターを追加し続けるべきではありません。API インターフェイスにパラメーターを追加し続ける場合は、API 設計に問題があります。

それはかなりナイーブな見方です。すべての API は進化します。それは私たちが望んでいるものではありませんが、仕様を最初から正しく完成させた顧客/クライアントを教えてください...

リクエスト/リプライ型の引数は、下位比較が非常に簡単にできるので優れています。API の 2 番目のバージョンが作成されたら、既存のコードを変更する必要もありません。

このことを考慮:

public class GetUserRequest
{
    string Id;
}

public class GetUserReply
{
  string Id;
  string DisplayName;
}

そして API インターフェイス:

public class MyCoolApi
{
    GetUserReply GetUser(GetUserRequest request);
}

(API の構造は実装の種類によって異なります)

ここで、新しい要件があります。すべてのユーザーに年齢を含める必要があります。

オープン/クローズの原則に従い、応答クラスを継承します。

public class GetUserReply2 : GetUserReply
{
  string Id;
  string DisplayName;
  int Age;
}

すべてのバージョン 1 ユーザーはバージョン 1 をデシリアライズし、バージョン 2 ユーザーはバージョン 2 としてデシリアライズします。

入力パラメーターについても同様です。サービス (API) クラスを、Request クラスのバージョンに応じてバックグラウンドで正しい API 実装を呼び出すだけのプロキシ (プロキシ パターン) にすることができます。

結論: Request/Reply は、メソッドのオーバーロードに対してより多くの柔軟性を提供します。

于 2012-10-10T08:27:47.907 に答える
1

私たちは比較していると思います

   invoke( int param1, string param2) { ... }

   invoke ( string param3, int param4, int param5) { ... }

など、すべての有効なパラメータの組み合わせ

   invoke(requestClass theRequest)

このように使用されます

   request.set("param1", value);
   request.set("param2", value);
   invoke(request);

ここにはいくつかのトレードオフがあります。

要求アプローチの欠点は、呼び出し元がパラメーターの無効な組み合わせを提供でき、コンパイル時の警告を受け取らないことです。エラーは実行時まで検出されません。

しかし、成長し続けるインターフェースは完全に手に負えなくなる可能性があり、必要な方法の数で組み合わせ爆発を起こす可能性があります。

SQLは、非常に豊富なリクエストの例と見なすことができます。パラメータごとのメソッドのオーバーロードアプローチよりも、適切に構造化されたクエリ言語またはリクエストオブジェクトの方が望ましい場合があることは明らかです。

私の個人的な経験則:10の異なるオーバーロードされたメソッドに向かっている場合は、リクエストオブジェクトを検討する必要があります。

于 2012-10-10T08:14:49.680 に答える
0

本質的な違いはなく、固有の複雑さを軽減することもできません。もちろん、どちらを選択してもサポートするユースケースをいつでも見つけることができます。特定の問題領域を知らなければ、抽象的な原則に基づいてお気に入りを選ぶことはできません。

ただし、今日は簡単なソリューションを選択することをお勧めします。「将来の変化」を心配する必要はありません

于 2012-10-09T18:35:13.970 に答える