27

(その価値については.NETのコンテキストで)

私は継承を使用しない傾向があり、インターフェイスはめったに使用しません。唾を吐き出して以来、インターフェイスが最高のものだと考えている人に出会いました。彼はそれらをどこでも使用します。私はこれを理解していないので、それに続く質問です。インターフェイスの理解度を確認したいだけです。

どこでもインターフェイスを使用している場合、将来を予測できると思います。アプリの要件が明確になり、アプリで何も変わることはありません。私にとって、特に開発の初期段階では、インターフェースが邪魔になります。このアプリは、その生涯を通じて非常にダイナミックです。インターフェイスからメンバーを削除または追加する必要がある場合、多くのものが壊れます。上記の人は、新しいメンバーを処理するために別のインターフェースを作成したと言っています。何も壊れません。

構成じゃないの?インターフェイスなしでコンポジションを使用しないのはなぜですか? より柔軟に。

インターフェイスからメンバーを削除する必要がある場合、彼はどのように処理しますか? 基本的に彼はしません。物事が壊れるだけで、影響を受けたすべての領域を確認して修正できるので、それは素晴らしいことです. 関連するすべてのコード パスがどこにあるかをよりエレガントに把握する代わりに、力ずくでクラスの一部を切り取る必要がありますか?

私はソフトウェア アプリケーションをグラフと考えています。完全なグラフは最悪のケースで、n(n-1)/2 になります。これは、すべてのクラスがすべてのクラスと対話することを意味します。ややこしい蜘蛛の巣。n-1 は最高であり、コミュニケーションの厳密なヒエラルキーです。新しい必要なメンバーを補うためだけに別のインターフェイスを追加すると、グラフに頂点が追加されます。これは、より多くのエッジと n(n-1)/2 方程式のより強力な実現を意味します。インターフェイスのないコンポジションは、ミックスインに似ています。一部のクラスのみが特定のメソッドを使用します。インターフェースを使用すると、すべてのクラスはメンバーを必要としない場合でもメンバーを使用することを余儀なくされます。コンポジション/ミックスイン アプローチでは、新しい不要なエッジは追加されません。

4

15 に答える 15

40

インターフェイスは、クラスにメソッドの使用を強制しません。それらは実装クラスにすべてのメソッドを実装するように強制しますが、それは別の問題です。

インターフェイスがAPIを実装から分離する方法が好きです。確かに、これはアクセス修飾子を使用して行われますが、インターフェイスによって明確になります。さらに重要なことに、インターフェースはモックを容易にします。つまり、インターフェースを実装する前でも、インターフェースに依存するクラスを単体テストできます。

そして、はい、これは私がしばしば単一の本番実装しかないインターフェースになってしまうことを意味します。私はテスト可能性を得たので、それは私の見解では問題ではありません。

一方、私はすべてのクラスのインターフェースを作成しているわけではありません。私は、オブジェクトが本質的にサービスを提供しているインターフェイス(認証、データアクセスなど)を作成するのが好きです。プレーンなデータオブジェクト(重要な動作がある場合でも)は、インターフェイス、IMEの観点からはそれほど有用ではありません。

于 2009-02-20T16:54:03.473 に答える
7

ウィキペディアによると、

業界でのポリモーフィズムの主な用途(オブジェクト指向プログラミング理論)は、異なるタイプに属するオブジェクトが、それぞれが適切なタイプ固有の動作に従って、同じ名前のメソッド、フィールド、またはプロパティの呼び出しに応答する機能です。プログラマー(およびプログラム)は、オブジェクトの正確なタイプを事前に知る必要がないため、実行時に正確な動作が決定されます(これは遅延バインディングまたは動的バインディングと呼ばれます)。

それがインターフェースをとても便利にしている理由です。

「上の男は、新しいメンバーを処理するために別のインターフェースを作成すると言っています。何も壊れません。」

私はここで推測しているだけですが、この男は古い学校のCOMのバックグラウンドから来ているようです(もちろん、私は間違っている可能性があります!)。私がこれまでに取り組んだすべてのコードについて、次のようなものを見たことがあります。

  • IWidgetManager
  • IWidgetManager2
  • IWidgetManager3

これは、インターフェイスを操作するための良い方法ではありません。私の経験では、両方の極端な状況を見てきました。新しいメンバーが追加されるたびに新しいインターフェイスが作成されるようにインターフェイスを変更すること、またはインターフェイスをまったく使用せず、高度な結合に悩まされる製品を使用することへの恐れです。あなたは良いバランスを見つける必要があります。インターフェイスを変更することは、必ずしも世界の終わりではありません。

あなたが取り組んでいるプロジェクトのサイズはどれくらいですか?比較的小規模なプロジェクトの場合、インターフェイスの利点を理解するのは難しい場合があります。一方、それが数十万行のコードを含み、多くのモジュールで構成されているプロジェクトである場合、その利点ははるかに明白になります。

于 2009-02-20T16:54:11.663 に答える
5

インターフェイスには多くの便利な状況があります。さまざまなクラスにまたがるクラスに特定の動作を追加する必要がある場合は、インターフェイスに最適なタイミングです。良い例はIDisposableインターフェースです-あなたはあなたが終わったとき、タイムリーに消える必要があるいくつかのリソースを持っています。データベース接続ですか?窓の取っ手ですか?関係ない。

もう1つの例は、まだ存在していないオブジェクトへのインターフェイスなど、実装方法が本当にわからない場合です。おそらく、オブジェクトはライブラリのクライアントによって提供されるか、制御されていない完全に異なるモジュールによって実装される必要があります。基本的に、クラスで使用可能なメソッドのコントラクトを設計できます。

そうは言っても、私は必要な場所でのみそれらを使用します。通常のクラスでそれを行うことができる場合、またはそれが特定のオブジェクトに固有のものである場合は、それをクラスにします。他の人が言っているように、すべてのクラスにインターフェイスを使用することにはいくつかの利点がありますが、それは非常に余分なオーバーヘッドであるため、それでまともな純利益は見られません。ほとんどの場合、依存関係ができるだけ少なく、フラットで幅が広いようにクラス構造を設計しました。

要約:劇的に異なる方法で実装される共通の機能が必要な場合は、インターフェースがまさに必要なものです。

于 2009-02-20T17:13:10.727 に答える
3

インターフェイスは、抽象化への依存関係を維持するのに役立ちます。

インターフェイスを使用するコードはインターフェイスにのみ依存するため、詳細に人為的な依存関係がないことがわかります。これにより、バグを「修正」したりリファクタリングしたりするときに何を壊すべきか、何を壊すべきでないかが正確にわかっているため、将来コードを変更する限り、多くの自由が得られます。

私の意見では、それは優れたコード設計の本質です。

于 2009-02-23T20:51:46.137 に答える
2

依存関係についてです。必要に応じて、具象型ではなくインターフェイス型にコードを依存させたい。たとえば、複数の具象型があり、すべてが同様の動作を実行するが、実装が異なる場合があります。コード ベースに、これらの複数の具象型または 1 つのインターフェイスへの依存関係を持たせたいですか? 変更を加える必要がある場合、コード ベースはどの程度柔軟になると思いますか?

コンポジションを使用してパブリック メンバーを使用したくないという点については、不要な依存関係をカプセル化しているだけだと思います。合成を使用する場合は、具象型の代わりにインターフェース型を合成することで、依存関係を大幅に減らします。

より良い説明については、制御の反転に関する文献を調べてみてください。

于 2009-02-21T15:56:50.717 に答える
2

「上の人は、新しいメンバーを処理するために別のインターフェイスを作成すると言っています。何も壊れません。

構成じゃないの?インターフェイスなしでコンポジションを使用しないのはなぜですか? もっと柔軟に。」

「このジョブを実行するために、これらの機能をすべてこの 1 つのオブジェクトに継承します」というように、継承の観点から合成を考えているようです。これはコードの書き方が悪いです。「超高層ビルを建てたいから、設計図の書き方から基礎の打ち方、照明の取り付け方まで、あらゆる仕事を覚える…」と言っているようなものです。

代わりに、それぞれが 1 つのタスクを実行する個別のオブジェクトという観点から構成を考えてください。複雑な仕事をするために、これらの個別のオブジェクトに頼って個々のタスクを実行できるようになりました。超高層ビルを建設するために、建築家や建設作業員を雇うようなものです。彼らがそれぞれの仕事をどのように行っているかを詳細に知る必要はありません。コードでは、これはオブジェクトに依存関係を注入して、継承ではなく複雑なタスクを実行することを意味します。

では、インターフェイスはどこに収まるのでしょうか? それらは個々のオブジェクト間の契約です。それらにより、個々の具体的な実装を気にする必要がなくなります。それらを使用すると、同じ責任を共有するが実際には異なる実装を持つ可能性がある一連のオブジェクトで共通言語を話すことができます。インターフェイスは、タスクを実行するオブジェクトへの抽象化になります。ハンマーを持ったすべての人がどのように機能するかを知る必要はありません。HitNail() の方法を知っているだけです。

単一の責任を持つ多数の小さなクラスを含む複雑なコード システムを構成し始めると、特定のクラスの具体的な実装に過度に依存し、そのクラスが変更され始めると、深刻な問題が発生する可能性があることがすぐにわかります。 ... したがって、具体的な実装に依存する代わりに、インターフェイス (抽象化) を作成します。そして、「JobX をどのように行うかは気にしません。ただ、それを行うだけです」と言います。

テスト、モッキングなど、インターフェースには他にも利点があります...しかし、それらはインターフェースにコーディングする理由ではありません。その理由は、仕様に依存せず、相互に高度に結合されたコード システムを作成するためです。これが、グラフを考える頭脳で、多数の具象クラスを互いに結合することを恐れる必要がある理由です。これらのクラスの 1 つを変更すると、波及効果が生じるためです。

具象クラスではなく抽象化に結合すると、結合が制限されます。あなたは、「私は、私たちが合意した契約にのみ結合するつもりであり、それ以外は何もしません」と言います. また、そのコントラクトを実装するクラスがそのタスクを完了するための内部的な方法を変更しても、非コントラクト プロパティまたはメソッドに依存していないため、気にする必要はありません。合意された契約のみに依存しています。

于 2009-02-20T17:48:35.603 に答える
2

インターフェイスをいつ使用するか、およびその使用方法を理解したい場合は、本をご覧になる必要があると思います: Head First Desing Patterns

これは、インターフェイスの何がすごいのかを理解するのに本当に役立った本です。

この本を読む前からインターフェースとは何かは知っていましたが、いつ使うべきか全くわかりませんでした。

于 2009-02-20T17:54:29.303 に答える
1

インターフェイスは、依存性注入とIoCフレームワークのコンテキストで私にとって最も理にかなっています。一連の動作(メソッド)を定義し、インターフェースの実装を通じてそれらの動作を「保証」できるという考えが気に入っています。これで、単一のアセンブリと構成ファイルの更新で、まったく新しい機能を既存のシステムにプラグインできます。

インターフェイスを効果的に設計するには、かなりの事前計画が必要です。大規模なシステムやフレームワークのコンテキストで最も役立つことがわかりました。それらが有用であるとき、それらは本当に有用です。私のお気に入りのいくつか:

  • IComparable(オブジェクトを互いに比較する方法を決定します)
  • IQueryable(LINQ誰か?)
  • IDisposableusingステートメントを手元に置いてください)
于 2009-02-20T17:05:48.657 に答える
0

インターフェイスの主な用途は、実行時にコードを切り替えることができるように、実装のバリエーションを許可することです。これを行う理由/理由はいくつかあります。

過去には、システム内のすべてのクラスにインターフェイスが必要であると主張する人もいましたが、これはやり過ぎとして広く認識されています。現在、クラスのインスタンスがシステム操作の一部として(状態を表すために)変更できる場合にインターフェースが使用されます。ストラテジーやコマンドなどのGoFパターンがこの使用をキャプチャするか、システムの一部をテストのために置き換える必要があります(つまり、依存関係)。注入)。開発者がテスト駆動開発の慣行に従っている場合、主要なインフラストラクチャオブジェクトにはインターフェイスがあります。これにより、テストでこれらのオブジェクトの「モック」を作成して、システムの制御フローをテストできます。このインターフェースの使用とリスコフの置換原則(オブジェクト指向設計の原則の1つ)の間には関係があります。

呼び出し元が利用できるものにあまり関係のないインターフェースのさらなる使用法は、マーカーインターフェースです。これは、メタデータをクラス定義に関連付ける方法です。これは、システムがオブジェクトを表示する方法に影響を与える可能性があります(たとえば、オブジェクトをシリアル化できるようにする)、または単にドキュメントとして機能する可能性があります。

于 2009-06-04T20:16:11.607 に答える
0

これについては、.net 設計ガイドラインを参照してください: http://msdn.microsoft.com/en-us/library/ms229013.aspx

インターフェイスを使用する理由はたくさんありますが、間違った理由で使いすぎていることもよくあります。インターフェイスは、値の型を操作する場合にはるかに柔軟性があり、コレクションなどを操作する場合に非常に便利ですが、自分のプロジェクトのクラス階層を設計するときは、常に最初に単純さを考えようとします。インターフェイスはしばしば (不必要に)より複雑な状況。

私の経験則では、意味のあるすべての BCL インターフェイスを実装し、実際に非常に価値のあるものを提供する場合にのみ、独自のインターフェイスを設計に追加します。IWidgetManager、IWidgetManager2 などを使用する代わりに、抽象クラス WidgetManager を使用し、必要に応じて具体的なメソッドを実装したいと考えています。

于 2009-02-21T02:15:21.017 に答える
0

そこにトップダウンの設計手法が書かれていると思います。
あなたはそれをする必要はありませんが、時々彼は本当に助けてくれます.

于 2009-02-20T17:20:26.217 に答える
0

私たちは、カスタム UI 要素のインターフェイスを多用します。各要素は、特定のメソッドが別の要素に存在することを期待しています (そして、インターフェイスがその存在を強制します)。

于 2009-02-27T07:01:16.600 に答える
0

この人は、インターフェイスへのプログラミングの概念を誤解しているように聞こえます。.Net/Javaのキーワードのみを使用したプログラミングや、C++ の純粋仮想関数のみを使用したクラスを使用したプログラミングを指すものではありませんinterface。その原則で参照されるインターフェースは、低レベルのものをカプセル化した高レベルの構造です。システムの。掛け算と同様に、それ自体に特定の数の繰り返しを追加するという考えがカプセル化されています。しかし、3 * 2 と言うとき、それが 3 + 3、2 + 2 + 2、または (2 + 2) + 2 のいずれであってもかっこ内の部分がキャッシュされます。それから6を受け取る限り。

実際のところ、インターフェイスの概念は、多くの GoF パターンの場合と同様に、これらの 1 つまたは複数の組み合わせinterfaceによって満たすことができます。キーワードの種類が曖昧さで水を曇らせているabstract classだけです。interface

それはおかしいです。StackOverflow のエピソード #38 を中心としたコメントなどは、この男の考え方によるものと思われます。

于 2009-02-23T20:36:28.343 に答える