web-dev-qa-db-ja.com

依存関係の逆転が、低レベルのモジュールでの密結合と再利用性の低下につながらないことを確認するのに苦労しています

私は自分の仕事のためにやったプロジェクトをリファクタリングしていて、SOLIDの原則を適用してアーキテクチャをよりクリーンにするようにしています。依存関係の逆転の原則に関する問題に遭遇しました。解決できないようです。

依存関係の逆転の原則では、上位レベルのモジュールは下位レベルのモジュールに依存するべきではなく、どちらも抽象化に依存するべきであると述べています。私のプログラムのコンテキストでは、プログラムを実行するAppクラスと、オブジェクトと周囲の温度を取得するために使用しているMLX90614赤外線センサーのクラスがあります。初期リリースでは、アプリはMLX90614ドライバークラスに直接依存していました。しかし、これはDIPに違反しています。

//MLX90614.h
class MLX90614
{
    public:
    readTemperature();
}

//app.h
#include "mlx90614.h"
class App
{
   public:
   //do stuff
   private:
   MLX90614 sensor;
}

これを修正するために、Appで使用され、MLX90614で実装される抽象的なISensorインターフェイスを作成することにしました。

//sensor.h
class ISensor
{
    public:
    virtual public readTemperature() = 0;
}

class MLX90614 : public ISensor
{
    //implements ISensor
}

//app.h
#include "sensor.h"
class App
{
    private:
    ISensor *sensor;
}

これはアプリから具体的な依存関係を取り除くために機能しますが、この方法にはDIPのチュートリアルではカバーされていないように見えるいくつかの問題が見つかりました。

1つ目は、MLX90614に新しい依存関係が導入されたことです。つまり、まったく別のアプリケーションでドライバーを再利用したい場合は、可能性が高いので、インターフェイスシステム全体をドラッグする必要があります。これは、「バナナが欲しいが、ゴリラと森を手に入れる」という問題のようです。このコードを再利用して別のライブラリとして公開すると、アプリケーション固有のISensorインターフェイスは使用できなくなります。これは、パッケージデザインが悪いように思えます。

さらに悪いことに、多くのチュートリアルでは、DIPに完全に準拠するには、より高いレベルのコンポーネントでインターフェイスをパッケージ化する必要があると具体的に述べています(これは2番目のルールを満たします)。これにより、MLX90614がより高いレベルのAppモジュールと密に結合され、ドライバーを再利用するために、インターフェイスだけでなくアプリケーション全体をドラッグする必要があるため、事態はかなり複雑で面倒になりますそれと一緒に!これはプログラミングの悪夢のようです!

//mlx90614.h
#include "app.h"
class MLX90614 : public ISensor
{
    //Implements ISensor, but now is completely dependent on the App module,
    //which we definitely don't want.
}

//app.h
class ISensor
{
    //do stuff
}

class App
{
    private:
    ISensor *sensor;
}

このため、依存関係の逆転がシステムに害を及ぼすよりも効果があるかどうかはわかりません。下位レベルのモジュールを高度に再利用できるようにしたい場合、実装にまったく関係のない上位レベルのシステム全体に依存させるのは奇妙に思えます。そして、ほとんどのシステムでプログラミングした低レベルのライブラリが、高レベルの実装よりも常にはるかに再利用可能であることを考えると、依存関係の逆転がどのように役立つかはわかりません。

6
Ryan Mullin

依存関係の逆転がどのように役立つかはわかりません。

これは、まだ何にも使用できていないためです。

DIPが機能し、複雑さを増し、何もしないという事実を嘆いています。現在のところ、これらはすべて真実です。あなたが理解していないのは、DIPが今ではないということです。それは変化についてです。

DIPを使用すると、センサーコードを一緒にドラッグしないとセンサーコードを再利用できないことになると予測しています。ここにあなたは後ろ向きの関係があります。

MLX90614のインターフェイスISensorは作成しません。センサーの有無に依存するアプリ用に作成し、MLX90614かそれ以外かは関係ありません。アプリがMLX90614について直接知る前は、センサーから必要なものを詳細に示すインターフェースを単に公開しています。それが何であれ。それはいい。アプリはMLX90614よりも長持ちします。

別のアプリでMLX90614を使用するときは、別のインターフェイスを使用する必要があります。他のアプリに必要なものを示すもの。 MLX90614がすべてを行うわけではありません。それがインターフェース分離の原則です。

何らかの理由で、MLX90614をエクスペリエンスに影響されずにアプリ間で移動できるようにする必要があると主張しました。多分あなたはそれを図書館に置くことを考えています。もしそうなら、私は Object Adapter Pattern を検討して、アプリ全体で頑固にならないようにします。

enter image description here

バナナで好きなことをしてください。しかし、ゴリラは何を食べたいのか、どのようにそれを剥がすかを決めるものです。

13
candied_orange

複数のアプリケーションによって消費される複数のセンサーおよびによってISensorを実装したい場合は、次のようになります。

enter image description here

この時点で、2つの選択肢があります。

1)ISensorをSensor 1およびSensor 2と一緒にパッケージ化します。1つ以上のセンサーを使用するすべてのアプリケーションが、そのパッケージを参照します。

2)ISensorを単独でパッケージ化します。これで、すべてのアプリケーションとすべてのセンサーパッケージがISensorのパッケージを参照します。アプリケーションは、使用したい具体的な実装も参照する必要があります。

1
17 of 26