コールグラフの可視化(毛玉を避ける Focus+Context と描画ライブラリ)
コールグラフの全体表示は規模を問わず毛玉(hairball)になる。選択ノードと N ホップ近傍だけ展開して残りを畳む Focus+Context が実用解で、数百ノードなら Cytoscape.js + ELKjs の layered レイアウト、配信はローカルサーバ + ブラウザが最小構成。
調査時点: 2026-06。TypeScript のコールグラフ抽出ツールの出力をどう見せるかを調べたもの。Mermaid や素の Graphviz は密になると線が絡み、zoom・focus・検索がないため不向き、という前提から始めている。
コールグラフは、関数を頂点、ある関数から別の関数への呼び出しを矢印として表した図。処理の流れや変更の影響範囲を調べるために使う。
全体表示は毛玉になる
関数単位のコールグラフは、中規模のコードベースで数百ノードになる。force-directed で全体を一度に描くと線が絡んだ塊(hairball)になり、規模を問わず読めない。実用解は 1 つで、選択したノードと N ホップの近傍だけを展開し、残りを畳む Focus+Context。
既存ツールの UX
| ツール | 方式 | 学べる点 / 弱点 |
|---|---|---|
| Sourcetrail(OSS、2021-12 アーカイブ、コミュニティフォークが継続) | 三画面連動 | 検索でシンボルを選ぶ → グラフが即座に再センタリング → エッジをクリックすると該当コード行へジャンプ。クラスは折りたたみスーパーノードで、隠れた要素数を数字バッジで示す。start と target と深さスライダーで Custom Trail を切り出す。bundled edges |
| go-callvis(Go) | ポインタ解析 → dot → SVG を localhost で配信 | パッケージ単位のフォーカス、-nostd / -noext で標準ライブラリと外部を除外。SVG が大きすぎてブラウザが固まるという批判がある |
IDE の Call Hierarchy(VSCode CallHierarchyProvider / IntelliJ) | ツリー展開 | コード連動が完全で学習コストがない。グラフ構造が見えず横断的な把握には向かない |
| CodeSee / CodeCharta | モジュール依存マップ / 3D 都市メトリクス | 関数レベルの呼び出し関係は出さない |
描画ライブラリ(2026)
| ライブラリ | 描画 | 規模の目安 | 備考 |
|---|---|---|---|
| Cytoscape.js | Canvas | 3〜5k ノードで FPS 低下(二次情報) | 解析向け。ELK / dagre アダプタが公式、compound node 対応 |
| Sigma.js + graphology | WebGL | 10k 超 | 大規模に強いが階層レイアウトが薄い |
| vis-network | Canvas | Cytoscape と同程度 | 学習コストが低い |
| React Flow(xyflow) | DOM / SVG | 1000 ノード超は公式が非推奨 | ダイアグラムエディタ向け |
| G6(AntV) | Canvas / WebGL | 3 万プリミティブ程度 | 高機能だがドキュメント品質にばらつき |
数十〜数百関数のコールグラフなら Cytoscape.js で足りる。数千を超えたら Sigma.js を検討する。
レイアウト
有向グラフなので階層型レイアウトを使う。
- ELKjs
layered: 活発に開発され、アルゴリズムが多い。cytoscape-elk で Cytoscape.js と組める - dagre: 事実上メンテナンスが止まっており、ダウンロード数も桁違いに少ない
- d3-dag: TypeScript ファーストの現代的な代替
再帰呼び出しがあると厳密な DAG(循環を持たない有向グラフ) にならない。ELK の循環処理(仮想ノードの挿入か)は一次情報で未確認。
分かりやすさの UX パターン
- Focus+Context: 選択ノード + N ホップ近傍だけ展開。残りは数字バッジ付きの折りたたみ。深さスライダーと Trail 履歴を付ける
- 段階的開示: クラス / モジュールをスーパーノードにしてクリックで開く(expand-on-click)。ズームレベルでクラスタ表示と個別関数表示を切り替える(semantic zoom)
- クラスタリング: ファイル / ディレクトリを compound node でグルーピングする
- エッジ管理: bundled edges、方向の色分け(通常は灰、再帰は赤)。Hierarchical Edge Bundling は数百規模には過剰
- 毛玉防止: 全体を最初に見せない(entrypoint 起点)、標準ライブラリと node_modules を初期状態でフィルタ、検索 → ハイライト → フォーカスの導線、重要度(betweenness など)をノードサイズに反映
配信形態
| 形態 | 利点 | 欠点 |
|---|---|---|
ローカルサーバ + ブラウザ(npx <tool> serve) | 実装が最小、依存フリー、分割ロードできる | コマンド起動が要る |
| 静的 HTML 単一ファイル | 渡せば動く。CI の artifact にできる | 数千ノードで MB 超。複雑な UI が難しい |
| VS Code WebView 拡張 | コードジャンプが完全 | marketplace 依存、VS Code 専用。Call Graph Navi など既存拡張が多い |
OSS として配るなら CLI + ローカルサーバ型を主軸にすると、既存の VS Code 拡張群と役割が分かれる。
使われない図になる失敗パターン
- 全体を一度に見せる設計
- インタラクションのない静的 PNG / SVG(go-callvis への「SVG が大きすぎて固まる」批判)
- 標準ライブラリ / node_modules を展開してしまう(フィルタの実装忘れ)
- force-directed の非決定レイアウト(前回見た位置に戻れない)
- 最初の 5 分で有用さが伝わらない
最小構成の推奨
CLI が静的解析でコールグラフを JSON に出し、serve でローカル HTTP を立て、ブラウザで Cytoscape.js + cytoscape-elk(layered)が描く。UX の最低ラインは 4 点。
- 選択ノード + 2 ホップ近傍のみ表示
- 標準ライブラリ / node_modules を初期フィルタ
- クリックで呼び元 / 呼び先を展開
- 検索バーでハイライト
Sourcetrail の「コードへジャンプ」は VS Code 拡張版で後付けし、スタンドアロン版は URL に行番号を渡す程度で代替する。
関連
更新履歴
- 2026-06-19: 初版(ローカル調査ノート)
- 2026-10-17: Wiki へ移植、概念ページとして再構成。冒頭に定義を追加
出典
- https://github.com/CoatiSoftware/Sourcetrail/blob/master/DOCUMENTATION.md
- https://ondrajz.github.io/go-callvis/
- https://js.cytoscape.org/
- https://github.com/cytoscape/cytoscape.js-elk
- https://github.com/xyflow/xyflow/discussions/3003
- https://erikbrinkman.github.io/d3-dag/
- https://cambridge-intelligence.com/blog/hairball-effect-in-graph-visualization/
- https://fse.studenttheses.ub.rug.nl/9153/1/hoogendorp10.pdf