Sourcery+mermaidでクラス図を一発生成🤖

[GitHubがmermaidをサポートしましたね！🎉](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/)
早速使ってみたりしていたのですが、「[クラス図も作れるんだー](https://mermaid-js.github.io/mermaid/#/classDiagram)、iOSアプリのあのややこしいところのクラス図作ろうかなー」とかゴニョゴニョしてたら、ピンときました！
これは[Sourcery](https://github.com/krzysztofzablocki/Sourcery)案件だ！自動生成できるんじゃないだろか！

ということでやってみました💪
まだまだバグってそうなんですが、それっぽく動くようになったので晒してみます。

ソースコードは[Gist](https://gist.github.com/zeero/32095f805b89825b32591b195c4bf7e9)に置いてます。

mermaidで表示するために補正いれたりしてます。仕様などの注意書きは `README.md` 読んでください🙏🏼

## 使い方

実行手順は以下の通りです:

1. [Sourcery](https://github.com/krzysztofzablocki/Sourcery)をインストール
・ プロジェクトで使ってるとかがないなら、brewで入れちゃうのが楽です
1. [Gist](https://gist.github.com/zeero/32095f805b89825b32591b195c4bf7e9)からコード一式をダウンロード
1. `.sourcery.yml` を修正して、解析対象のソースコードを指定
・ Sourceryなので、解析対象をディレクトリ単位で指定したり、複数を対象にしたりできます💡
1. ダウンロードしたディレクトリで `sourcery` コマンド実行
1. 同ディレクトリにできた `class_diagram.md` を、GitHub Issueなどmermaid対応してるツールで表示する

## デモ

これを使って、いくつかのOSSを解析してみました。

### [ReSwift](https://github.com/ReSwift/ReSwift)

まずは規模的に手頃なところでReSwift。
![reswift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36771/7fd19b48-6959-65d7-ef30-86a10552efad.png)
無事表示できました🎉

`SubscriptionBox` が、監視に関係しそうなメソッド持ってる `Subscription` と、監視を受ける　`StoreSubscriber` を保持（composition）してるので、監視管理の中心的な役割を持ってそうですね。

あと、不具合ぽい話になってしまいますが、右の方にある `Store` から `StoreType` と `DispatchingStoreType` の両方に、 `realization` の線が引かれちゃってます。
`StoreType` と `DispatchingStoreType` には継承関係があるので、本当は
```
Store ..(realization)..> StoreType --(inheritance)--> DispatchingStoreType
```
という関係性だけでいいのですが、Sourcery&Stencilの仕様的に解消が難しそうでした...
独自で拡張したらなんとかなるのだろうか...🤔

### [RxSwift](https://github.com/ReactiveX/RxSwift)

<img width="256" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36771/a1ae5990-bf9b-22f7-9fcf-d70af7d1100f.png">

RxSwiftは巨大過ぎて表示できない模様😇 

### RxCocoa

RxCocoaだとこんな感じ。
![rxcocoa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36771/2a2f7292-af96-b4e4-64f8-dd61a1a4bc87.png)
うおーー...規模感がすごい
もはや全然見えないですが、敢えて言うなら「横に広い」ライブラリということでしょうか。
UIKitの各クラスに機能追加していってるライブラリなので、さもありなんという感じです。

### [PKHUD](https://github.com/pkluz/PKHUD)

次はUI系からPKHUD。
![pkhud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36771/802b3fa4-93ab-ba56-9c46-2bbdb668a847.png)
なかなかいい感じに表示できました！
UI系ライブラリは一つの課題にフォーカスしてるので、そこまで複雑なクラス構成になることがないのかもですね。
中央辺りにある `PKHUDSquareBaseView` を継承した各ビューが `PKHUDAnimating` プロトコルも実装しているので、四角いビューを表示＆アニメーションできるような構成になっているのがクラス図だけでもわかりました。

### [UhooiPicBook](https://github.com/uhooi/)

最後に、ライブラリではなくアプリでもデモしてみたかったので、 @uhooi さんのUhooiPicBookを拝借してみます🙏🏼
![uhooi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36771/340e2713-903e-60eb-4c12-a062256767ad.png)
注目すべきは

```mermaid
classDiagram

ViewController *-- EventHandler
EventHandler <|.. Presenter
Presenter *-- InteracatorInput
InteracatorInput <|-- Interactor

Interactor *-- InteractorOutput
InteractorOutput <|.. Presenter

```

のあたりでしょうか。VIPERっぽい責務分解で、インターフェイスはCleanArchitectureのInputPort/OutputPortに沿ったプロトコルによって抽象化されているのがわかります。

PresenterとInteractorが循環参照してるようにも見えますが、これは自動生成時にweak参照を考慮できていないためです、、🙇🏻
コードを確認したところ、InteractorはweakでPresenter（にあたるInteractorOutput）を保持しており、循環参照にはなってません。
[weakかどうかはSouceryが情報持ってないので現時点では切り分け難しそうです、、、](http://merowing.info/Sourcery/Classes/Variable.html)

## 感想

ビジュアライズされることで、規模感や中心になるクラスなど、概要把握に役に立ちそうな感触でした💡
また、一度自動生成で全部のクラス分作ってしまってから、欲しいクラスのところだけを切り取って加工するなど、足場としても使えそうです。
Stencilとだいぶ格闘して、リレーションシップとか頑張って実装してみた甲斐がありました。
興味があれば遊んでみてください😃