【ツール活用|実務向け】dependency-cruiserで実現する「疎結合な設計」の自動検知と維持

導入

大規模なプロジェクトにおいて、コードの「依存関係」は時間とともに複雑化し、いわゆる「スパゲッティコード」へと変貌しがちです。特に循環参照や、本来触れるべきではないレイヤー間の直接参照は、バグの温床となります。本記事では、依存関係を可視化・検証するツール「dependency-cruiser」を活用し、CI環境でアーキテクチャの規約違反を自動的にブロックする方法を解説します。

基礎知識

dependency-cruiserは、JavaScriptやTypeScriptのモジュール依存関係を解析し、グラフ化や検証を行うツールです。
循環参照 (Circular Dependency): AがBを呼び出し、BがAを呼び出すような構造。メモリリークや初期化順序のバグを引き起こす原因となります。
アーキテクチャ制約: 例えば「プレゼンテーション層が直接データアクセス層を呼んではいけない」といった、設計上のルールです。
これらを静的解析で自動検知することで、レビューコストを大幅に削減できます。

実装/解決策

まずはプロジェクトにdependency-cruiserをインストールし、設定ファイルを作成します。

1. インストール:
npm install –save-dev dependency-cruiser

2. 初期設定:
npx dependency-cruiser –init

これにより、.dependency-cruiser.jsが生成されます。この設定ファイル内で「禁止する依存関係」をルールとして定義します。

サンプルプログラム

以下は、.dependency-cruiser.js内に記述するルール定義の例です。例えば「featuresディレクトリ内のコードが、他のfeaturesを直接参照してはいけない」という制約を設ける場合です。

// .dependency-cruiser.js の rules セクションに追記する例
{
rules: [
{
name: “no-cross-feature-imports”,
severity: “error”, // 違反時はエラーとして扱い、CIを失敗させる
from: { path: “^src/features/([^/]+)” },
to: {
path: “^src/features/([^/]+)”,
pathNot: “^src/features/$1” // 自分自身のディレクトリ内は許可
},
comment: “機能間(features)の直接的な依存は禁止です。共有モジュール経由で利用してください。”
}
]
}

// 実行コマンド(パッケージのscriptsに追加することを推奨)
// npx depcruise src –validate .dependency-cruiser.js

応用・注意点

CIへの組み込み: 上記コマンドをGitHub ActionsなどのCIワークフローに組み込むことで、アーキテクチャ違反を含むプルリクエストをマージ前に確実にブロックできます。
可視化の活用: –output-type dot を指定してGraphviz形式で出力し、SVG画像化することで、チームメンバー間での「依存関係の現状把握」が容易になります。
陥りやすい罠: 厳しすぎるルールを設定すると、開発初期にオーバーエンジニアリングになりがちです。最初は循環参照の検知のみから始め、徐々にレイヤー間の制約を追加していく「段階的導入」をお勧めします。

コメント

タイトルとURLをコピーしました