1

同僚とコーディングスタイルの競合が発生しました。我々は両方のインターフェースから始め、言う:インターフェイスの実装とインターフェイスの提供

interface IMessageList { 
    void AddMessage(IMessage message); 
    void RemoveMessage(IMessage message); 
} 

私はインターフェイスは、私はそれをクラスを実装していますで使用する方法:

// Method 1 
class SomeClass : IMessageList { 
    private IList<IMessage> messages = new List<IMessage>(); 
    public AddMessage(IMessage message) { 
     messages.Add(message); 
    } 
    public RemoveMessage(IMessage message) { 
     messages.Remove(message); 
    } 
} 

私の同僚が何をするかは、しかし、これです:

// Mehod 2 
interface IMessageListProvider { 
    IMessageList MessageList { get; } 
} 
class MessageList : IMessageList { 
    // An implementation similar to the above 
} 
class SomeClass : IMessageListProvider { 
    private IMessageList messageList = new MessageList(); 
    public MessageList { get { return messageList; } } 
} 

彼は、Microsoftのコードからこの方法をプログラムするためのアイデアを得たと言いますが、私の研究では、私は、これは「プラグ可能なシングルトンのMicrosoft固有の形式である「プロバイダ」のパターンのように聞こえることがわかりました"しかし、私の同僚は実際にそれを実際に使っていることはありません。これは彼が一般的にインターフェイスで動作する方法です。また、適切なコンテキストでもプロバイダパターンに批判的な人々が見つかりました:http://blog.ploeh.dk/2011/04/27/ProviderIsNotAPattern.aspxhttp://www.colourcoding.net/blog/archive/2009/07/29/microsofts-provider-pattern-a-bad-idea-carried-out-to-perfection.aspx。第1の方法と同様

::だから、ここでは、プロバイダパターン自体のより具体的な問題を脇に設定するには、私は上記のコードだけを見ると、賛否両論ある

長所:

  • 1つの契約(IMessageList)のみを定義して使用し、IMessageListの使用は他の抽象に依存しません。
  • 一つが容易派生型でIMessageListメンバをオーバーライドしbase.AddMessage介してベースの実装にアクセスすることができるので、それは拡張可能である、等

短所:

  • インターフェースの多くを実装するクラスこの方法は多くの方法で終了し、名前の競合はより簡単に発生します。
  • 多くのクラスがインターフェイスメソッドを実装して転送している場合、インターフェイスにメンバーが存在する数だけフォワーダが存在します。
  • SomeClassIMessageList関連コンポーネントと他のコンポーネントの間にカプセル化はありません。

    長所:第2の方法として

  • 多くのクラスがIMessageListProviderを実装し、転送している場合には、唯一の方法は、それぞれでオーバーライドする必要があります。
  • IMessageListの実装は、より緩やかな結合を維持してSomeClassのままになります。

短所:この方法は、単にそれをカプセル化していない、複雑さを隠しているプロバイダの多くを実装

  • は、私たちが定義した実質的な契約ですが、コードはほとんどIMessageListProviderを通過しなければならないので、IMessageListだけを使用することはほとんどありません。私たちの抽象化は別の抽象化に依存しています。
  • IMessageListIMessageListProviderを同時に実装することはできません。なぜなら、 'IMessageList'メソッドにアクセスするには2つの方法があり、1つは間違っている可能性があるからです。これは、定義している型に制限を設けていますが、これらの両方のインタフェースを実装してもコンパイラエラーは発生しません。
  • base.MessageListを呼び出すと、私たちにオブジェクトが与えられるだけなので、IMessageListの動作を簡単に上書きすることはできません。代わりに、基本クラスが使用しているオブジェクトのサブクラスを返すようにオーバーライドする必要があります。

私の方法では、IMessageListのメンバーを上書きすると、誰もがIMessageListを使用するために起こることがわかります。彼の方法では、IMessageListProviderを使用するクラスの抽象ファクトリを配置する必要があります。そのため、派生型を送信して、必要なものを実装することができます。しかし、これは単純な多型に戻るための長い道のりです。インタフェースが必要となる。また、オーバーライドが非常に難しいので、IMessageListの実装を1つだけ使用することに私たちを固定するようです。しかし、具体的な実装が1つしかない場合は、なぜインターフェイスの集まりですか?私たちは契約(IMessageList)から始めましたが、今では別の抽象化(IMessageListProvider)に依存しています。これは基本的に1つのタイプ(MessageList)私たちの元来の抽象化したコンセンサス。

要するに、私は彼の方法から悪い匂いがするが、彼は2つの間の選択は単なるスタイルの違いであると断言している。私はこれについて他の意見を見つけることができるかどうかを調べるためにたくさんの調査をしましたが、パターン固有のプロバイダのものを思いついただけなので、どれくらいうまく適用できるかはわかりません。だから私はコミュニティがインターフェースを実際にインターフェースを実装するのと比べてプロパティゲッターとして提供するこの一般的なスタイルについて何を考えているのか不思議です。

// Compromise 
class SomeClass : IMessageList { 
    private struct MessageList : IMessageList { 
     private IList<IMessage> messages = new List<IMessage>(); 
     public AddMessage(IMessage message) { 
      messages.Add(message); 
     } 
     public RemoveMessage(IMessage message) { 
      messages.Remove(message); 
     } 
    } 
    private readonly messageList = new MessageList(); 
    public AddMessage(IMessage message) { 
     messageList.Add(message); 
    } 
    public RemoveMessage(IMessage message) { 
     messageList.Remove(message); 
    } 
} 

これは、しかし、上記のようにインターフェースを破壊することなく、彼はSomeClassIMessageListの実装間望んでカプセル化を実現:私の同僚への妥協案として

私はこのような何かを示唆しました。あるいは、 MessageListは、他のクラスがそれを使用できるように内部または公的にすることができます。しかし、 MessageListは常に便利な形で転送されるべきであり、実際には返されないという私の信念です。その結果、実際にはインタフェースの実装となり、抽象化を妨害します。

答えて

0

私がここから見ているところでは、特に吸うことのない依存性注入フレームワークを使用している場合、IMessageListProviderの必要性は見当たりません。 xxxProviderがある場合は、 "提供された"オブジェクトがプロバイダクラスのロジックによって異なる場合に発生します。ここでIMessageListProviderを必要とするため有効の理由です:実行時にIMessageListを構築または取得

  1. は高価であり、その構造はできるだけ遅く延期されなければなりません。
  2. 実行時にIMessageListProviderの実装に含まれるロジックによって選択する必要があるIMessageListのさまざまな実装があります。

あなたの説明から、どちらも真実ではないようです。これはcargo cult programmingの明確な例で、IMessageListProviderの消費者がLaw of Demeterに違反するように強制します。

+0

あなたの答えをありがとう、ありがとう!ありがとう!でも私はちょうど "tl; dr"を私の質問にしたいと思っています。 – user875215

関連する問題