0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ギャルが依存性の逆転を説明するよ〜✨

Last updated at Posted at 2025-03-13

まずオブジェクト指向って何?

オブジェクト指向(OOP)は、ざっくり言うと、アプリとかの仕組みを「オブジェクト」っていう小さな部品の集合みたいにして組み立てるスタイルなの。これでコードが超見やすく、管理しやすくなるのよね~。

例として、例えば社員管理システムとか作るとするよ!こんな感じで、社員それぞれを「オブジェクト」にするわけ👇:

class Employee {
  constructor(public name: string, public position: string) {}

  work() {
    return `${this.name} is working as a ${this.position}`;
  }
}

const employee = new Employee("Taro", "Developer");
console.log(employee.work()); // → "Taro is working as a Developer"

社員(Employee)ってクラスから、個別の「社員オブジェクト」を作って使う感じ。これがオブジェクト指向の基本ノリね💼💖!

依存性の逆転(Dependency Inversion)とは?

依存性の逆転(DIP)は、めっちゃシンプルに言うと、「上のクラスも下のクラスも直接お互いに頼らず、抽象的なルール(インターフェースとか)を介してやり取りしようぜ!」って考え方。これでコードがゴチャゴチャせず、変更に強くなるの。

なぜ必要?

そのまま実装すると、コードが「具体的なクラス」にガッツリ依存しちゃって修正が超ダルくなるの!💦例えば「社員データ」をデータベースから取得するクラスがあったとして、実際に使うデータベースを変更したらコード全部直さなきゃ…ってなるのよ。それ絶対嫌じゃん?🤦‍♀️✨

DIPを使うと、データ取得の仕組みを「インターフェース(抽象)」で定義しておいて、どのデータベースでも柔軟に変更可能な感じになるの!

コード例:社員データ取得のシステム
「現場でありそう」なコードを書いてみたよ!👇

DIPを使わない場合(NG例)

class DatabaseService {
  getEmployees() {
    return ["Taro", "Hanako", "Jiro"];
  }
}

class EmployeeManager {
  private dbService: DatabaseService;

  constructor() {
    this.dbService = new DatabaseService();
  }

  listEmployees() {
    return this.dbService.getEmployees().join(", ");
  }
}

// 実行
const manager = new EmployeeManager();
console.log(manager.listEmployees()); // "Taro, Hanako, Jiro"

🌟 問題点:

EmployeeManagerがDatabaseServiceに直接依存しちゃってるから、データベースの仕組みを変えるとき(例えば、クラウドDBに切り替えたいとき)に修正が面倒すぎる💦。

クラウドDBを追加する場合

class EmployeeManager {
  private dbService: any;

  constructor() {
    // 新しくCloudServiceを使う場合
    this.dbService = new CloudService();
  }

  listEmployees() {
    return this.dbService.getEmployees().join(", ");
  }
}

// 実行例
const manager = new EmployeeManager();
console.log(manager.listEmployees()); // "Alice, Bob, Charlie"

今回はCloudServiceだけど、将来的に別のデータベース(例えばNoSQLとか)を使う場合も、また同じことを繰り返さなきゃいけない。

DIPを使う場合(GOOD例✨)

// 抽象(インターフェース)を定義
interface EmployeeRepository {
  getEmployees(): string[];
}

// データベース用のクラス
class DatabaseService implements EmployeeRepository {
  getEmployees(): string[] {
    return ["Taro", "Hanako", "Jiro"];
  }
}

// クラウド用のクラス(新しいデータソース)
class CloudService implements EmployeeRepository {
  getEmployees(): string[] {
    return ["Alice", "Bob", "Charlie"];
  }
}

// EmployeeManagerは抽象に依存!
class EmployeeManager {
  private repository: EmployeeRepository;

  constructor(repository: EmployeeRepository) {
    this.repository = repository;
  }

  listEmployees() {
    return this.repository.getEmployees().join(", ");
  }
}

// 実行
const dbManager = new EmployeeManager(new DatabaseService());
console.log(dbManager.listEmployees()); // "Taro, Hanako, Jiro"

const cloudManager = new EmployeeManager(new CloudService());
console.log(cloudManager.listEmployees()); // "Alice, Bob, Charlie"

🌟 良い点:

EmployeeManagerは具体的なDatabaseServiceやCloudServiceに依存せず、EmployeeRepositoryという抽象にだけ依存してる。

だから、データベースをクラウドに切り替えても、EmployeeManagerを一切修正せずに済むの!修正箇所が最小限で楽チン~💅✨。

ギャルポイント✨

DIPを意識すると、システム全体が「独立モジュール」みたいにスッキリまとまるから、チーム開発でもバチバチ強いコーディングができる!🌟

依存性を具体から抽象に変えることで、拡張性と柔軟性が爆上がり!これ、最強じゃない?💖

こんな感じでDIPを理解しておけば、業務でコードを書くときにもバッチリ活用できるし、めっちゃ「できるエンジニア」って感じ出せるよ~✨!他にも知りたいことがあったら、遠慮なく聞いてね!

参考文献

[1] 依存性の逆転のいちばんわかりやすい説明
[2] 【SOLID】依存関係逆転の原則を完全に理解したい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?