本文へ移動
English

図の描き方の実例

同じ内容を読みにくい図と読みやすい図で描き比べ、dia の図を読みやすくするコツを示します。

Updated View as Markdown

どの例も同じ内容を 2 回描いています。先の図は読みにくく、後の図は dia が AI に渡している描き方の指針(英語)に沿っています。画像はすべて、添えた JSON から dia 自身が描いたものです。同じ直し方を AI に頼むときの参考にしてください。

矢印で表す関係は 1 種類にする

呼び出し、デプロイ、監視、データの書き出しは、それぞれ別の種類の関係です。すべてを矢印で描くと矢印同士が交差し、お客さまがお店を使うときに何が起きるのかを読み取れなくなります。矢印にする関係は 1 種類に絞り、ほかは説明文に書きます。

直す前:呼び出し、デプロイ、監視、書き出しがすべて矢印になっている直す前:呼び出し、デプロイ、監視、書き出しがすべて矢印になっている
直す前:呼び出し、デプロイ、監視、書き出しがすべて矢印になっている
直した後:矢印は呼び出しだけ。ほかは説明文に書いた直した後:矢印は呼び出しだけ。ほかは説明文に書いた
直した後:矢印は呼び出しだけ。ほかは説明文に書いた
- "description": "The online shop and everything around it.",
+ "description": "Arrows show calls made while a customer uses the shop.\n\nGitHub Actions deploys Web and API. Datadog monitors both. PostgreSQL is exported to BigQuery every night.",
  "model": {
    "edges": {
      "visit": { "from": "user", "to": "web" },
      "call": { "from": "web", "to": "api" },
      "query": { "from": "api", "to": "db" },
      "cached": { "from": "api", "to": "cache" },
-     "deployWeb": { "from": "ci", "to": "web" },
-     "deployApi": { "from": "ci", "to": "api" },
-     "watchWeb": { "from": "monitor", "to": "web" },
-     "watchApi": { "from": "monitor", "to": "api" },
-     "export": { "from": "db", "to": "warehouse" }
    }
  }

主な処理を先に書く

矢印が輪になるとき、dia は先に書かれた矢印の向きを保ち、後から書かれた矢印を戻りの矢印として描きます。戻りの矢印を先に書くと、話の終わりから図が始まります。直す前の図では Worker がいちばん上に来て、利用者の依頼が途中から下へ伸びています。

直す前:メールでリンクを送る矢印を先に書いたため、図が Worker から始まる直す前:メールでリンクを送る矢印を先に書いたため、図が Worker から始まる
直す前:メールでリンクを送る矢印を先に書いたため、図が Worker から始まる
直した後:依頼の矢印を先に書き、リンクを送る矢印は戻りとして描かれる直した後:依頼の矢印を先に書き、リンクを送る矢印は戻りとして描かれる
直した後:依頼の矢印を先に書き、リンクを送る矢印は戻りとして描かれる
  "edges": {
-   "notify": { "from": "worker", "to": "user" },
    "request": { "from": "user", "to": "api" },
    "enqueue": { "from": "api", "to": "queue" },
    "pick": { "from": "queue", "to": "worker" },
    "store": { "from": "worker", "to": "bucket" },
+   "notify": { "from": "worker", "to": "user" }
  }

配置の向きを決め、残りの並び方を読む

flow は配置の向きを決めます。"down" は矢印の元を上に、"right" は左に置きます。矢印でつながっていない要素は、配置の向きと直角に並びます。"down" では横に、"right" では縦に並びます。そのため、グループの中身を縦に積みたいときは、そのグループを "down" ではなく "flow": "right" にします。この例では処理が左から右へ流れ、4 つのデータ元が始まりにリストとして並びます。

直す前:Sources を flow down にしたため、中身が横に並ぶ直す前:Sources を flow down にしたため、中身が横に並ぶ
直す前:Sources を flow down にしたため、中身が横に並ぶ
直した後:Sources を flow right にしたため、中身が縦に積まれる直した後:Sources を flow right にしたため、中身が縦に積まれる
直した後:Sources を flow right にしたため、中身が縦に積まれる
  "style": {
    "root": { "flow": "right" },
-   "sources": { "label": "Sources", "flow": "down" },
+   "sources": { "label": "Sources", "flow": "right" },

ラベルは短くする

ラベルは 1 行で描かれるため、長いラベルは図の幅を広げます。矢印のラベルは 1 つごとに 1 行分の間隔を取ります。要素の名前は数語にとどめ、バージョン、台数、設定値は説明文に移します。説明文には Markdown が使えます。

直す前:バージョン、台数、応答時間がラベルに入っている直す前:バージョン、台数、応答時間がラベルに入っている
直す前:バージョン、台数、応答時間がラベルに入っている
直した後:ラベルは短くし、詳しいことは説明文に書いた直した後:ラベルは短くし、詳しいことは説明文に書いた
直した後:ラベルは短くし、詳しいことは説明文に書いた
- "web": { "label": "Storefront (Next.js 15 on Vercel)", "icon": "i:lucide:globe" },
- "api": { "label": "Orders API (Go, 3 replicas behind an ALB)", "icon": "i:lucide:server" },
- "call": { "label": "REST over HTTPS with a JWT, p95 120 ms" },
+ "web": { "label": "Storefront", "icon": "i:lucide:globe" },
+ "api": { "label": "Orders API", "icon": "i:lucide:server" },
+ "call": { "label": "REST" },

詳しいことは説明文に書きます。

How an order is placed.

- Storefront: Next.js 15 on Vercel. Calls the Orders API over HTTPS with a JWT (p95 120 ms).
- Orders API: Go, 3 replicas behind an ALB.
- PostgreSQL 16: 1 primary and 2 read replicas, reached through PgBouncer (pool size 20).
- Stripe: card payments with 3-D Secure through the PaymentIntents API, retried 3 times.

大きなシステムは分けて描く

1 枚の図が答える問いは 1 つにします。サービス、データベース、ワーカーをすべて 1 枚に描くと、どの処理も目立ちません。1 つのドキュメントに複数の図を入れ、まず領域を示す全体図、続いて領域や処理ごとの図を置きます。

直す前:サービス全体を 1 枚に描いている直す前:サービス全体を 1 枚に描いている
直す前:サービス全体を 1 枚に描いている
直した後:領域を示す全体図と、再生ボタンを押したときの処理の図に分けた直した後:領域を示す全体図と、再生ボタンを押したときの処理の図に分けた直した後:領域を示す全体図と、再生ボタンを押したときの処理の図に分けた直した後:領域を示す全体図と、再生ボタンを押したときの処理の図に分けた
直した後:領域を示す全体図と、再生ボタンを押したときの処理の図に分けた

全体図では、サービスをグループにまとめ、領域ごとに矢印を 1 本だけ引きます。

"edges": {
  "hasAuth": { "from": "services", "to": "auth", "type": "contains" },
  "hasPlayback": { "from": "services", "to": "playback", "type": "contains" },
  "api": { "from": "apps", "to": "gateway" },
  "route": { "from": "gateway", "to": "services" },
  "publish": { "from": "services", "to": "kafka" },
  "consume": { "from": "kafka", "to": "workers" }
}

1 枚のまま残したいときは、ビューを足します。dia でビューを選ぶと、挙げた要素と矢印が強調され、ほかは薄く表示されます。

"views": {
  "playback": {
    "title": "Playback",
    "ids": ["api", "toPlayback", "playbackData", "playbackEvents", "toRecommend", "watch", "origin"]
  }
}

変化はステップで見せる

今のやり方と移行後のやり方を比べるときは、両方を 1 枚に描かないでください。共通する要素が 2 回ずつ現れ、左右の配置もばらばらに決まります。代わりに "kind": "steps" のドキュメントを作ります。各図は前の図の写しから始まり、残った要素は同じ位置に描かれるので、変わったところだけが目に入ります。要素を少しずつ増やしながら説明する図にも、同じ形式が向いています。

直す前:今と移行後を 1 枚に並べている直す前:今と移行後を 1 枚に並べている
直す前:今と移行後を 1 枚に並べている
直した後:1 つのドキュメントの 2 ステップにした。営業、顧客、経理は同じ位置のまま直した後:1 つのドキュメントの 2 ステップにした。営業、顧客、経理は同じ位置のまま直した後:1 つのドキュメントの 2 ステップにした。営業、顧客、経理は同じ位置のまま直した後:1 つのドキュメントの 2 ステップにした。営業、顧客、経理は同じ位置のまま
直した後:1 つのドキュメントの 2 ステップにした。営業、顧客、経理は同じ位置のまま
- create_document { "kind": "standard" }   "today" と "later" のグループを持つ図が 1 枚
+ create_document { "kind": "steps" }      図 "today" の次に図 "migrated"

2 つ目のステップでは sales、customer、accounting の ID をそのまま使い、間の矢印だけを入れ替えます。

"edges": {
  "close": { "from": "sales", "to": "salesforce" },
  "sync": { "from": "salesforce", "to": "freee" },
  "invoice": { "from": "freee", "to": "customer" },
  "book": { "from": "freee", "to": "accounting" }
}
メニュー

Type to search…

↑↓ 移動↵ 開くEsc 閉じる