web-dev-qa-db-ja.com

パッケージインターフェース-カップリングと再利用性

意図

パッケージは、単一の機能を適切に実行するように設計する必要があります。

理想的には、これは、それらが高度にモジュール化され、異なるパッケージが共通のインターフェースを共有することを保証するだけで「プラグイン」できる必要があることを意味します。

ただし、パッケージ間に何らかの依存関係を作成したり、醜い「統合クラス」または「共通インターフェイス」パッケージを作成したりせずに、これを行う方法がわかりません。

コンセプトの例

ドメインレベルのセマンティクスに行き詰まりすぎたくないので、少し工夫された単純なイベントロガーの例を使用します。

パッケージA

[〜#〜] xyz [〜#〜]を実行し、カスタムロギングオブジェクトを提供できるようにします。

ロガーが有効であることを確認するために、パッケージAにはPackageA\Logインターフェースが含まれています。ロギングオブジェクトがclassXコンストラクターに提供されると、ロガーオブジェクトがPackageA\Logを実装していない場合、例外がスローされます。

パッケージB

[〜#〜] abc [〜#〜]を実行し、カスタムロギングオブジェクトを提供できるようにします。

ロガーが有効であることを確認するために、パッケージBにはPackageB\Logインターフェースが含まれています。ロギングオブジェクトがclassAコンストラクターに提供されると、ロガーオブジェクトがPackageB\Logを実装していない場合、例外がスローされます。

パッケージC

パッケージAおよびパッケージBのログを提供する統合ロガー。 。etal。

アプリケーション内のすべてのパッケージに汎用ロガーを提供するために構築されたLogオブジェクトが含まれています。

現在の次善のアイデア:

1。クラスPackageC\Logにどちらのインターフェースも実装しませんが、インターフェースのバリエーションごとにクラスを拡張します(例:PackageC\Loggers\PackageA extends PackageC\Log)。

問題:より多くのメンテナンスが必要であり、インターフェースする新しいパッケージごとにPackageCを変更する必要があることを意味します。

2。インターフェースPackageA\LogおよびPackageB\LogをクラスPackageC\Logに直接実装します。

問題:PackageCが別のプロジェクトで再利用された場合、PackageAまたはPackageBは存在しません。

Common Interfacesパッケージを作成し、すべてのパッケージにパブリックインターフェイス用にそれらのインターフェイスを実装/要求させます。

問題:非常に実用的ではなく、作成したパッケージを統合する場合にのみ機能します。サードパーティとのやり取りはありません。

質問

PackageC\LogはどのようにしてPackageA\ClassXPackageB\ClassAの両方の要件を満たすことができますか?

実際には、PackageAPackageBに必要なインターフェースはおそらく同じではないため、この質問は通常、より複雑です。では、これを解決する唯一の方法はオプション1(上記で定義)ですか?つまり、インターフェイスを実装するパッケージは統合クラスを作成する必要がありますか?

1
Marvin

ロギングコンポーネントの実際の操作は、それを使用する他のコンポーネント/クラス/ ...とほぼ同じであるため、パッケージCから1つのインターフェイスのみを提供することは理にかなっています。

パッケージAおよび/またはパッケージBがロギングを機能させるために他のインターフェースを必要とする場合、 アダプターデザインパターン を使用してPackageA\LogのインターフェースをPackageC\Logに接続することは理にかなっています。およびPackageB\LogからPackageC\Log

インターフェイスPackageC\Logは汎用のままですが、事前定義されたロギングインターフェイスを接続できます。

1