🧜♀️
【Mermaid記法】グロい図の治療法【結論、割とあたりまえのことをやっていく】
- Mermaid 使ってるけど図が煩雑になりがちな方の助けになるといいな~
背景
- 開発中ライブラリのプログラム関係図を作って、構成をわかりやすくしよう!
- Codex に頼んじゃお~😋
結果↓
実際のコード
graph TD
%% API
classDef highlight stroke-width:8px
SoundSystem:::highlight
SoundPresetProperty
SerializedBGMPresetDictionary
SerializedSEPresetDictionary
SerializedListenerPresetDictionary
%% Player
BGMManager
SEManager
ListenerEffector
%% Loader & Cache
ISoundLoader
SoundLoader_Addressables
SoundLoader_Resources
SoundLoader_Streaming
SoundLoaderFactory
ISoundCache
SoundCache
IEvictionStrategy
EvictionStrategy_LRU
EvictionStrategy_TTL
EvictionStrategy_Random
SoundCacheFactory
%% Pool
IAudioSourcePool
AudioSourcePool_Base
AudioSourcePool_FIFO
AudioSourcePool_Strict
AudioSourcePoolFactory
%% Relations
SoundSystem -->|利用| BGMManager
SoundSystem -->|利用| SEManager
SoundSystem -->|利用| ListenerEffector
SoundSystem -->|プリセット読込| SoundPresetProperty
SoundSystem -->|生成| SoundLoaderFactory
SoundLoaderFactory -->|生成| SoundLoader_Addressables
SoundLoaderFactory -->|生成| SoundLoader_Resources
SoundLoaderFactory -->|生成| SoundLoader_Streaming
SoundLoader_Addressables -->|依存| ISoundCache
SoundLoader_Resources -->|依存| ISoundCache
SoundLoader_Streaming -->|依存| ISoundCache
SoundLoader_Addressables -->|間接依存| SoundCacheFactory
BGMManager -->|利用| ISoundLoader
SEManager -->|利用| ISoundLoader
SEManager -->|利用| IAudioSourcePool
SoundCacheFactory -->|生成| SoundCache
SoundCacheFactory -->|生成| EvictionStrategy_LRU
SoundCacheFactory -->|生成| EvictionStrategy_TTL
SoundCacheFactory -->|生成| EvictionStrategy_Random
SoundCache -->|利用| IEvictionStrategy
EvictionStrategy_LRU -->|実装| IEvictionStrategy
EvictionStrategy_TTL -->|実装| IEvictionStrategy
EvictionStrategy_Random -->|実装| IEvictionStrategy
AudioSourcePoolFactory -->|生成| AudioSourcePool_FIFO
AudioSourcePoolFactory -->|生成| AudioSourcePool_Strict
AudioSourcePool_FIFO -->|継承| AudioSourcePool_Base
AudioSourcePool_Strict -->|継承| AudioSourcePool_Base
SoundPresetProperty -->|BGMプリセット| SerializedBGMPresetDictionary
SoundPresetProperty -->|SEプリセット| SerializedSEPresetDictionary
SoundPresetProperty -->|Listenerエフェクトプリセット| SerializedListenerPresetDictionary
- 🤔🤔🤔…
- プロンプトをこねこねして Codex 君により良い図を作ってもらうのもいい
- しかし、その前に「どんな図にすれば見やすいか」を整理したいので本記事を書く
グロ図のチェックポイントと治療法
レイヤー, グループで視覚的に分けられていない
✅解決策 subgraph で囲む
Before
実際のコード
graph TD
SoundPlayer -->|利用| SoundCache_A
SoundPlayer -->|利用| SoundCache_B
SoundPlayer -->|生成| SoundLoader_A
SoundPlayer -->|生成| SoundLoader_B
After
実際のコード
graph TD
SoundPlayer
subgraph Cache
Cache_A
Cache_B
end
subgraph Loader
Loader_A
Loader_B
end
SoundPlayer -->|利用| Cache
SoundPlayer -->|生成| Loader
過剰な情報量
- 例えば、全体を俯瞰するための図で Strategy の派生を全て表示する必要はないかも
✅解決策 まとめる, 抽象化する
Before
実際のコード
graph TD
SomeFactory -->|生成| Some_A
SomeFactory -->|生成| Some_B
SomeFactory -->|生成| Some_C
SomeFactory -->|生成| Some_D
After
実際のコード
graph TD
SomeFactory -->|生成| Some群
矢印の向きがバラバラ
- 「矢印をたどるだけで視線をめっちゃジグザグ動かす必要があるな…」となったら注意
- Mermaid では細かく矢印の位置を指定できないので、矢印の交差自体はよくある
✅解決策 グラフ方向を LR, TD など適宜変更する…
- といったことを考えたが、矢印の発生, 向きはプログラムの関係を表現した結果なので
あまりに酷い場合、図をどうこうするよりもプログラム設計から見直す必要がある
ラベルに使う単語がバラバラ
✅解決策 用いる語彙を統一する
Before
実際のコード
graph TD
A -->|利用| B
A -->|使う| C
A -->|呼び出す| D
A -->|Use| E
After
実際のコード
graph TD
A -->|利用| B
A -->|利用| C
A -->|利用| D
A -->|利用| E
語彙統一の例(私がよく使う C# で考えています)
- 利用:他クラスのメソッドを呼び出す
- 生成:Factory クラス, メソッドによるインスタンス生成
- 依存:コンパイル時に型や設定を参照する
- 継承:クラス継承
- 実装:インターフェース実装
- 必要に応じて「委譲」とかもありカモ
生成AIに頼む場合
- 「このリポジトリのプログラム関係図作って~」とだけ頼むと、
記事冒頭のような図が出力されやすい - 「このリポジトリのプログラム関係図を機能ごとに作ってください。
機能同士の関係を考慮して、メイン以外は適宜「Loader群」のようにまとめてください
1:メイン:CoreSystem
2:メイン:Loader
3:メイン:Cache
4:…」
と書くとクオリティがマシになる
余談
- 「治療法」なんて気取ったタイトルにしましたが、
書いてみると割とあたりまえの内容ばかりでした - こういう図って何て言えばいいんですかね。クラス図とは違いますし。
超余談
- 「マーメイド」ぐらいしか共通点ないんですけど、追憶のマーメイドって曲が好きです
Discussion