ソリッドの理解:依存性反転原理



依存反転原理は何か?
依存性反転原理は,コンポーネントの拡張性とゆるやかに結合した構成要素を保証するためのソフトウェア設計と開発の標準的な誘導規則の一つである.
簡単に言うと、依存関係の反転原理は、具体的な実装ではなく抽象化に依存する必要があると述べています.

システム結合とは何か
システム結合は、システム内の他の項目に1つの項目の制約状態として定義される.結合は文脈情報で起こります.例えば、エアコンでは、これらの構成要素が冷却システムの全体を構成するので、圧縮機は内部冷却冷媒および冷却機構に結合されると言われている.

緊密結合対疎結合成分?
結合は、2つのタイプであることができます:きつくカップリングとゆるい結合.これらは特定のコンポーネント/モジュールの代わりにシステムがどのように反応するかを示します.
前の例では、空気状態の冷却機構が圧縮機に「しっかり結合」された場合、他の会社によって作られたコンプレッサの代替は、冷却機構を完全に壊す可能性が高い.これは密結合コンポーネントシステムの一例である.緊密に結合されたコンポーネントには、具体的な、ハードコード化された実装があります.
ゆるい結合は上記の例の全くの反対です、システムが同じ機能のうちの1つであるが、異なる構成/実装の代わりに、システムがこれらとして働くのを確実にします.

今のコード例を見てみましょう
前からのアナロジーで次のように簡単なエアコンクラスを定義します.
class CompressorV1 {
  constructor() {
    console.log("Compressor V1");
  }

  setup() {
    // perform some necessary setup task
  }

  turnOn() {
    this.setup();
    // function code
  }
}

class AirConditioner {
  private compressor: Compressor = new CompressorV1();

  constructor() {}

  public powerOn() {
    this.compressor.turnOn();
  }
}
Compressorv 1オブジェクトは、このエアコンクラスの直接依存です.新しい変更が我々の類似物によってなされることになっていたならば、それは新しいコンプレッサータイプで動くために機能性を広げる方法を持たないので、これはエアコンクラスを壊します.依存性インバージョン原理を実装することなく、新しいコンプレッサー圧縮機V 2がエアコンに導入された場合、コードの将来のスナップショットになります
class CompressorV2 {
  constructor() {
    console.log("Compressor V2");
  }

  setup() {
    // perform some necessary setup task
  }

  turnOn() {
    this.setup();
    // function code
  }
}

class AirConditioner {
  private compressor: Compressor = new CompressorV1();
  private compressor2: CompressorV2 = new CompressorV2();

  constructor(private activeCompressor = 1) {}

  public powerOn() {
    if (activeCompressor == 1) {
      this.compressor.turnOn();
    } else {
      this.compressor2.turnOn();
    }
  }
}
その問題は突然明らかになる.
このコードは、エアコンディショナークラス内のコア依存性であるさまざまなコンポーネントを追加することによって、あまりスケーリングされません.そして、たとえコンポーネントが交換を必要としないとしても、このように他のブロックを使用することは生産コードに良くありません.コードの実行中に決定分岐が発生すると、実行が遅くなります.

制御の反転
上記の例から、エアコンプレッサーオブジェクトのインスタンス化と管理を担当するクラスがあります.これは、新しいコンプレッサーが導入されるたびに、新しいコンプレッサー型をサポートするためにエアコンクラスを変更する必要があります.
しかし、別の角度から見てみましょう.エアコンクラスがコンプレッサーオブジェクトのライフサイクルを処理させる代わりに、我々はエアコンのためにそれを扱う抽象的なコンプレッサーインターフェースを定義します.このインターフェースのiCompressorと名付けます(フロントにIを追加するだけではインターフェイスの命名規則です).
なぜインターフェイス、あなたが尋ねる?インターフェイスは、実際に実装せずに、特定の種類の関数を定義することができます.このように、我々は「セットアップ」と「Turnon」の宣言を持っているが、それの定義でないコンプレッサーのインターフェースを定義します.
interface ICompressor {
  setup(config?: any): any;
  turnOn(): any;
}
各コンプレッサークラスは、このインターフェイスを実装します.結果のコード:
class CompressorV1 implements ICompressor {
  constructor() {
    console.log("CompressorV1 is in system");
  }

  setup(config?: any): any {
    // perform the very same setup tasks in this interface function
  }

  turnOn(): void {
    // same function code
  }
}

class CompressorV2 implements ICompressor {
  constructor() {
    console.log("Compressor V2 is in system");
  }

  setup(config?: any): any {
    // perform the same necessary setup task
  }

  turnOn(): void {
    // same function code as before
  }
}
さらに、エアコンクラスは、このエレガントなインターフェイスデザインでよりきれいに見えます:
class AirConditioner {
  constructor(private compressor: ICompressor) {}

  public powerOn() {
    this.compressor.turnOn();
  }
}
我々が現在我々のプログラムを走らせることになっているならば、これはそれがどのように見えるかです
class Main {
  static main(args: string[]): Number {
    const ac: AirConditioner = new AirConditioner(new CompressorV1());
    ac.powerOn();
  }
}
我々が今したことは、コントロールの反転として知られています.このプロセスはコンプレッサークラスのエアコンの依存性を取り除く.一般化するために、より高いレベルのモジュール(エアコンディショナークラス)が、より高いレベルの抽象化(ICompressor)を導入することによって、下位レベルモジュール(compressorv 1/compressorv 2クラス)に依存する依存性制御フローを反転させました.

もう一つの例
さて、上記のエアコンケースでは、複雑な挙動が導入されることは珍しくありません.仮に、3種類目のコンプレッサーが登場し、このタイプのコンプレッサーをACSでサポートする必要があるとします.しかし、このコンプレッサーのセットアッププロセスは少し異なります.完全にオフラインのセットアッププロセスを持っていた最初の2つのタイプとは異なり、この1つは、コンプレッサーを有効にする前に圧縮機システムリソースの監視のために設定する必要があるリモート接続モジュールを持っています.
したがって、第3のコンプレッサーは、セットアップタスクが完了する前に終了する非同期要求に依存しているので、内部のセットアップ動作が異なります.
現在、より高いレベルの不備を使用して実装のおかげで、コンプレッサーのこの新しいタイプは非常に簡単に私たちのエアコンで統合することができます.我々は、単に次の方法でもう一つのコンプレッサークラスを実装します、しかし、今度は、turnon機能はasync機能として実行されます.これは、インターフェイスとして完全に有効な変更であり、関数のシグネチャについてのみ機能し、関数がどのように実装されるかについては決して心配しません.
class SmartCompressor implements ICompressor {
  constructor() {
    console.log("Smart Compressor is in system");
  }

  loadConfiguration(): any {
    //function to load connection configuration
  }

  setup(config?: any): Promise<any> {
    // perform the same necessary setup task
  }

  async turnOn(): void {
    const configObject = loadConfiguration();
    try {
      await this.setup(configObject);
      // function code to turn on compressor
    } catch (err) {
      // catch error if connection fails
      console.log(err.message);
    }
  }
}
コンプレッサーを設定するプロセスは、今回は非常に異なりますが、依存関係の逆転は、この新しい追加は、私たちのシステムの完全な再反復を必要としません(我々は、我々はエアコンのクラスにこの時間をタッチする必要がない方法に注意してください)、このように我々の時間と健全性の喪失を節約.このシステムは,依存性反転原理の助けを借りて疎結合システムに変換された.

結論
要約すると、これは依存関係の反転原理がどのように実装され、実装しようとするのかです.どのように、なぜゆるく結合されたアーキテクチャは、この原理を支持しているのか、そして、なぜそれがS . O . L . I . Dソフトウェア設計原則のリストを作ったのかをはっきりと見ることができます.