10

これは、ZedShawがずっと前に彼のブログで行った特定のコメントへの応答です。

その後、専門家はコメントなしでバベルの塔を実装し、恐ろしく複雑なモック対応テストを実行し、すべての単一クラスにインターフェイスがあることを確認し、すべてのクラスを「Impl」で終了します。これがベストプラクティスだからです。

私はSpringとGoogleGuiceを同等に使用していますが、これらのフレームワークはImpl後置を使用していますが、控えめに使用していることに気づきました。私のコードでは、モックなどが簡単になると言われているので、どこでもインターフェイスを使用しています。この問題を素朴に理解していますか?(おそらく、モックフレームワークは抽象クラスまたはクラスで動作する可能性があります。わかりません。試したことはありません)具体的な実装では、実装名の前にDefaultという単語を付けるSpring規則を選択しました。

e.g. BottleOpener (interface) is implemented by DefaultBottleOpener (class)

この問題のベストプラクティスは何ですか?

UPDATE1いつでも匿名クラスを返すことができるので、メソッドからインターフェイスを返すと便利だと思います。

4

13 に答える 13

17

それは単なるモック以上のものです。Springの場合、それは動的プロキシとアスペクト指向プログラミングに関するものです。これが、Springがトランザクション、リモーティング、およびすべてのタイプの側面を実行する方法です。

リポジトリやサービスなどにインターフェースを使用していますが、モデルオブジェクトなど、実装が変更される可能性が低いものにはインターフェースを配置していません。

インターフェイスは、APIを実装方法から分離します。実装が変更されない場合、インターフェースはあまり意味がありません。

Zed Shawは素晴らしいライター兼開発者ですが、彼の言うことを一粒の塩で受け止めてください。彼が夢中になっている誇張表現のいくつかは、娯楽的価値のためだと思います。彼はポイントを持っています(「権威であると主張する誰かがそれが「ベストプラクティス」であるとあなたに言うからといって物事をしないでください」)、しかし彼の言い方はそれが劇場の一部です。

于 2010-02-18T02:58:14.070 に答える
6

ベストプラクティスは次のとおりです。

  • 規則を選び、それについて一貫性を持たせます。と
  • すべてにインターフェースを実装させることをやりすぎないでください。
于 2010-02-18T02:57:56.010 に答える
6

『 Interface Oriented Design』という本には、インターフェースについての有用な考え方があります。つまり、インターフェースはプロバイダーではなくクライアントに属しているということです。したがって、特定のクラスをインターフェイスで表す必要があるかどうかを考えるのではなく、特定のクラスが対話する可能性のあるインターフェイスを考えてから、それらのインターフェイスに準拠するクラスを検索または記述します。実装クラスのパブリック機能の長いリストと比較すると、インターフェイスは非常に簡素化されている可能性があります。もちろん、特定のクラスは複数のインターフェイスを実装できます。クラスとインターフェースの間の1対1の対応を探すことは、インターフェースを完全なクラスの表現として考えても、インターフェースについて考える方法としては有用ではありません。

于 2010-02-18T05:43:48.620 に答える
2

すべてのクラスのインターフェースを作成することに利点はありません。それはあなたにたくさんのコードを2回書くことを強制するだけです。

APIと実装を区別するためのインターフェースを作成する必要はないと思います。クラスのパブリック関数とそのシグネチャのリストはAPIです。クラスがAPIの一部ではないworker-bee関数を必要とする場合、それらはパブリックであってはなりません。見えない

与えられたコンテキストで、それが有用な目的を果たすときに、私はインターフェースを作成します。基本的にこれは次のことを意味します。

(a)実際、私の最も一般的な理由は、多重継承を実装/シミュレートすることです。AがBを拡張する必要があるが、Cを受け入れる関数も必要であり、その関数にAを渡したい場合は、BまたはCのいずれかを親クラスではなくインターフェイスにして、AがBを拡張するようにする必要があります。 Cまたはその逆。

(b)ライブラリまたはユーティリティの外部の何か、通常は複数の何かによって実装されるライブラリまたはユーティリティ関数のAPIを作成しているとき。Javaライブラリの「Comparable」インターフェイスはこの例です。ソートユーティリティには、オブジェクトのペアを比較する関数が必要です。プログラムが呼び出し側プログラムで定義されたオブジェクトを使用してsortユーティリティを呼び出す場合、sortユーティリティはそれらを比較する方法を知ることが期待できないため、呼び出し側プログラムは比較機能を提供する必要があります。比較関数のシグニチャは、呼び出し元がそのオブジェクトに実装できるインターフェイスに論理的に組み込まれます。

(c)実装を明らかにせずにインターフェースを公開したい場合。これは独自の理由である可能性がありますが、実際には、通常、別の人またはチームがインターフェイスを実装するためです。

于 2010-02-18T05:03:10.977 に答える
2

これは主に主観的な問題です。最良の応答は、おそらく、コードの単体テストを可能な限り有効にすることができるが、インターフェースの作成が物事の遂行の邪魔にならないようにすることによるものです。コードがすぐにいっぱいになる場合は、それを切り詰めてください。

そうは言っても、400のクラスとそれらのクラス用の400以上のインターフェースがあるコードを見てきました。命名規則が貧弱なコードの山を掘り下げるだけで、私は意欲をかき立てられました。反対に、私はインターフェースのないサードパーティのプロプライエタリライブラリを扱っています。これらのオブジェクトをあざけるのは苦痛になりつつあります。

于 2010-02-18T02:59:04.193 に答える
2

別の共同作業者に「サービス」を提供するクラスには、インターフェースが必要です。目的の動作を実現するために、実装を切り刻んで変更したい場合があります。例として、TwitterサービスをEメールサービスに簡単に置き換えることができます。

'value'オブジェクトを表すクラスは、単一の目的を果たすため、インターフェースを必要としないはずです。テストでは、これらのオブジェクトをモックする必要はなく、オブジェクトグラフのリーフノードを定義するため、直接使用するだけです。

于 2010-02-18T05:35:27.730 に答える
1

SmallTalkでは、実際の実装の前に常にインターフェイスの定義を開始することを「聞いた」のですが、実際には、達成したい目的と設計目標によって異なります...

于 2010-02-18T02:58:19.197 に答える
1

オブジェクトにインターフェースを設定し、オブジェクトがインターフェースを介してのみ相互に通信するようにすることは良いことです。

私はオブジェクトを意味し、本質的に「データ」であるコレクションやその他のものではないことに注意してください。

ただし、クラスに「IClassName」などを実装し、コードベース全体にそのパターンを実装することは、インターフェイスの概念についての理解が不十分であることを反映しています。インターフェイスは通常、「ねえ、これが私が必要とするサービスです」の宣言として、消費クラスによって宣言されるべきです。このように、インターフェースは、世界に対するオブジェクトの単一のビューではなく、2つのオブジェクト間の相互作用を表します。また、各クラスが独自の理想的なインターフェイスを処理しているため、責任を分離するのに役立ち、ドメインロジックを実装ロジックから分離するのに役立ちます。

(編集)

それは本当に間接参照と抽象化の違いについてです。APIに直接一致するインターフェースは、単に間接的なものです。消費者のニーズに直接一致するインターフェースは、消費者が何をしたいのかを宣言し、それがどのように行われるかに関するすべての情報を隠すため、抽象化です。

ZedShawはこれに関する良い記事を持っています。

http://www.zedshaw.com/essays/indirection_is_not_abstraction.html

于 2010-02-18T03:19:22.860 に答える
1

すべての具象クラスをインターフェースの背後に隠すことで、本当にうまくいかないと思います。

余計な場合もありますが、それほど費用はかかりません。

ドメインオブジェクトにインターフェイスを実装させることもできます。利点:

  • クライアントコードから醜い詳細を隠すことができます(たとえば、JPAアノテーション、ORMフレームワークでのみ使用されるセッター)
  • DAOまたはサービスの場合と同様に、抽象化に対してプログラムすることができます。ユーザーの抽象化について考えてみてください。ビジネスロジックは、それらが保存される方法と場所(DBやOSなど)に依存せず、サードパーティのコードを使用する必要がある場合は、アダプターパターンを簡単に使用できます。
于 2010-02-18T04:00:43.700 に答える
1

デザインにもよると思います。依存性注入またはモックオブジェクトテストを使用する場合は、インターフェイスが理にかなっています。また、複数の実装を計画している場合は、動作のコントラクトを記述するためのインターフェイスが必ず必要です。

疑わしい場合は、おそらくアジャイルアプローチを採用しますか?

ビールの栓抜きが必要です

class BeerBottleOpener // life's good

今、ワインボトルオープナーが必要です

class WineBottleOpener // life's still good

少しリファクタリング

interface BottleOpener;
class BeerBottleOpener implements BottleOpener;
class WineBottleOpener implements BottleOpener;
// now living the life!  ;-)

ところで、モックテストには、インターフェイスを必要とするEasyMockを使用しました。クラスをモックでき、より明示的で少し単純なMockitoに切り替えました。

于 2010-02-18T04:37:40.620 に答える
0

インターフェイスで船外に出るのは非常に現実的な可能性です。仮想ディスパッチを使用してすべてのメソッド呼び出しを行うことによる[無視できる]パフォーマンスの低下を無視すると、システムにより多くのオプションが導入されます。実際には、ソフトウェアのデバッグと保護が難しくなる可能性があります。メソッド/関数が古いインターフェース実装者を受け入れる場合、実装者がインターフェースを間違って、あるいは悪意を持って実装した可能性があることを受け入れることにしました。プログラム/ライブラリ/フレームワークがどのようにバリエーションを可能にするかは、設計プロセスの重要な部分です。

于 2010-02-18T03:12:03.480 に答える
0

すべてにインターフェイスを提供する(または、より一般的には未使用になる可能性のある柔軟性を設計する)ことを、オーバーエンジニアリングと呼びます。何かの具体的な実装が複数ある可能性が低い場合、インターフェースは肥大化しています。未使用の柔軟性の構築を回避するコードは理解しやすくなります。これは、実装が1つしかないという事実をインターフェイスが曖昧にすることなく、処理している具体的なタイプがわかり、コードの推論が容易になるためです。

これは、モックに対する私のお気に入りの議論の1つでもあります。これは、「実際の」実装が1つしかないものを複数実装できるなど、コードに人為的な要件を導入します。

于 2010-02-18T03:13:31.220 に答える
0

執着するまで何かをするのは間違っています。これらは単なるツールであり、私たちはマスターです。

于 2010-02-19T23:59:27.407 に答える