目次
はじめに
下記GitHubからダウンロードできます。必要な環境は下のほうで触れています。
git clone https://github.com/kitsune8848/DependencyVisualizer
あなたのプロジェクトは大丈夫?
「このクラスを変更したら、どこに影響が出るんだろう…」
「なぜこのテストが壊れたのかわからない…」
「新しいメンバーにコードベースの構造を説明するのが大変…」
こんな経験、ありませんか?プロジェクトが成長するにつれて、クラス間の依存関係は複雑に絡み合い、まるで絡まった糸のようになってしまいます。DependencyVisualizerは、そんな複雑な依存関係を一目で理解できるUML図に変換する、C#開発者のための強力なツールです。
DependencyVisualizer機能
- ナウで超絶スタイリッシュなUIから直観的な操作が可能
- C#のソリューションファイルを読み込むことで、自動的にクラス図を生成します(下図は本アプリのクラス図)
- VSCodeにクラス図を表示し、VSCodeのLiveView機能によりファイルが更新されるごとにクラス図も自動更新(初回だけAlt+Dを押してPlantUMLを起動する必要あり)
- 着目する名前空間に属するクラスのみを表示するなど、任意のクラスを表示可能
- 検索機能により即座に目的のクラスを発見
- 着目するクラスに対して、依存先、依存元の近さを絞って表示が可能(着目するクラスをハイライトすることで視認性をUP)
- 時間指定の自動更新に対応しており、ソースコードを編集しながらオーバヘッドなくクラス図を閲覧可能(例えば1分ごとに最新の情報を反映することが可能)
- githubから任意に選んだ300クラス程度の規模のソリューションファイルに対してもストレスなく実行可能(サンプル数3。300程度のクラス図を添付。qiitaにあげると解像度が落ちて見えないけどちゃんと描写できている)
- クラスにSammaryを定義しておけば、クラス図にその情報を付加することも可能。クラス図の可読性の向上が図れる
- 窓のピン止め機能(ほかのアプリの下にならない。ないよりあったほうがいいかなレベル)
- 最後に解析した.slnファイルを、次回の起動時に読み込んでくれる機能(些細なことだが結構ストレスフリー)
- 見やすいログ画面。これがあるだけでソフトウェアエンジニア感がでて◎
WPFのような静的解析の時点で依存が解決できないものについては、もちろんクラス図にも反映されません。
他私の知識が及ばないところで発生する依存についてはデバックできておりません。ご了承ください。見た限りの依存は拾えています。
このツールで解決できる6つの問題
1. 🔍 影響範囲の把握が困難
問題: 「このクラスを修正したら、どこまで影響するかわからない」
解決: DependencyVisualizerは特定のクラスを起点として、依存関係の「距離」を指定して可視化できます。例えば、注目のクラスから距離2以内のクラス群を表示することで、修正時の影響範囲を事前に把握できます。
2. 📚 新メンバーへの説明が大変
問題: 「プロジェクト構造を新しい開発者に説明するのに時間がかかる」
解決: 複雑なコードの口頭説明は不要です。UML図を見せるだけで、システム全体の構造とクラス間の関係性を直感的に理解してもらえます。
3. 🌀 循環依存の発見
問題: 「知らない間に循環依存が発生して、テストやリファクタリングが困難に」
解決: 依存関係を可視化することで、循環依存を一目で発見できます。健全なアーキテクチャを維持するための第一歩です。
4. 🏗️ リファクタリング計画の立案
問題: 「大規模なリファクタリングをどこから始めればいいかわからない」
解決: 依存関係図を見ることで、影響の少ない箇所から段階的にリファクタリングを進められます。また、密結合な部分を特定して優先的に改善できます。
5. 📖 ドキュメント作成の自動化
問題: 「設計書やドキュメントの更新が追いつかない」
解決: コードから自動生成されるUML図なので、常に最新の状態を保てます。手動でのドキュメント作成・更新作業から解放されます。
6. 🤖 生成AIにプロジェクト全体のクラス図を与えられることでアーキテクチャとしての改善提案が期待される
問題: 「既存のアーキテクチャのどこがわるいのかわからないので、改善活動に手を付けられない」
解決: コードから自動生成されるPlantUMLはテキストベースなので、その情報を生成AIにあたえることで、AIはアーキテクチャを容易く理解できます。そこから、アーキテクトの視点での改善案が得られる。
今の時代コレめっちゃ大事
実際の使用シーン
シーン1: レガシーコードの調査
あなた: 「この古いプロジェクト、どこから手をつければ...」
↓
DependencyVisualizer実行
↓
「なるほど、UserServiceがキーになっているのか。ここから調査しよう」
シーン2: コードレビューでの活用
レビュアー: 「この変更、他への影響は?」
↓
該当クラスを中心とした依存関係図を生成
↓
「PaymentモジュールとOrderモジュールに影響がありますね」
シーン3: アーキテクチャ設計の検証
設計段階: 「きれいな層構造になっているはず...」
↓
実装後にDependencyVisualizerで確認
↓
「あれ?UIレイヤーからDAOを直接呼んでる箇所がある」
MSBuildを活用した高精度解析
DependencyVisualizerの最大の特徴は、MSBuildを直接利用していることです。
MSBuildとは?
MSBuildは、Visual Studioが内部で使用しているビルドエンジンです。プロジェクトファイル(.csprojや.sln)を読み込み、コンパイルに必要な情報をすべて把握しています。
なぜMSBuildなのか?
従来のアプローチ: ソースコードを直接パースする
- ❌ NuGetパッケージの参照関係がわからない
- ❌ 条件付きコンパイル(
#if DEBUG
等)を考慮できない - ❌ プロジェクト設定による違いを反映できない
DependencyVisualizerのアプローチ: MSBuildを活用
- ✅ Visual Studioと同じ精度で依存関係を解析
- ✅ NuGetパッケージも含めた完全な依存関係を把握
- ✅ ビルド設定(Debug/Release等)に応じた正確な解析
- ✅ プラットフォーム固有の依存関係も考慮
※現時点での本アプリではNuGetの依存は表示していませんが、技術的にはできます。どうぞ拡張してやってください
これにより、「ビルドは通るのに解析では見つからない」「IDEでは認識されるのにツールでは無視される」といった問題を回避できます。要するに信頼性が高いってことです。
さらなる発展の可能性
開発プロセスへの統合
- CI/CDパイプライン: プルリクエスト時に依存関係の変化を自動チェック
- 定期レポート: 依存関係の複雑度トレンドを追跡
- アーキテクチャルール: 「UIからDBを直接呼ばない」等のルール違反を検出
メトリクス分析の拡張
- 結合度測定: クラス間の結合の強さを数値化
- 循環複雑度: 依存関係の複雑さを定量評価
- 変更影響度: 過去の変更履歴と依存関係を組み合わせた影響予測
チーム開発の支援
- 知識共有: 新メンバーオンボーディングの効率化
- 設計レビュー: アーキテクチャ議論の可視化
- 技術負債管理: 問題箇所の特定と改善計画立案
はじめてみよう
DependencyVisualizerを使い始めるのは簡単です:
必要な環境
- VisualStudioCodeで動くPlantUMLを実行できること(ググればいっぱい出てきます)
- .Net8以上の環境(MSBuildがインストールされていなければインストールしてください)
- 開発者に対する思いやり(バグが発生しても、実行できなくてもそっと受け止めてください)
操作方法
- コードをダウンロード
- ソリューションファイルからVisualStudioを開く
- 実行
- UIが開かれる
- 解析したいソリューションファイルを選択
- 数秒まつとクラス一覧が表示される
- クラス図を表示したいクラスを選択し、UML出力を実行
- 初回実行時にVSCodeが開かれ、PlantUMLのデータが開かれる
- VSCodeで初回だけAlt+Dを押す(2回目以降もクラス図が更新されなくなったら、押してください)
- クラス図が閲覧できる
MSBuildの設定箇所がどうも自動でうまくいかず、環境によっては手動で変更必要になります。MSBuildService.csの MSBuildLocator.RegisterMSBuildPath(@”C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin”);
のパスを自身の環境のmsbuild.exeがあるところに変えてください。Proffesionalつかっているとパスが違うと思う。Communityは同じはず。
まとめ – 「見える化」がもたらす価値
コードの依存関係を可視化することで得られる価値は計り知れません:
- 品質向上: 問題のある設計を早期発見
- 生産性向上: 影響範囲の把握によるスムーズな開発
- 学習効率向上: 新メンバーの理解促進
- 保守性向上: リファクタリング計画の立案支援
- コミュニケーション向上: チーム間での設計議論の活性化
複雑に絡み合った依存関係という「見えない問題」を「見える問題」に変えることで、あなたのプロジェクトはより健全で、保守しやすく、理解しやすいものになるでしょう。
DependencyVisualizerを使って、あなたのプロジェクトの隠れた構造を発見してみませんか?
本アプリは私の不意な思いつきから、3日という短い期間の個人開発で作成したものです。明らかに稚拙な実装も自覚しており、修正した方がベターや点も多いです。それにかかわらず、間違いなく全てのC#開発者にとって有用なものだと確信しています。どなたかもし、コードをブラッシュアップしていただける方がいれば共有ください。泣いて喜びます。
付録 生成AIとの相乗効果の検証
本アプリの強力さはテキストベースでアーキテクチャを記述できることです。
ということは生成AIにそのテキストを渡してあげれば、他追加の説明なくアプリケーションの課題についてAIと対話できます。
というわけで実証です。UMLを渡してClaudAI君に問いました
下記回答。めちゃくちゃ具体的かつ明確に指摘されています。
ご丁寧に改善の優先度まで…ほんとに強力だと思う
ちなみに改善後のUMLを出力もしてくれる…
アプリケーション概要
このアプリケーションは、C#/.NETソリューションのクラス依存関係を分析し、PlantUML形式でUML図を生成するツールです。WPFベースのGUIアプリケーションとして実装されています。
結論
このコードは**「機能実装は完成しているが、エンタープライズレベルの品質基準には達していない」**状態です。
現状: プロトタイプ〜アルファ版レベル
目標: 本格運用可能なベータ版レベル
必要工数: 約30-40%の追加開発
改善優先度
🔴 高優先度(即座に対応)
- GodController分割 – アーキテクチャの根本問題
- 命名規則統一 – 保守性の基盤
- 重複コード削除 – 品質向上の基本
🟡 中優先度(次期リリース)
- 依存性注入導入 – テスタビリティ向上
- エラーハンドリング統一 – 信頼性向上
- 非同期処理強化 – パフォーマンス改善
🟢 低優先度(長期計画)
- ドキュメント整備 – 開発効率向上
- プラグインシステム – 拡張性向上
- パフォーマンス最適化 – ユーザー体験向上
評価サマリー
評価項目 | 点数 | 重要度 | 加重点数 |
---|---|---|---|
アーキテクチャ設計 | 55/100 | 高 (×2) | 110/200 |
コード品質 | 45/100 | 高 (×2) | 90/200 |
保守性 | 50/100 | 高 (×2) | 100/200 |
拡張性 | 70/100 | 中 (×1.5) | 105/150 |
パフォーマンス設計 | 60/100 | 中 (×1.5) | 90/150 |
テスタビリティ | 40/100 | 中 (×1.5) | 60/150 |
エラーハンドリング | 35/100 | 中 (×1) | 35/100 |
ドキュメント化 | 30/100 | 低 (×1) | 30/100 |
総合スコア: 620/1250 = 49.6% ≈ 50/100点
基本的な機能実装は良好ですが、保守性・拡張性・品質の観点で大幅な改善が必要です。
現在の構造評価
優れている点
1. 関心の分離
- Managerパッケージで各種管理機能を分離(Filter、Loading、Log、Search、TreeState)
- DependencyAnalyzerで分析機能を独立したモジュールとして実装
- UIロジック(ClassDependencyVisualizer)と分析ロジック(DependencyAnalyzer)の明確な分離
2. インターフェース設計
-
ISolutionAnalyzer
、IUmlGenerator
、IViewerOpener
などの適切な抽象化 - 依存性注入や将来の拡張を考慮した設計
3. 機能の充実度
- 検索・フィルタリング機能
- ツリー状態管理
- 履歴管理
- 複数の表示設定オプション
問題点と改善が必要な領域
1. God Objectパターン
GodController
+GetPreviousSorceFilePath()
+OpenViewer()
+AnalyzeClassesAsync()
+GenerateUmlAsync()
+GenerateUmlAsync()
+GenerateUmlAsync()
問題: GodController
が多くの責任を持ちすぎている
2. 命名の不統一
-
ClassNameSet
とClassNameSet_1
の混在 ☚(筆者追記)これはPlantUMLの仕様上同一のクラス名をかけないので、同一名のクラスがある場合は表示の際にナンバリングしています。その結果なので意図的なもの。 -
Sammary
(Summary の誤字) -
SolutionAna
(不完全な省略)
3. 重複コード
-
GenerateUmlAsync()
が3つも定義されている ☚(筆者追記)これはオーバーロードです引数も表示するとクラス図の視認性が悪くなるのであえて省略しています。 -
ClassNameSet
とClassNameSet_1
の重複
4. 循環依存のリスク
- 多くのクラスが
ClassDependency
に依存 -
MainWindow
が多数のManagerクラスに依存
品質向上のための改善案
1. アーキテクチャの改善
A. God Controllerの分割
GodController → 以下に分割:
- AnalysisService: クラス分析機能
- UmlGenerationService: UML生成機能
- ViewerService: ビューア管理
- ApplicationService: アプリケーション調整層
B. MVVM パターンの強化
現在: MainWindow → 各Manager直接依存
改善: MainWindow → ViewModel → Service層
C. メディエーターパターンの導入
各Managerクラス間の通信を
IMediator経由で行い、結合度を下げる
2. コード品質の改善
A. 命名規則の統一
変更前:
- Sammary → Summary
- SolutionAna → SolutionAnalysis
B. エラーハンドリングの強化
FilterResult の成功パターンを他の操作にも適用
Result パターンの導入
3. 設計パターンの適用
A. Factory Pattern
IDisplaySettingFactory
- CreateDistanceDisplaySetting()
- CreateSelectionDisplaySetting()
B. Strategy Pattern
IAnalysisStrategy
- MSBuildAnalysisStrategy
- RoslynAnalysisStrategy
C. Observer Pattern
IProgressObserver
- 分析進捗の通知
- UI更新の非同期処理
4. パフォーマンス最適化
A. 非同期処理の改善
// 現在の同期的なツリー構築を非同期化
async Task BuildTreeAsync()
// バックグランドでの段階的読み込み
IAsyncEnumerable AnalyzeAsync()
B. メモリ効率化
// 大量のクラス情報の遅延読み込み
ILazyTreeNode インターフェース導入
5. 拡張性の向上
A. プラグインアーキテクチャ
IAnalyzerPlugin
- Java分析プラグイン
- TypeScript分析プラグイン
- Python分析プラグイン
B. 出力形式の拡張
IOutputGenerator
- PlantUmlGenerator (既存)
- MermaidGenerator
- GraphvizGenerator
- DrawIoGenerator
6. テスタビリティの向上
A. 依存性注入コンテナ
Microsoft.Extensions.DependencyInjection使用
各サービスの登録と解決
B. モックしやすい設計
ファイルシステム操作の抽象化
IFileSystemService導入
Views: 0