# 帳票設計書 14-Graphviz DIコンテナダンプ

## 概要

本ドキュメントは、Symfony DependencyInjectionコンポーネントにおけるGraphviz DIコンテナダンプ機能（`GraphvizDumper`）の設計仕様を定義する。DIコンテナのサービス依存関係をGraphviz DOT形式で出力し、可視化ツールでグラフ画像に変換可能にする。

### 本帳票の処理概要

GraphvizDumperは、DIコンテナに登録されたサービス間の依存関係をGraphviz DOT言語形式で出力する。出力されたDOTファイルは、`dot`ユーティリティを使用してPNG等の画像形式に変換できる。

**業務上の目的・背景**：大規模なSymfonyアプリケーションでは、サービス間の依存関係が複雑になりやすい。GraphvizDumperを使用してサービスの依存関係グラフを可視化することで、アーキテクチャの理解、循環依存の発見、リファクタリングの計画立案が容易になる。

**帳票の利用シーン**：サービスコンテナの構造分析、ドキュメント生成、コードレビュー時の依存関係確認、アーキテクチャ改善の検討時に使用される。

**主要な出力内容**：
1. Graphviz DOTグラフ宣言（`digraph sc`）
2. ノード定義（各サービスをノードとして表現）
3. エッジ定義（サービス間の依存関係を矢印で表現）
4. スタイル属性（色、形状、フォント等）

**帳票の出力タイミング**：開発者が明示的にGraphvizDumperを呼び出した場合。

**帳票の利用者**：アプリケーション開発者、アーキテクト。

## 帳票種別

Graphviz DOT形式テキスト出力（依存関係グラフ）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | プログラム呼び出し | API呼び出し | GraphvizDumper::dump() |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | DOT（Graphviz） |
| 用紙サイズ | N/A（グラフの自動レイアウト） |
| 向き | N/A（graphオプションで制御） |
| ファイル名 | 任意（例: `container.dot`） |
| 出力方法 | 文字列として返却 |
| 文字コード | UTF-8 |

### Graphviz固有設定

| 項目 | デフォルト値 |
|-----|------------|
| graph.ratio | compress |
| node.fontsize | 11 |
| node.fontname | Arial |
| node.shape | record |
| edge.fontsize | 9 |
| edge.fontname | Arial |
| edge.color | grey |
| edge.arrowhead | open |
| edge.arrowsize | 0.5 |
| node.instance.fillcolor | #9999ff |
| node.definition.fillcolor | #eeeeee |
| node.missing.fillcolor | #ff9999 |

## 帳票レイアウト

### レイアウト概要

DOTグラフ構造として、ノード（サービス）とエッジ（依存関係）で構成される。

```
┌─────────────────────────────────────┐
│  digraph sc {                       │
│    グラフオプション                    │
│    ノードデフォルトオプション            │
│    エッジデフォルトオプション            │
├─────────────────────────────────────┤
│    node_xxx [label="..." ...]       │
│    node_yyy [label="..." ...]       │
│    (各サービスのノード定義)            │
├─────────────────────────────────────┤
│    node_xxx -> node_yyy [...]       │
│    (依存関係のエッジ定義)             │
├─────────────────────────────────────┤
│  }                                  │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | digraph宣言 | 有向グラフの開始 | 固定値 | `digraph sc {` |
| 2 | graphオプション | グラフ全体のオプション | options['graph'] | `ratio="compress"` |
| 3 | nodeデフォルト | ノードのデフォルトスタイル | options['node'] | `node [fontsize="11" ...]` |
| 4 | edgeデフォルト | エッジのデフォルトスタイル | options['edge'] | `edge [fontsize="9" ...]` |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | ノードID | サービスIDのDOT安全化名 | dotize(サービスID) | `node_xxx` | N/A |
| 2 | ノードラベル | サービスID、エイリアス、クラス名 | Definition, Aliases | `"id (alias)\nclass"` | N/A |
| 3 | ノードスタイル | 塗りつぶし色等 | node.instance/definition/missing | `fillcolor`, `style` | N/A |
| 4 | エッジラベル | 依存関係の名前（メソッド名等） | findEdges() | `label="methodName()"` | N/A |
| 5 | エッジスタイル | 必須/任意、遅延ロード | Reference, Definition | `style="filled"/"dashed"` | N/A |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | グラフ閉じ | 有向グラフの終了 | 固定値 | `}` |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ContainerBuilderインスタンス | コンストラクタで渡されたコンテナ | Yes |
| スタイルオプション | graph, node, edge等のカスタマイズ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ノード | サービス定義の登録順 |
| 2 | エッジ | サービスIDごとにグループ化 |

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを直接参照しない。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | N/A | N/A |

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| ノードID | `preg_replace('/\W/i', '_', $id)` | N/A | サービスIDを英数字+アンダースコアに変換（行234-236） |
| ノード色分け | instance=#9999ff, definition=#eeeeee, missing=#ff9999 | N/A | サービスの種別に応じた色分け |
| エッジスタイル | required→filled, optional→dashed | N/A | 依存の必須/任意でスタイル変更 |
| 遅延エッジ色 | lazy=true → color="#9999ff" | N/A | 遅延ロードの依存関係に色付け |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[dump呼び出し] --> B[オプションマージ]
    B --> C[findNodes - ノード検出]
    C --> D[findEdges - エッジ検出]
    D --> E[startDot - グラフ開始]
    E --> F[addNodes - ノード追加]
    F --> G[addEdges - エッジ追加]
    G --> H[endDot - グラフ終了]
    H --> I[環境変数プレースホルダ解決]
    I --> J[DOT文字列返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ParameterNotFoundException | 解決できないパラメータ参照 | （キャッチされて無視） | 特になし（クラス名が未解決のまま表示） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千サービス定義 |
| 目標出力時間 | 1秒以内 |
| 同時出力数上限 | 制限なし |

## セキュリティ考慮事項

- 出力にはサービスIDとクラス名が含まれるが、パラメータ値や機密情報は含まれない
- cloneContainer()メソッドでコンテナのクローンを作成して安全に処理する（行184-197）

## 備考

- 画像変換コマンド例: `dot -Tpng container.dot > foo.png`
- ノードの3種類の色分け: instance（直接登録、青）、definition（定義ベース、灰色）、missing（未解決参照、赤）
- 共有サービスはfilled、非共有サービスはdottedスタイルで表示

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

GraphvizDumperが内部で使用するノード/エッジのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | options配列のデフォルト値（行36-43）でスタイル体系を理解 |
| 1-2 | GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | nodesプロパティ（行33）とedgesプロパティ（行34）の構造 |

**読解のコツ**: nodes配列は`['class' => string, 'attributes' => array]`構造、edges配列は`['name' => string, 'required' => bool, 'to' => string, 'lazy' => bool]`構造であることを理解する。

#### Step 2: エントリーポイントを理解する

dump()メソッドが処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | dump()メソッド（行57-83）でオプションマージとノード/エッジ検出 |

**主要処理フロー**:
1. **行59-63**: オプションのマージ
2. **行65**: findNodes()でサービスをノード化
3. **行68-80**: findEdges()で依存関係をエッジ化
4. **行82**: startDot + addNodes + addEdges + endDot の結合

#### Step 3: ノード検出処理を理解する

findNodes()でサービス定義をグラフノードに変換する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | findNodes()（行149-182）でDefinitionとインスタンスを区別 |

**主要処理フロー**:
- **行155-168**: Definition型サービスのノード生成（node.definitionスタイル）
- **行170-179**: インスタンス型サービスのノード生成（node.instanceスタイル）

#### Step 4: エッジ検出処理を理解する

findEdges()で依存関係を再帰的に探索する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | findEdges()（行112-147）で引数・プロパティ・メソッドコールを探索 |

**主要処理フロー**:
- **行122-131**: Reference型引数のエッジ生成
- **行132-133**: ArgumentInterface型の再帰探索
- **行134-140**: Definition型（インライン定義）の再帰探索
- **行141-143**: 配列型の再帰探索

### プログラム呼び出し階層図

```
GraphvizDumper::dump()
    |
    +-- findNodes()
    |       +-- cloneContainer()
    |       +-- getParameterBag()->resolveValue()
    |
    +-- findEdges() [各Definition]
    |       +-- findEdges() [再帰: arguments]
    |       +-- findEdges() [再帰: properties]
    |       +-- findEdges() [再帰: methodCalls]
    |
    +-- startDot()
    |       +-- addOptions()
    |
    +-- addNodes()
    |       +-- getAliases()
    |       +-- dotize()
    |       +-- addAttributes()
    |
    +-- addEdges()
    |       +-- dotize()
    |
    +-- endDot()
```

### データフロー図

```
[入力]                      [処理]                       [出力]

ContainerBuilder ─────> GraphvizDumper::dump() ─────> DOT文字列
  |-- Definitions            |                     |-- digraph sc {
  |-- Aliases                |-- findNodes()       |--   node_xxx [...]
  |-- ServiceIds             |-- findEdges()       |--   node_xxx -> node_yyy
                             +-- DOT組み立て        |-- }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GraphvizDumper.php | `src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php` | ソース | メインのGraphvizダンプ処理クラス |
| Dumper.php | `src/Symfony/Component/DependencyInjection/Dumper/Dumper.php` | ソース | 基底クラス |
| ContainerBuilder.php | `src/Symfony/Component/DependencyInjection/ContainerBuilder.php` | ソース | コンテナ定義の管理 |
| Definition.php | `src/Symfony/Component/DependencyInjection/Definition.php` | ソース | サービス定義データ構造 |
| Reference.php | `src/Symfony/Component/DependencyInjection/Reference.php` | ソース | サービス参照 |
| ParameterBag.php | `src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php` | ソース | パラメータ管理 |
