ChatGPTで依存関係の可視化がうまくいかずに悩んでいたところ、以下のポストでClaudeを使ってMermaid図を生成するとよいことを教えてもらいました。
こちらを参考に、何が可視化できればよいかを整理したうえで、Mermaid図を生成するためにはどのようなプロンプトが必要かを考えます。
依存関係の可視化は何のためにどんな要素が必要か
Power Appsの構成要素はアプリ、画面、コントロール、入出力・動作プロパティとツリー構造になっており、これに加えて変数やデータソースがあります。
何のために必要か
この構造によって通常のプログラミング言語よりもオブジェクトごとにコードが散らばっており、機能のロジックを人に説明したりバグを改修したりするときに大きなハードルになっています。
依存関係を可視化することで、ドキュメント作成・バグの改修・リファクタリングなどにかかる工数や対応漏れを大幅に少なくすることができると思います。
どんな要素が必要か
依存関係を表す図に含まれるべき要素(ノード)としては、大別してオブジェクト(とそのプロパティ)、変数、データソースの三種類があります。
また依存関係を示す線(エッジ)は、オブジェクトごとのツリー構造や要素ごとの依存関係を表すものが必要です。
それぞれが線がオブジェクトにかぶったり、視覚的にわかりやすい色分けがされていることも可視化する上では重要になります。
実際にやってみた
何のためにどんな要素が必要かというところが整理できたので、実際にMermaid図を生成してみます。
以下のプロンプトとYAMLファイルを入力します。
ソースのアプリはこちら↓
これらのyamlファイルはPower Appsで作成したテトリス風ゲームのソースコードです。
これをソースにして後続の指示に従い変数、プロパティやコントロールそれぞれの依存関係や親子関係を、
網羅的で完璧にMermaid図にしたものを時間をかけてもよいので生成してください。
Power Appsには以下の大別して■の三要素があり、その中にもそれぞれ設計要素などが含まれています。
■オブジェクト
・画面
・コントロール
・入出力プロパティ
■変数
・名前付き計算式
・グローバル変数
・コンテキスト変数
・コレクション
■データソース
・データソース
・コネクタ
Mermaid図が必要な理由:
・この構造によって通常のプログラミング言語よりもオブジェクトごとにコードが散らばっており、機能のロジックを人に説明したりバグを改修したりするときに大きなハードルになっています。
・依存関係を可視化することで、ドキュメント作成・バグの改修・リファクタリングなどにかかる工数や対応漏れを大幅に少なくしたいです。
Mermaid図に必要な要素と条件:
・依存関係を表す図に含まれるべき要素(ノード)としては、大別してオブジェクト(とそのプロパティ)、変数、データソースの三種類があります。
・また依存関係を示す線(エッジ)は、オブジェクトごとのツリー構造や要素ごとの依存関係を表すものが必要です。
・それぞれが線がオブジェクトにかぶったり、視覚的にわかりやすい色分けがされていることも可視化する上では重要になります。
・画面、コントロール、入出力プロパティのツリー構造が視覚的にわかる
・変数・データソースと入出力プロパティの依存関係が線でつながっている
・コントロールとその入出力プロパティの親子関係が線でつながっている
・ノードとエッジが省略されることなくすべて網羅的にMermaid図上に存在している
このプロンプトで以下のMermaid記法の文字列が生成されました。
flowchart TD
%% 色の定義
classDef screen fill:#e6f3ff,stroke:#0066cc
classDef control fill:#fff2cc,stroke:#d6b656
classDef property fill:#d5e8d4,stroke:#82b366
classDef namedFormula fill:#f8cecc,stroke:#b85450
classDef globalVar fill:#e1d5e7,stroke:#9673a6
classDef contextVar fill:#dae8fc,stroke:#6c8ebf
classDef collection fill:#fff2cc,stroke:#d6b656
classDef dataSource fill:#d5e8d4,stroke:#82b366
classDef connector fill:#ffe6cc,stroke:#d79b00
subgraph Objects["オブジェクト"]
subgraph Screens["画面"]
Screen1[Screen1]:::screen
end
subgraph Controls["コントロール"]
ImageBackGround[ImageBackGround]:::control
GalleryBoard[GalleryBoard]:::control
Timer1[Timer1]:::control
SliderHorizontal[SliderHorizontal]:::control
SliderVertical[SliderVertical]:::control
ContainerRight[ContainerRight]:::control
ButtonRight[ButtonRight]:::control
ContainerLeft[ContainerLeft]:::control
ButtonLeft[ButtonLeft]:::control
ContainerStart[ContainerStart]:::control
ButtonStart[ButtonStart]:::control
TextInputKeyBoard[TextInputKeyBoard]:::control
SliderHorizontalKeyBoard[SliderHorizontalKeyBoard]:::control
ContainerScore[ContainerScore]:::control
LabelScore[LabelScore]:::control
AudioBGM[AudioBGM]:::control
AudioSE[AudioSE]:::control
LabelChain[LabelChain]:::control
ToggleBGM[ToggleBGM]:::control
ToggleSE[ToggleSE]:::control
GalleryQues[GalleryQues]:::control
ButtonGuide[ButtonGuide]:::control
ContainerGuide[ContainerGuide]:::control
ButtonGuideClose[ButtonGuideClose]:::control
LabelGuide[LabelGuide]:::control
ContainerGameOver[ContainerGameOver]:::control
ButtonTryAgain[ButtonTryAgain]:::control
LabelScore_1[LabelScore_1]:::control
LabelScore_2[LabelScore_2]:::control
ImageX[ImageX]:::control
end
subgraph Properties["入出力プロパティ"]
Screen1_OnStart[OnStart]:::property
GalleryBoard_Items[Items]:::property
GalleryBoard_OnSelect[OnSelect]:::property
Timer1_OnTimerEnd[OnTimerEnd]:::property
SliderHorizontal_OnChange[OnChange]:::property
SliderVertical_OnChange[OnChange]:::property
ButtonRight_OnSelect[OnSelect]:::property
ButtonLeft_OnSelect[OnSelect]:::property
ButtonStart_OnSelect[OnSelect]:::property
TextInputKeyBoard_Default[Default]:::property
AudioBGM_Loop[Loop]:::property
AudioSE_AutoStart[AutoStart]:::property
GalleryQues_Items[Items]:::property
ButtonGuide_OnSelect[OnSelect]:::property
ContainerGameOver_Visible[Visible]:::property
ButtonTryAgain_OnSelect[OnSelect]:::property
end
end
subgraph Variables["変数"]
subgraph NamedFormulas["名前付き計算式"]
MovingMino[MovingMino]:::namedFormula
MovingRng[MovingRng]:::namedFormula
end
subgraph GlobalVars["グローバル変数"]
_Score[_Score]:::globalVar
_chain[_chain]:::globalVar
_guide[_guide]:::globalVar
_gameOver[_gameOver]:::globalVar
_SE[_SE]:::globalVar
end
subgraph ContextVars["コンテキスト変数"]
ctx_SelectedBlock[SelectedBlock]:::contextVar
end
subgraph Collections["コレクション"]
ColBlocks[ColBlocks]:::collection
ColBoard[ColBoard]:::collection
ColQue[ColQue]:::collection
ColScore[ColScore]:::collection
end
end
subgraph DataSources["データソース"]
LocalStorage[LocalStorage]:::dataSource
end
subgraph Connectors["コネクタ"]
PowerAppsConnector[PowerAppsConnector]:::connector
end
%% オブジェクトの階層構造
Screen1 --> ImageBackGround
Screen1 --> GalleryBoard
Screen1 --> Timer1
Screen1 --> SliderHorizontal
Screen1 --> SliderVertical
Screen1 --> ContainerRight
Screen1 --> ContainerLeft
Screen1 --> ContainerStart
Screen1 --> TextInputKeyBoard
Screen1 --> SliderHorizontalKeyBoard
Screen1 --> ContainerScore
Screen1 --> AudioBGM
Screen1 --> AudioSE
Screen1 --> LabelChain
Screen1 --> ToggleBGM
Screen1 --> ToggleSE
Screen1 --> GalleryQues
Screen1 --> ButtonGuide
Screen1 --> ContainerGuide
Screen1 --> ContainerGameOver
ContainerRight --> ButtonRight
ContainerLeft --> ButtonLeft
ContainerStart --> ButtonStart
ContainerScore --> LabelScore
ContainerGuide --> ButtonGuideClose
ContainerGuide --> LabelGuide
ContainerGameOver --> ButtonTryAgain
ContainerGameOver --> LabelScore_1
ContainerGameOver --> LabelScore_2
ContainerGameOver --> ImageX
%% プロパティとコントロールの関連
Screen1 --> Screen1_OnStart
GalleryBoard --> GalleryBoard_Items
GalleryBoard --> GalleryBoard_OnSelect
Timer1 --> Timer1_OnTimerEnd
SliderHorizontal --> SliderHorizontal_OnChange
SliderVertical --> SliderVertical_OnChange
ButtonRight --> ButtonRight_OnSelect
ButtonLeft --> ButtonLeft_OnSelect
ButtonStart --> ButtonStart_OnSelect
TextInputKeyBoard --> TextInputKeyBoard_Default
AudioBGM --> AudioBGM_Loop
AudioSE --> AudioSE_AutoStart
GalleryQues --> GalleryQues_Items
ButtonGuide --> ButtonGuide_OnSelect
ContainerGameOver --> ContainerGameOver_Visible
ButtonTryAgain --> ButtonTryAgain_OnSelect
%% 変数とプロパティの依存関係
MovingMino --> Timer1_OnTimerEnd
MovingMino --> SliderHorizontal_OnChange
MovingMino --> ButtonRight_OnSelect
MovingMino --> ButtonLeft_OnSelect
MovingRng --> Timer1_OnTimerEnd
_Score --> LabelScore
_Score --> LabelScore_1
_chain --> LabelChain
_guide --> ContainerGuide
_gameOver --> ContainerGameOver_Visible
_SE --> AudioSE_AutoStart
ctx_SelectedBlock --> GalleryBoard_OnSelect
ColBlocks --> Screen1_OnStart
ColBoard --> Screen1_OnStart
ColBoard --> GalleryBoard_Items
ColBoard --> Timer1_OnTimerEnd
ColQue --> Screen1_OnStart
ColQue --> GalleryQues_Items
ColScore --> Screen1_OnStart
%% データソースと変数の関連
LocalStorage --> ColScore
%% コネクタとデータソースの関連
PowerAppsConnector --> LocalStorage
%% 主要なゲームロジックの流れ
Timer1_OnTimerEnd -->|ブロック移動| ColBoard
SliderHorizontal_OnChange -->|水平移動| ColBoard
SliderVertical_OnChange -->|垂直移動| ColBoard
ButtonRight_OnSelect -->|回転| ColBoard
ButtonLeft_OnSelect -->|回転| ColBoard
ButtonStart_OnSelect -->|ゲーム開始/リセット| ColBoard
ButtonStart_OnSelect -->|ゲーム開始/リセット| ColQue
ButtonStart_OnSelect -->|ゲーム開始/リセット| _Score
ButtonTryAgain_OnSelect -->|ゲームリセット| ColBoard
ButtonTryAgain_OnSelect -->|ゲームリセット| ColQue
ButtonTryAgain_OnSelect -->|ゲームリセット| _Score
ButtonTryAgain_OnSelect -->|ゲームリセット| _gameOver
%% 注釈
classDef note fill:#f9f,stroke:#333,stroke-width:2px;
class Note1,Note2,Note3 note;
Note1["ColBoardはゲームの
メイングリッドを表す"]
Note2["MovingMinoは現在
移動中のブロックを追跡"]
Note3["_Scoreはゲーム中
常に更新される"]
ColBoard --- Note1
MovingMino --- Note2
_Score --- Note3
複雑すぎて線が被ってしまってますが、依存関係の可視化には成功しました。
コメント