8

インターフェースを実装することでコア機能を拡張できるフレームワークを構築しようとしています。以下は、このインターフェースの唖然とした例です。

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

最近、このインターフェイスを変更することにしました(依存するコードを壊してはいけないことはわかっていますが、実際には、このインターフェイスを実装しているサードパーティがまだないため、「やり直し」の機会があります。このインターフェースを正しく実装するため)。

ソフトウェアを正しく機能させるには、このインターフェイスにさらに2つのパラメータを追加する必要があります。私たちが考えている2つの方法は、次のように署名に追加することです。

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, bool p4, DateTime p5);
}

または、このようなパラメータオブジェクトを作成します

public class MyParameters
{
    public bool p4 { get; set; }
    public DateTime p5 { get; set; }
}

そして、次のようにメソッドの最後にそれらを追加します。

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3, MyParameters p4);
}

私は、どちらの方法が「最も」正しい方法であるかについてのある種のガイダンスを探しています。私は両方のカテゴリーで賛否両論を見ることができますが、私の偏見が私を間違った道に導くことを望んでいません。

私の主な関心事のいくつかは次のとおりです。

  • ソフトウェアの拡張性-インターフェースを実装することで、ユーザーがまだ考えていないことを実行できるようにしたい
  • 保守性-理想的には、GetData()の呼び出しを担当するコードに再度触れる必要はありません。
  • クリーンなAPI-サードパーティの開発者を苦しめるために到達したソリューションは必要ありません

この問題のガイダンスを得るためにオンラインでどのような質問をするべきかさえわかりません。答えは「依存する」(p1-p5がGetData()関数の目的にどの程度関連しているかなど)と感じていますが、評価に役立つ質問のリストを誰かに教えてもらえますか?一方のソリューションがもう一方のソリューションよりも優れているかどうか。

関連: 投稿1 投稿2

4

2 に答える 2

2

ずっと行ってみませんか:

public Interface IParameters
{
    string p1 {get; set;}
    char p2 {get; set;}
    double p3 {get; set;}
    bool p4 { get; set; }
    DateTime p5 { get; set; }
}

public interface MyInterface
{
    IData GetData(IParameters p);
}
于 2012-12-19T05:35:17.557 に答える
2

これに答えてみましょう。オプションを評価しましょう:

1)以下のインターフェースの場合

public interface MyInterface
{
    IData GetData(string p1, char p2, double p3);
}

は壊れてます:

a)使用しないでください。その場合は、実装者に強制的に書き直してください。したがって、メソッド定義を変更します。

public interface MyInterface
{
    IData GetData(something else);
}

b)ただし、ユーザーに新しい定義を使用するように促すだけで、最初の定義が廃止されたことをユーザーに通知する新しいオーバーロードを作成できます。

public interface MyInterface
{
    //xml to tell them this is deprecated.
    IData GetData(string p1, char p2, double p3);
    IData GetData(string p1, char p2, double p3, and whatever);
}

あなたの新しい定義については、モデルについて知らなくても誰もが提供できるワンストップソリューションはありませんが、あなたは自分自身に問いかけます、

I)「パラメータ自体を組み合わせると、単一のエンティティを表すことができますか?パラメータを1つ持つことは、現実の世界で何かを意味しますか?」そうであれば、そうします。そうでない場合は、しないでください。このようなジレンマに陥っているときは、そのような抽象的なレベルで考えることに頼るべきだと思います。bool p4クラブとのポイントが何なのかわかりませんDateTime p5。あなたはそれ自体が実生活で何かを表すそれらのパラメータをクラブするべきです。それらの組み合わせが意味をなさない場合は、そのままにしておきます。あなたはそのようなクラブをそのような論理的な考え方に任せることにもっと成功するでしょう。念のために言っておきますが、定義は他のプログラマーに任せています。彼らの仕事を容易にするために、メソッドのシグネチャは非常に論理的である必要があります。

II)クラスは、単にデータのセットを保持するのではなく、より多くのことを実行できますか?ここではクラスをオプションにする必要があります。

III)クラス定義のみを制御する必要があり、その実装は制御する必要はありませんか?その場合は、入力のパブリックインターフェイスを定義し、実装を顧客に任せてください。

IV)私のインターフェースへの将来の変更は、既存の実装を壊してはいけませんか?オーバーロードはあなたの道です。

署名を平らにするか、クラブにするかの2つの選択肢があるとします。

1)クラブなし:

a)コードの削減、別のレイヤーの削減。

b)別のクラスを公開する必要はありません。

2)クラブ付き:

a)関数に入るモデルの理解を深めます-あなたの意図は明確です。

b)新しく形成されたクラスを構築するためのオプションの詳細を追加する必要がある場合は、将来的に簡単に拡張できます。あなたがクラスを持っているとしましょう

class Input {
    string p1; char p2; double p3;

    public Input(string p1, char p2, double p3){
    }
}

とインターフェース

public interface MyInterface
{
    IData GetData(Input p1);
}

ここで、boolやDateTimeなどのオプションの詳細を追加することができます。それらはオプションであるため、コンストラクターに強制する必要はありません。同じコンストラクターを引き続き使用でき、必要に応じてコンストラクターの外部で変更する権限をユーザーに付与できます。

class Input {
    string p1; char p2; double p3; bool p4; DateTime p5;

    public Input(string p1, char p2, double p3){
    }
}

インターフェースは同じでもかまいません。私が言ったように、この種のものを導き出すための推進力は悲しいことにあなたのモデルに依存しています。つまり、グループ化が何かを意味する場合は、それをクラスまたはインターフェイスにします(ロジックを制御するユーザーによって異なります)。

于 2012-12-19T12:29:24.340 に答える