web-dev-qa-db-ja.com

インターフェイスは別のパッケージに配置する必要がありますか?

私は、多くのコンポーネントと依存関係を持つ、かなり大きなプロジェクトに取り組んでいるチームは初めてです。コンポーネントごとに、そのコンポーネントの公開されたインターフェイスが配置されるinterfacesパッケージがあります。これは良い習慣ですか?

私の通常のプラクティスは常にインターフェースであり、実装は同じパッケージに入れます。

71
kctang

インターフェイスと実装の両方を配置することは一般的な場所であり、問​​題ではないようです。

たとえば、Java API-ほとんどのクラスには、同じパッケージに含まれるインターフェースとその実装の両方があります。

Java.util パッケージ:

SetMapListなどのインターフェイスが含まれていますが、HashSetHashMapArrayListなどの実装もあります。

さらに、Javadocは、ドキュメントをInterfacesクラスとClassesに分離するため、これらの条件で適切に動作するように設計されていますパッケージの内容を表示するときに表示します。

膨大な数のインターフェイスがない限り、インターフェイス専用のパッケージを持つことは、実際には少し過剰かもしれません。しかし、そうするためだけにインターフェースを独自のパッケージに分離するのは悪い習慣のように思えます。

インターフェイスの名前を実装と区別する必要がある場合、インターフェイスを識別しやすくするための命名規則を使用できます。

  • インターフェース名の前にI。を付けます。このアプローチは、.NETフレームワークのインターフェースで使用されます。 IListがリストのインターフェースであることを伝えるのはかなり簡単です。

  • -able接尾辞を使用します。このアプローチは、Java APIなど、ComparableIterable、およびSerializableをいくつか挙げてください。

89
coobird

どの言語でも、同じパッケージにそれらをまとめるのは問題ありません。重要なことは、外の世界にさらされているものと、それが外からどのように見えるかです。実装が同じパッケージ内にあるかどうかは誰も知りませんし、気にしません。

この特定のインスタンスを見てみましょう。

1つのパッケージにすべてのパブリックのものがあり、パブリックに公開されていない別のパッケージにプライベートのものがある場合、ライブラリのクライアントには1つのパッケージが表示されます。公開されたものを含むパッケージにプライベートなものを移動するが、パッケージ内からそれらを公開しない場合、クライアントはまったく同じものを見ます。

したがって、これには正当な理由のないルールの匂いがあります。公に見えるものに影響を与えずに、公に見えるものに基づいて決定を下すことです。

とはいえ、特定のインスタンスで、インターフェースと実装を別々のパッケージに分割することをお勧めする場合は、すぐに実行してください。念頭に置いてこれを行う理由は、パッケージが巨大であるか、標準実装の代わりにリンクしたい代替実装があることです。

18
Curt J. Sampson

OSGiなどの多くのフレームワークでは、ほとんど必要です。これにより、jarレベルではなくパッケージでの疎結合が促進されると思います。

10
javamonkey79

さまざまなパッケージにインターフェイスを配置するための1つの議論は、製品またはサービスの消費者に配布できる「api」jarを作成する方が簡単だということです。インターフェイスと実装を一緒に使用してこれを行うことは完全に可能ですが、異なるパッケージにある場合はスクリプトを作成する方が簡単です。

7
Cameron Pope

はい、特定の実装を公開せずにインターフェイスを公開できるため、非常に良い方法です。ただし、外部インターフェイスを公開する必要がない場合は、インターフェイス定義を実装と同じパッケージに入れることに問題はありません。

5
Paul Sonier

実用的なソフトウェアエンジニアリング:ケーススタディアプローチは、インターフェイスを個別のプロジェクト/パッケージに配置することを提唱しています。

この本で説明しているPCMEF +アーキテクチャには、次の原則があります。

  1. 下方依存の原則(DDP)
  2. 上方通知原則(UNP)
  3. 近隣コミュニケーション原則(NCP)
  4. 明示的な関連付けの原則(EAP)
  5. サイクル除去原則(CEP)
  6. クラス命名原則(CNP)
  7. 知人パッケージの原則(APP)

原則#3および#7の説明は、なぜそれが良いアイデアであるかを説明しています。

近隣通信の原則では、パッケージは近隣のパッケージとのみ直接通信できることを要求しています。この原則により、システムが相互通信オブジェクトの非圧縮ネットワークに分解されないことが保証されます。この原則を実施するために、非隣接オブジェクト間でのメッセージの受け渡しでは委任を使用します(9.1.5.1項)。より複雑なシナリオでは、知人パッケージ(セクション9.1.8.2)を使用してインターフェイスをグループ化し、遠方のパッケージを使用するコラボレーションを支援できます。

Acquaintance Packageの原則は、Neighbor Communication Principleの結果です。知人パッケージは、オブジェクトがメソッド呼び出しの引数で具体的なオブジェクトの代わりに渡すインターフェースで構成されます。インターフェイスは、任意のPCMEFパッケージに実装できます。これにより、依存関係の管理を単一の知人パッケージに集中させながら、隣接していないパッケージ間の通信を効果的に可能にします。知り合いパッケージの必要性はセクション9.1.8.2で説明されており、PCMEFのコンテキストで次に説明します。

このリンクを参照してください: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf

5
Kenci

私が作業する場所でこれを行います(つまり、あるパッケージにインターフェイスを配置し、別のパッケージに実装を配置します)。これから得られる主な利点は、実装間で簡単に交換できることです。

3
hhafez

私はプロジェクトでこれを行っていますが、これらの理由のためにうまく機能しています:

  • 個別にパッケージ化されたインターフェイスと実装は、さまざまなタイプのMapまたはSetとは異なるユースケース用です。ツリー(Java.util.tree.Map、Java.util.tree.Set)専用のパッケージを用意する理由はありません。これは単なる標準のデータ構造なので、他のデータ構造と組み合わせてください。ただし、非常にシンプルなデバッグインターフェースとかなり本番のインターフェースを備えたパズルゲームを扱っている場合、フロントエンドの一部としてcom.your.app.skin.debugとcom.your.appがあります。 .skin.pretty。これらは異なることをするため、これらを同じパッケージに入れません。同じパッケージ内にある場合、2つの非公式の名前空間を作成するために、いくつかのSmurfNamingConvention(DebugAttackSurface、DebugDefenceSurface、PrettyAttackSurfaceなど)に頼るでしょう。

  • 別のパッケージにある関連するインターフェイスと実装を見つける問題の私の回避策は、パッケージの命名構成を採用することです。例えば。 com.your.app.skin.frameworkにすべてのインターフェイスを含めることができ、パッケージツリーの同じレベルにある他のパッケージが実装であることを知っています。欠点は、これが型破りな慣習であることです。正直なところ、私はこのコンベンションが6か月後にどれほど良いかを見ます:)

  • 私はこのテクニックを宗教的に使用しません。特定の実装でのみ意味をなすインターフェースがあります。私はそれらをフレームワークパッケージに固執しません。 40個の異なる実装クラスを作成するようには見えないパッケージがあるので、気にしません。

  • 私のアプリケーションはguiceを使用しており、非常に多くのインターフェースを持っています。

一般に、プログラム設計の質問には長所と短所があり、万能の答えはありません。なぜあなたはこのテクニックを小さな200行のプログラムで使うのでしょうか?他のアーキテクチャの選択を考えると、私の特定の問題に対してそれは理にかなっています。 :)

2
Moray Jaundice

私はそれほど多くのJavaの経験はありませんが、インターフェースを実装する具体的なクラスを持つアセンブリが将来の拡張を可能にするため、これをC#/。NETの良い習慣として行うのが好きです。仲介業者の工場またはWebサービスのシナリオでは有線でプロキシされるため、クライアントに至るまで配布されません。

2
Jesse C. Slicer

私は通常、インターフェイスを実装に配置しますが、なぜそれらを別々にしたいのかをある程度理解できます。たとえば、インターフェイスに基づいてクラスを再実装したい場合、インターフェイスだけでなく、実装にjar/lib/etcが必要になるとします。それらを別々にすると、「ここにそのインターフェイスの実装があります」と言うだけで完了します。私が言ったように、私は何をすべきかではありませんが、なぜ一部の人が望んでいるのかを見ることができます。

1
Matt_JD

私は同じパッケージでそれらを好む。インターフェイス専用のパッケージを作成しても意味がありません。これは、インターフェイスのプレフィックスとサフィックス(たとえば、Javaの「I」、「Impl」など)を単純に愛するチームにとっては特に冗長です。

一連のインターフェイスをパブリックAPIとして公開する必要がある場合は、それらを完全に独立したプロジェクトに保持し、代わりにプロジェクトの依存関係を作成する方が合理的です。しかし、それはすべて、私が思う状況の好みと利便性に要約されます。

0
aberrant80

OSGiフレームワークの場合は、実装パッケージを非表示にしつつパッケージ全体を簡単にエクスポートできるように、OSGiフレームワークでは異なるパッケージにある方が良いことに注意することが重要だと思います。

0
jkabugu

プロジェクトを反映するパッケージにそれらを入れてください。インターフェイスと実装が同じプロジェクトの一部である場合、それらを組み合わせることは問題ありませんが、APIを記述している場合、他の誰かがプロジェクトに関連するパッケージ名を選択する可能性があります。

一般に、同じプロジェクトの場合は、インターフェイスを実装とは別のパッケージに保持してもメリットはありません。混乱している場合は、インターフェイスの配置に関係なく、他のパッケージの命名の問題がある可能性があります。

0
Rog