ReSharper の Type Dependency Diagram でC#クラスの依存関係が一目瞭然


## はじめに

Unityでコードをたくさん書いていくと、徐々にスクリプト間の関連性がわからなくなっていったりするものです。最近だとAssembly Definition File(asmdef)を入れるために、依存関係を断ち切る必要がでてきたりしますが、そのような場合に、クラスの関係を一目で見られるように可視化すると、作業がはかどります。
これを実現する `Type Dependency Diagram` の便利な使い方についてご紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/ad28533c-4091-a0a1-0286-86a5d2f0fcfc.png)

## Type Dependency Diagramとは

クラスやインタフェース、enum等の型同士の関連性を可視化するのに便利なツールです。ReSharperの中に入っている１つの機能で、Visual Studio内で利用できます。C#向けです。

* ReSharperについて
  * この記事で扱うType Dependency Diagramを表示するために必要です。
  * Visual Studioに、様々な解析やリファクタの機能を追加することができるツールです。
  * ReSharperは初回インストール時に限り30日間「評価」することもできます。
  * Rider等JetBrainsのツールをお使いの場合、dotUltimateパックに入っているので、セットにするとお得に購入できます。

## 準備

* お使いのVisual StudioにReSharperをインストールしましょう。ここでは省略します。
  * Visual Studioのバージョンは 2017/2019/2022 あたりなら良いはずです。
* Unityのスクリプト編集ツールとしてRiderなどを設定されている方は `Preferences` -> `External Tools` の項目から、`External Script Editor` を `Visual Studio ****` に設定しましょう。

## 最初の一歩

Unityでなにかプロジェクトを開いて、クラスを選んで `Type Dependency Diagram` で見てみましょう。
ここでは、 Meta社の公開しているサンプルプロジェクト https://github.com/oculus-samples/Unity-TheWorldBeyond を例にします。

`Scripts/VirtualPets.cs` のところで右クリックして、メニューから `Show Type Dependency Diagram` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/014e992e-f913-c7cf-a0d5-2141d23f80b5.png)

そうすると、こちらのようなウィンドウが表示されると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/58376b87-c214-b96d-2525-2086d0b84052.png)

さて、VirtualPetクラスが、enum PetStateに依存していることがわかります。
ちなみに、PetStateクラス内に enum PetState が存在していますので、当然といえば当然です。

ここでは、関連している型をみていきたいので、VirtualPetの右クリックメニューから `Add All Referenced Types` を実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/5f0287d6-5deb-85b5-8147-b7589a9d5c2f.png)

そうすると、VirtualPetから参照されているクラスが追加され、このようになります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/270ed4e5-40ad-c660-c687-2bfd7ad92e1a.png)

便利でしょうか？いや、細かすぎて何がなにやらですね。
これから、これを見やすくしていきます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/aac27f23-4dfc-153b-d9ff-72159bfd621e.png)

左上にあるツールバーの右端でグルーピングを変更できます。 `Group by Namespace` を選びましょう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/05a5a164-7d19-b911-89cb-cbfce3179eb7.png)

今度は突然すごいシンプルになりました。真ん中に {} とありますが、これはルートネームスペースを表しています。すべての親ということですね。
焦らずに左上の三角形を押しましょう。そうすると中身がでてきます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/a4ead447-f614-520f-8f52-56a9a86f5d05.png)

中身が展開されました。
注目したいのは赤で囲ってあるところです。左の四角はSystem、下の四角はUnityEngineとあります。
SystemやUnityEngineネームスペースのクラスは、要するにStringやMonoBehaviourのようなものですが、一般的にはこれらは解析対象ではない、空気のような存在ですから、この図からは除外するのが妥当というものです。

それぞれ、選択した後キーボードの `Delete` キーを押すと削除できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/074d9cc3-4030-a7f8-db0c-71e61e8e15db.png)

だいぶすっきりしてきました。これで十分の場合はここで止めても良いでしょう。
また、些末なクラスはここで選択して削除しても良いでしょう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/da9af2de-d11d-7822-7ab4-112e7b0ec01f.png)

しかし、ここでもう一段、ツールバー右端のGroupingから `Group by Project Structure` を選択しましょう。これはフォルダベースでグルーピングすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/d51a7334-0b58-4b23-599e-8f4d88ff9202.png)

`Oculus.VR` フォルダに属するクラスがあることがわかります。これらが解析に重要であれば残しても良いですが、ライブラリ側コードですから今回は除外しましょう。
`Oculus.VR`の四角を選択して `Delete` キーを押すか、または `x` ボタンで除外することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/6ed2db2d-93c8-b574-7c14-82ce81fdc715.png)

これで、だいぶ余分な型は消せたのではないかと思います。あとは見やすくしてみましょう。
真ん中の四角の `...\Scripts` のところが閉じているので、三角形を押して展開しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/8dedda16-6dba-0a31-5850-7f16ca9b0dfd.png)

それなりに依存関係が見えてきた感じがしますね。たとえば、`VirtualPet` クラスは、フォルダ外部の `MultiToy` クラスや `SpaceshipTrigger` クラスに依存していることが判明しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/7989657a-96b2-f48d-3d61-80f389bf0840.png)

また、VirtualPet と MultiToy は、両方向の矢印がありますので、相互依存になっています。このままでは ScriptsフォルダやMultiToyをasmdef化できないかも、といったことがわかるでしょう。
※Unityでasmdef化すると、独立アセンブリ(DLL)となるため、片方向依存であることが必須要件となります。

また、見やすくする方法はいくつかあります。
何度か触っているツールバーのグルーピングのアイコンから `Do Not Group` を選択すれば、すこしすっきりとするでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/286a6bdb-f4f3-ce4d-acb2-2115092f68c5.png)

ちょっと矢印が混雑していていけてないな、と思った場合、左側のアイコンでレイアウトを変えることができます。
上側の `Organic Layouter` の場合はこちらのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/5d1ed8c8-c167-5773-1af5-c0b345887923.png)

下側の `Business Logic Layouter` の場合はこちらのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/ad28533c-4091-a0a1-0286-86a5d2f0fcfc.png)

個々の要素を自分で並べかえることもできるので、見やすいレイアウトを探ってみましょう。

勘違いしてはいけない点としては、グラフ内に追加された要素すべてを可視化したとはいえない点です。ここまでの流れはあくまで `VirtualPet` クラスが直接依存しているクラスについて可視化したものです。VirtualPets以外については、完全に可視化されたとは言い難い状況です。さらにほかのクラスについて着目したい場合は、そのクラスのメニューから `Add All Refernced Types` を実行し、再度クリーンアップの手順を踏むと良いでしょう。

## そのほかできること

* 特定のクラスを利用しているクラス・型をすべて図に追加する。
  上記の手順では、あくまでクラスが参照している型を追加しましたが、逆に参照されているほう `Usages` を追加することもできます。
  クラスの上にカーソルをしばらくホバーするとでてくる画面から、`Add All Usages to the Diagram` を選択しましょう。

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/df3149e1-202e-8c5e-b180-325df8fa92ff.png)

  追加されました。
 
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/67468efb-93ac-5296-0334-42f2c44cd643.png)

* 任意の型をソリューションエクスプローラーで選択して、Type Dependency Diagram にドラッグ＆ドロップで追加することができます。

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/eb32c01d-6c3b-4599-110a-430b13432c17.png)

  追加されました。

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/ae38dc49-4204-d2e1-1f95-d9543be69279.png)

* 任意の型を `Type to search` の欄から検索して追加することができます。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/afb2dc30-af5f-4e25-4f5c-ae030b088695.png)


* ツールバーのFilterアイコンから、表示する関連のタイプをON/OFFできます。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71421/ba665fce-b8a5-205b-bb5f-670104b96df1.png)



## 注意点

* コードの規模によっては、解析やレイアウト変更にかなりの時間がかかります。この場合でも、上で説明したテクニックで不要なファイルを削除するのがおすすめです。

## おしまい

コードをリファクタするとき、asmdef化するときや、コードの全体像を明らかにしたいときなどに利用してみると良いと思います！

## 参照

公式の解説です
https://pleiades.io/help/resharper/Exploring_Type_Dependency_Graph.html

## 宣伝

Psychic VR Lab では、Unityエンジニアを募集しています！