DFDは、”軽く描ける”ことを優先した

Model Weave
この記事は約10分で読めます。

前回は、ER図・クラス図・DFDでは、同じ“線”に見えても意味が違うという話を書いた。

ERでは、関係はEntity側に置くのが自然だった。
Classでは、単体定義とdiagram定義の両方に役割があった。
そしてDFDでは、Flowそのものがdiagramの主役になる。

今回は、そのDFDをModel Weaveでどう扱うことにしたのかを書いてみたい。

DFDは、ER図やクラス図と少し性格が違う。
ER図やクラス図は、ある程度きちんと定義された部品を並べて関係を見ることが多い。
一方でDFDは、もっと早い段階で使いたくなる。

以前構築した事のある倉庫管理のシステムで例えれば、外部システムと自社システムの間で、どんなデータが流れているのか。
荷主システムから何が来て、変換処理を通って、WMSに何が入るのか。
作業システムへどんな指示が出て、どんな実績が戻ってくるのか。

こうした話は、まだ詳細なデータ定義や処理定義が固まっていなくても描きたい。
むしろ、最初にざっくり描きたい。

だからDFDでは、最初から厳密に作り込みすぎるより、軽く描き始められることを優先した。

DFDでは「流れ」が主役になる

DFDで見たいのは、個々の部品そのものよりも、データの流れだ。

もちろん、外部実体、プロセス、データストアといった要素は必要になる。
ただ、それらは最終目的ではない。
知りたいのは、どのデータが、どこからどこへ流れるのかだ。

この点が、ER図やクラス図とは少し違う。

ERでは、テーブル定義が強い。
カラムやインデックス、外部キーがあり、Entityそのものがかなり重要な設計資産になる。

Classでも、単体のクラス定義には意味がある。
属性、メソッド、責務、依存関係を持ち、クラス単体で読んでも価値がある。

一方、DFDでは、個々のobjectだけを見ても全体像はわかりにくい。
外部実体やプロセスの説明よりも、それらの間をどんなデータが流れているかが重要になる。

だからModel Weaveでは、DFDのFlowを dfd_diagram 側に置くことにした。
dfd_object にFlowを持たせるのではなく、diagramの中でObjectsとFlowsを並べて、データの通り道を表現する。

この判断は、第4回で書いた「正本をどこに置くか」という話の続きでもある。
DFDでは、Flowの正本はdiagram側にある方が自然だった。

最初から全部を個別ファイルにしない

DFDを考えていて、もう一つ大事だと思ったのが、最初から全部を個別ファイルにしないことだった。

Model Weaveでは、DFDの単体要素として dfd_object を用意している。
外部実体、プロセス、データストアを1ファイル1オブジェクトとして定義できる。

これは再利用したい要素には向いている。
たとえば、複数のDFDで同じ外部システムを使う場合や、重要なプロセスを別の図でも参照したい場合には、dfd_object として切り出した方がいい。

ただ、DFDを描き始める最初の段階では、そこまでしたくないことも多い。

「荷主システム」
「通信データ変換システム」
「在庫管理システム」
「庫内作業システム」
「在庫データ」

まずは、このくらいの名前だけで置いて、流れを見たい。
すべてを個別ファイル化してからでないと図が描けない、となると重い。

そこで、dfd_diagram のObjectsでは、外部 dfd_object 参照だけでなく、diagram内だけで使うlocal objectも扱えるようにした。

つまり、DFDでは次の二つを両立させている。

再利用したいもの
-> dfd_object として個別ファイル化する

その図の中だけで軽く置きたいもの
-> dfd_diagram の local object として書く

この方が、DFDらしい使い方に合っている。

最初はlocal objectで軽く描く。
後から重要になったものだけ dfd_object に切り出す。
この流れなら、初期検討と詳細化の両方に対応しやすい。

local objectを正式に扱うことにした

local objectは、単なる手抜きではない。
DFDにおいては、かなり実用的な表現だと思っている。

初期のシステム間連携図では、まだ名前しか決まっていない外部システムや、仮の処理単位がよく出てくる。
この段階で、すべてにIDを振り、単体ファイルを作り、説明を書いていくのは少し重い。

それよりも、diagram内でこう書けた方が始めやすい。

| id | label | kind | ref | notes |
|---|---|---|---|---|
| CLIENT | 荷主システム | external | | 固定長連携 |
| CONVERT | 通信データ変換システム | process | | 固定長/CSV変換 |
| WMS | 在庫管理システム | process | | 在庫・入出庫管理 |
| STOCK | 在庫データ | datastore | | 在庫情報 |

このように ref が空でも、diagram内のlocal objectとして扱える。
そしてFlowsでは、その id を使って流れを書く。

| id | from | to | data | notes |
|---|---|---|---|---|
| FLOW-INBOUND-PLAN | CLIENT | CONVERT | 入庫予定データ | 固定長 |
| FLOW-INBOUND-CSV | CONVERT | WMS | 入庫予定CSV | CSV変換後 |
| FLOW-STOCK-UPDATE | WMS | STOCK | 在庫更新 | |

このくらいの軽さで書けると、DFDはかなり使いやすくなる。

大事なのは、local objectを「未完成だから仕方なく許すもの」として扱わないことだ。
Model Weaveでは、local objectも正常な表現として扱う。
再利用が必要になったら、あとで dfd_object に切り出せばいい。

これは、Markdownを正本にするうえでも相性がいい。
最初は軽く書き、後から必要に応じて分割する。
設計を育てていく流れに合っている。

Flowsだけで勝手にnodeを作らない

軽く描けるようにする一方で、何でも自動補完しすぎないようにもした。

特に大事なのは、Flowsだけからmissing nodeを暗黙生成しないことだ。

たとえば、Flowsにこう書いたとする。

| id | from | to | data | notes |
|---|---|---|---|---|
| FLOW-001 | CLIENT | WMS | 入庫予定データ | |

このとき、Objectsに CLIENTWMS が定義されていなかったら、勝手にnodeを作ることもできる。
その方が一見便利に見える。

ただ、それをやると、書き間違いと意図的な省略の区別がつきにくくなる。
WMS と書くつもりが WMS1 と書いてしまっても、勝手に新しいnodeが作られてしまう。
それではdiagnosticsの意味が薄くなる。

だから、Flowのfrom/toはObjectsに定義されたものを解決する。
Objectsにないものは、暗黙生成せず、未解決として扱う。

ここは、軽さと整合性のバランスだと思っている。
local objectによって軽く書けるようにはする。
ただし、Flowに出てくる登場人物はObjectsに明示する。
このくらいの制約があった方が、後から読んだときに安心できる。

DFDはMermaid-firstに寄せた

DFDの描画については、Mermaid-firstに寄せることにした。

ER図やクラス図では、詳細な表示やクリック操作、情報量の多いレビューのためにcustom rendererにも意味がある。
一方でDFDは、流れの見通しや自動レイアウトの価値が大きい。

DFDでは線が多くなりやすい。
外部実体、プロセス、データストアが増えると、手で線の配置を調整するのはかなりつらい。
しかも、初期段階のDFDでは「まず流れを見たい」ことが多い。

この用途では、Mermaidの自動レイアウトが向いている。
Model Weave側で独自のDFD custom rendererを維持し続けるより、MarkdownからMermaidの flowchart LR を生成する方が、実用上のバランスがよかった。

もちろん、Mermaidにも限界はある。
大規模な図では読みづらくなるし、細かいクリック遷移や線の制御には制約がある。
ただ、DFDについては、それでもMermaid-firstでよいと判断した。

DFDで大事なのは、最初から完璧な見た目を作ることではない。
データの流れを早く見える形にすることだ。

そのため、Model WeaveではDFDをMermaid-first、実質的にはMermaid-onlyに寄せている。
rendererを切り替えるより、Markdownの書き方を安定させ、そこから自動的にDFDが立ち上がることを優先した。

Mermaidは正本ではなく派生出力

ここで誤解しないようにしたいのは、Mermaidを使うからといって、Mermaid記法を正本にしたわけではないということだ。

Model Weaveの考え方では、正本はMarkdownのmodel fileにある。
Mermaidは、そこから生成される派生出力だ。

つまり、ユーザーが直接Mermaidを書いてDFDを管理するのではなく、ObjectsFlows のテーブルを書く。
その結果として、Model WeaveがMermaidのflowchartを生成する。

この分け方はかなり重要だ。

Mermaidを直接書くと、自由度は高い。
しかし、Model Weaveとして参照解決やdiagnosticsを行うには、ObjectsとFlowsが構造として読めた方がいい。

Markdown table
-> Objects / Flows として解釈
-> diagnostics
-> Mermaid生成
-> Preview / PNG export

この順番にすることで、人間が読みやすいテキストと、図として見やすい出力を両立しやすくなる。

図は便利だが、図を正本にしない。
これはERやClassと同じで、DFDでも変えなかった。

DFDは、設計の早い段階で効く

DFDを入れてみて感じたのは、これはかなり早い段階の設計に向いているということだった。

ERやClassは、ある程度対象が整理されてから書きやすくなる。
もちろん初期から使うこともできるが、テーブルやクラスの名前、責務、関係がある程度見えていた方が書きやすい。

それに比べてDFDは、もっと手前で使える。

まだテーブルが決まっていない。
クラスも決まっていない。
画面も詳細化されていない。
でも、外部から何が来て、内部で何を通り、どこへ出ていくのかは話せる。

この段階でDFDがあると、議論がかなり進めやすい。

特に業務システムでは、外部システム連携、ファイル連携、CSV、固定長、API、画面入力、バッチ処理など、データの流れが複雑になりやすい。
そこを最初に見える形にできると、後のER、data_object、mapping、app_processにもつなげやすい。

DFDは、詳細設計の完成形というより、設計を始めるための地図に近い。
だからこそ、軽く描けることに価値がある。

## ここまでで、Model Weaveの最初の流れが見えてきた

ここまでの記事で、Model Weaveの最初の流れはだいぶ見えてきたと思う。

最初に、AIと小説を書く中で、構造化された設定情報の価値に気づいた。
そこから、設計資産も人間とAIの両方が扱いやすい形で残せないかと考えるようになった。

次に、独立ツールではなくObsidianプラグインに切り替えた。
Markdownの保管や編集、検索、リンクといった基盤はObsidianに任せ、自作部分は構造の解釈と表示体験に集中するためだ。

その上で、まずER図とクラス図を形にした。
さらに、RelationやFlowの正本をどこに置くかを整理し、ER、Class、DFDで持ち方を変える判断をした。

そして今回は、DFDを軽く描けるようにした理由を書いた。

Markdownを正本にする。
図は派生ビューとして扱う。
ERやClassでは構造を読む。
DFDでは流れを見る。
そして、Obsidianの中で編集と確認を往復できるようにする。

このあたりまで来て、Model Weaveが何を目指しているのかは、かなり説明しやすくなってきた。

まだ全部が完成しているわけではない。
ただ、リリースに向けて、ツールとしての輪郭はかなりはっきりしてきたと思う。

次に書くなら、実際にModel Weaveで何ができるのか、どの形式が安定していて、どこがまだ発展中なのかを整理してみたい。
開発経緯の話から、少しずつ使い方の話へ移っていく段階に入ってきた。

コメント

タイトルとURLをコピーしました