依存関係
モジュールやサービスが他のモジュールやサービスに依存する関係で、結合度と変更の影響範囲を決定する
依存関係とは
依存関係 (Dependency) は、モジュール A がモジュール B を使用する関係で、B の変更が A に影響する。依存の方向と強さが、システムの保守性とテスト容易性を決定する。
依存の方向
依存の方向を図で示す。
❌ 高レベルが低レベルに依存 (密結合)
ビジネスロジック → DynamoDB Client
→ DB を変更するとビジネスロジックも変更
✅ 依存性逆転 (DIP)
ビジネスロジック → Repository インターフェース ← DynamoDB Repository
→ DB を変更してもビジネスロジックは変更不要
TypeScript での依存性注入
TypeScript での依存性注入のコード例を示す。
// インターフェース (抽象) に依存し、実装を差し替え可能にする
interface OrderRepository {
get(id: string): Promise<Order | null>;
}
class OrderService {
constructor(private repo: OrderRepository) {}
async process(id: string) {
const order = await this.repo.get(id);
// ...
}
}
// 本番: DynamoDB、テスト: インメモリに差し替え可能
循環依存
循環依存を図で示す。
❌ 循環依存:
A → B → C → A
→ どのモジュールも単独でテストできない
✅ 解決: インターフェースで依存を逆転
A → B → C → Interface ← A
依存の種類
依存の種類を以下にまとめる。
| 種類 | 説明 | 例 |
|---|---|---|
| コンパイル時依存 | import で参照 | npm パッケージ |
| ランタイム依存 | 実行時に必要 | DB 接続、外部 API |
| 開発依存 | 開発時のみ必要 | テストフレームワーク |
依存を減らす設計
依存性逆転でインターフェースに依存し、イベント駆動で直接呼び出しではなくイベントで連携する。必要なものだけ import して最小限のインポートを心がけ、複雑な依存はファサードで 1 つのインターフェースに集約する。
詳しくは関連書籍を参照。
この記事は役に立ちましたか?
関連用語
依存管理
プロジェクトが使用する外部パッケージのバージョン管理と更新を行う仕組み
依存グラフ
モジュールやパッケージ間の依存関係をグラフ構造で表現し、ビルド順序や影響範囲を分析する
SOLID 原則
オブジェクト指向設計の 5 つの基本原則で、保守性と拡張性の高いコードを実現する
依存性逆転の原則
SOLID の D - 上位モジュールは下位モジュールに依存せず、両者とも抽象に依存すべきという設計原則
依存性注入 (DI)
オブジェクトが必要とする依存関係を外部から注入することで、モジュール間の結合度を下げテスタビリティを向上させる設計パターン
制御の反転
フレームワークがアプリケーションコードを呼び出す設計原則で、依存性注入の基盤となる概念
関連する記事
テスト本ガイド - テスト設計を学べる技術書の選び方
テストの書き方からテスト戦略まで学べる技術書の選び方を紹介。テストピラミッド、TDD の正しい読み方、テストの ROI の考え方を解説します。
Web 開発本ガイド - フロントエンドからバックエンドまで
Web 開発の全体像を学べる技術書の選び方と学習マップを紹介。フレームワーク本の賞味期限問題と公式ドキュメントとの使い分けも解説します。
バグを生むのは知識不足ではなく想像力不足である
バグの多くは、コードを書いた時点で「こういうケースもありうる」と想像できなかったことが原因です。想像力を鍛える読書法と、エッジケースへの感度を高める方法を解説します。