+8

依存性注入のマジックを解き放つ:初心者向けガイド ・「Dependency Injection (DI)」

JavaScriptスキルを次のレベルに上げたいですか? コードをもっと整理しやすく、テストしやすく、モジュール化しやすい方法を学びたいですか? 幸運なことに、今日は依存性注入の世界に没頭しましょう!

依存性注入は、コード内の異なるオブジェクトの関係を管理するための強力なデザインパターンです。 コードをより柔軟にし、理解しやすくするのに役立ちます。 これは、シリアスなJavaScript開発者にとって必須のテクニックです。

この記事では、簡単な日本語で依存性注入の基本を解説し、それがどのようにコードをより強力にするかを例を用いて説明します。さらに、各例に対してコードサンプルを掲載し、実際にどのように動作するかを理解するのを手助けします。

それでは、早速始めて、依存性注入の力を引き出す方法を学びましょう!

依存性注入とは

依存性注入は、オブジェクトがその仕事をするために必要なものを提供する方法です。これらのものは依存関係と呼ばれます。 例を見てみましょう。

class Dog {
  constructor() {
    this.barkSound = 'woof';
  }
  
  bark() {
    console.log(this.barkSound);
  }
}

const myDog = new Dog();
myDog.bark(); // Output: 'woof'

例えば、「Dog」というクラスがあり、「bark」というメソッドで音を出します。音は「barkSound」というプロパティに保存されます。「barkSound」プロパティはコンストラクタメソッドの中で作られていることに注意してください。ハードコーディングされており、変えたい場合はクラスの中に入って変更する必要があります。

これは小さなプロジェクトで問題にならないかもしれませんが、プロジェクトが大きくなり、このようなクラスが多くなった場合は、メンテナンスするのが難しくなります。また、barkメソッドをテストする場合は、毎回新しいインスタンスを作成する必要がありますが、それは負担になります。

依存性注入

この問題を解決するために、依存性注入がどのように役立つのか見てみましょう。

class Dog {
  constructor(barkSound) {
    this.barkSound = barkSound;
  }
  
  bark() {
    console.log(this.barkSound);
  }
}

const myDog = new Dog('woof');
myDog.bark(); // Output: 'woof'

今度は、「barkSound」プロパティをクラスの中で作らず、コンストラクタに引数として渡します。これにより、犬の鳴き声を変更することができ、クラスを変更することなく、barkメソッドをテストすることができるようになります。

依存性注入は、多様な方法で使用できる強力なパターンです。ここでは、どうやって使うかの例を見せます。

1. テスト

前に述べたように、依存性注入はコードに対する自動テストを書きやすくします。 依存関係のテスト版を作成し、テストしたいオブジェクトに渡すことができます。 このようにすることで、依存関係をテストすることなく、オブジェクトをテストすることができます。

class Dog {
  constructor(dog) {
    this.dog = dog;
  }

  bark() {
    console.log(this.dog.barkSound);
  }
}

class SilentDog {
  constructor() {
    this.barkSound = "Meo Mew";
  }

  bark() {
    console.log(this.barkSound);
  }
}

const testDog = new Dog(new SilentDog());
testDog.bark(); // Output: 'Meo Mew'

2. 設定

依存性注入を使用して、アプリケーションの設定をコードから分離することができます。 このようにすることで、コード自体を変更せずにアプリケーションの振る舞いを変更することができます。

class Dog {
  constructor(config) {
    this.barkSound = config.barkSound;
    this.color = config.color;
  }

  bark() {
    console.log(this.barkSound);
  }
}

const config = {
  barkSound: "woof",
  color: "brown",
};

const myDog = new Dog(config);
myDog.bark(); // Output: 'woof'
console.log(myDog.color); // Output: 'brown'

3. プラグイン:

依存性注入を使用して、ユーザーがコードを変更せずに新しい機能をアプリケーションに追加できるようにすることができます。 例えば、ユーザーが自分自身のプラグインを書き、アプリケーションに追加できるプラグインシステムを作成することができます。

class MyApp {
  constructor(plugins) {
    this.plugins = plugins;
  }

  run() {
    this.plugins.forEach((plugin) => plugin.run());
  }
}

class MyPlugin {
  run() {
    console.log("This is my plugin");
  }
}

const app = new MyApp([new MyPlugin()]);
app.run(); // Output: 'This is my plugin'

4. データアクセス

依存性注入を使用して、アプリケーションのデータアクセスコードをコードから分離することができます。 これにより、アプリケーションがデータを格納し、取り出す方法を変更することができるので、コードのほかの部分を変更する必要がなくなります。

const db = {};

class Dog {
  constructor(dataAccess) {
    this.dataAccess = dataAccess;
  }

  save() {
    this.dataAccess.save(this);
  }

  bark() {
    console.log(this.barkSound);
  }
}

class LocalStorageDataAccess {
  save(dog) {
    db[JSON.stringify(dog)] = JSON.stringify(dog);
  }
}

const myDog = new Dog(new LocalStorageDataAccess());
myDog.barkSound = "woof";
myDog.save();
console.log(db);
// {
//  '{"dataAccess":{},"barkSound":"woof"}': '{"dataAccess":{},"barkSound":"woof"}'
// }

5. アーキテクチャ:

依存性注入を使用して、アプリケーションのレイヤードアーキテクチャを作成できます。これにより、コードをモジュール化し、理解しやすくすることができます。

class Dog {
  constructor(barkSound, color) {
    this.barkSound = barkSound;
    this.color = color;
  }
  bark() {
    console.log(`My dog barks with ${this.barkSound} and the color is ${this.color}`);
  }
}
class DogFactory {
  createDog(type) {
    switch (type) {
      case "GoldenRetriever":
        return new Dog("woof", "golden");
      case "Bulldog":
        return new Dog("bark", "white");
    }
  }
}
const factory = new DogFactory();
const goldenRetriever = factory.createDog("GoldenRetriever");
goldenRetriever.bark(); 
// Output: 'My dog barks with woof and the color is golden'

const bulldog = factory.createDog("Bulldog");
bulldog.bark(); 
// Output: 'My dog barks with bark and the color is white'

この例では、「DogFactory」というクラスが依存性注入パターンを使用して異なるタイプの犬を作成します。「barkSound」や「color」のようなプロパティを「Dog」クラスに依存関係として渡します。 このようにすることで、「Dog」クラスを変更することなく、異なるタイプの犬を作成することができます。 また、犬を作成することと「Dog」クラスを分けることができます。

結論

依存性注入は、JavaScriptのコードをモジュール化し、テストしやすく、柔軟にするための強力なパターンです。 コードの懸念を分離することで、理解しやすく、メンテナンスしやすくなります。 依存性注入を使用することで、よりテストしやすくモジュール化されたコードを作成し、コード内の異なるオブジェクトの関係を管理することができます。

最初は少し複雑に感じるかもしれませんが、基本を理解すれば、コーディングの旅が簡単になります。ここで示した例は簡単なものであり、プロジェクトでもっと高次の段階に取り入れることができます。大規模で複雑なコードベースを扱う場合、依存性注入は非常に役立つことが証明されるでしょう。

Mình hy vọng bạn thích bài viết này và học thêm được điều gì đó mới.

Donate mình một ly cafe hoặc 1 cây bút bi để mình có thêm động lực cho ra nhiều bài viết hay và chất lượng hơn trong tương lai nhé. À mà nếu bạn có bất kỳ câu hỏi nào thì đừng ngại comment hoặc liên hệ mình qua: Zalo - 0374226770 hoặc Facebook. Mình xin cảm ơn.

Momo: NGUYỄN ANH TUẤN - 0374226770

TPBank: NGUYỄN ANH TUẤN - 0374226770 (hoặc 01681423001)

image.png


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí