🧜‍♀️

Mermaidを利用して、簡潔にモデル図を書く

に公開

最近モデル図って結構大事だなぁと感じてるエンジニアの福田です

弊社でもモデル図を書いていこうという流れがあるのは感じてます。ですが、図を書くのって結構大変。自分はdraw.ioを利用することもあるのですが、なんか図を書く際の操作ってボタンぽちぽちって感じでなんか煩わしく感じます。
あと、draw.ioとかで書いた図をバージョン管理しようにもそれはそれで何が変更されたのかが分かりにくいので微妙です。
つまるところエンジニアからしたら結構嫌なんですよね。

そんな中、自分は簡単にまとめちゃいたいものはmermaidを利用して書くようにしてます!
mermaidを利用することで、Markdownテキストでグラフを作成できるようになります!これ、一見難しそうなのですが、一度書いてみちゃえば結構簡単で分かりやすいです!

また、テキストベースでグラフを作成するので、バージョン管理もしやすくなります!テキストベースってことはAIとかに食わせてとりあえず何を作りたいのかを理解させたり、実際に作らせたりすることも容易です!
つまり、最強のツールなわけですよ!うぇーい!

とりあえず基礎としては以下を参照してください!
https://zenn.dev/kento_mm_ninw/articles/8b10afdbef306a

今回はそんなMermaidを利用して、自分が普段よく書く図についてまとめていこうかと思います!

シーケンス図

シーケンス図はベースのものが用意されてます
例えば以下のように書くと、、、

sequenceDiagram
    participant front  as WEB<br>Frontend
    participant back   as WEB<br>Backend
    participant db     as DataBase

    rect rgba(255, 0, 0, 0.2)
        front->>+back : API1リクエスト
        back->>back   : API1処理の実行
        back->>-front : API1のレスポンス
    end
    Note over front: 諸々の処理
    rect rgba(0, 255, 0, 0.2)
        front->>+back : API2リクエスト
        back->>db     : DBのデータを確認
        alt DBにデータがある場合
            back->>back  : 諸々の処理を実行
        else DBにデータがない場合
            back->>db    : DBに新規データを保存
        end
        back->>-front : API2のレスポンス
    end

以下のような出力ができます!

結構シンプルなシーケンス図を簡潔に作ることが可能です

シーケンス図の基本的な書き方は以下のサイトが分かりやすいです
https://qiita.com/run1000dori/items/90f91687cfe7ece50020#条件分岐alt

自分なりにやってることを書いていきます!

色分けをしてやる

rect rgba()という処理で色分けを行うことができます!
色分けをすることによって、境界線がわかりやすくなるので自分は複雑なシーケンス図ほど色分け行ってわかりやすくしてます。ただの遊び心に見える色分けですが、個人的には重宝して利用してます!

長い文章を改行する

mermaidで長いテキストを貼り付けるときは改行を使ってやると良いです
改行の方法はマークダウン記法と同じです。自分は<br>を挟んでやって改行してます。
このやり方は後に出てくるオブジェクト図を書くときとかに利用できるので、覚えておくといいかと!

ちなみにマークダウン記法はいろいろな箇所で利用することが可能!
テキスト中に太字にしたい場所があった場合に**を利用するとかもできちゃいます!

システム関連図

一応Bata版として以下のようなものが用意されています

architecture-beta
    group api(cloud)[API]

    service db(database)[Database] in api
    service disk1(disk)[Storage] in api
    service disk2(disk)[Storage] in api
    service server(server)[Server] in api

    db:L -- R:server
    disk1:T -- B:server
    disk2:T -- B:db

出力は以下の感じ

AWSのサービスとかも読み込めたりするんですが、なんか以下の感じの出力になってしまいます。。。

architecture-beta
    service internet(internet)[Internet]

    group aws(logos:aws)[aws]
    group vpc(logos:aws-vpc)[VPC] in aws
    service elb(logos:aws-elb)[ELB] in vpc
    service ec2(logos:aws-ec2)[EC2] in vpc
    service s3(logs:aws-s3)[S3] in aws

    internet:R -- L:elb
    elb:R -- L:ec2
    ec2:R -- L:s3

AWSのアイコンを利用したければ以下の感じでアイコンを読み込まないといけないようです。
https://mermaid.js.org/config/icons.html
ただ、上記のようなことってただ単に図を描きたいときにやるのは面倒ですよね。。。

こういうのって大変ですし、個人的にはflowchartのグラフを利用して書いてやるのが望ましいと思います。
flowchartだと画像の登録も簡単に行えるってのも良きポイントです!

flowchart LR

internet@{img: "https://api.iconify.design/material-symbols/globe-asia.svg",label: "internet",pos: "b",w: 60,h: 60,constraint: "on"}

subgraph aws[aws]
    subgraph vpc[vpc:v1]
        elb@{ img: "https://api.iconify.design/logos/aws-elb.svg", label: "ELB", pos: "b", w: 60, h: 60, constraint: "on" }
        ec2@{ img: "https://api.iconify.design/logos/aws-ec2.svg", label : "Ec2", pos: "b", w: 60, h: 60, constraint: "on"}
    end
    s3@{ img: "https://api.iconify.design/logos/aws-s3.svg" , label: "S3", pos: "b", w: 60, h: 60, constraint: "on" }
end
internet --- elb --- ec2 --- s3

出力は以下の感じ

詳しい書き方は以下が参考になりました
https://qiita.com/b-mente/items/89e900dab7319ef502be

一応以下で何点か解説

画像の出力方法

今回の画像出力については以下の構文を利用して行ってます

【要素名】@{ img: 【画像URL】, label: 【ラベル名】, pos: 【ラベルの出力方向】, w: 【横の長さ】, h: 【縦の長さ】, constraint: 【ノードサイズ制限設定】 }

これさえ利用できれば画像の出力が簡潔に行えます!

ユースケース図

残念ながらmerimaidにユースケース図は用意されてないです。悲しい。
基本用意されてないのはグラフを使って誤魔化していきます。
ユースケース図を書くなら以下の感じ

graph TB
    subgraph "Todoアプリ"
        User((ユーザー))
        subgraph "Todo情報"
            Add[登録]
            Edit[編集]
            ViewList[一覧情報]
        end
        subgraph "Todo履歴"
            ViewHistory[履歴情報]
        end
    end
    User --> Add
    User --> Edit
    User --> ViewList
    User --> ViewHistory

出力は以下の感じ

特段語ることもないので次にいっちゃいます

オブジェクト図

オブジェクト図も用意されてないです。mermaid記法でかけるグラフって意外とないので困っちゃいます。。。
でもないなら代用すればいいってことでシンプルにグラフを利用して書いていきます

graph LR
  shop1("【ショップ】<br/>ショップ名:ショップ1<br/>ショップ住所:A地区")
  subgraph userGroup1[ ]
    user1("【ユーザー】<br/>ユーザー名:テスト太郎<br>性別:男性<br>誕生日:2月2日")
    card1("【ポイントカード情報】<br/>名前:カードA<br/>説明:カードAです<br/>カード画像: S3Url1<br/>ポイント:100pt")
  end
  subgraph userGroup2[ ]
    user2("【ユーザー】<br/>ユーザー名:テスト花子<br>性別:女性<br>誕生日:2月2日")
    card2("【ポイントカード情報】<br/>名前:カードB<br/>説明:カードBです<br/>カード画像: S3Url2<br/>ポイント:200pt")
    card3("【ポイントカード情報】<br/>名前:カードC<br/>説明:カードCです<br/>カード画像: S3Url3<br/>ポイント:300pt")
  end
  shop1-->user1
  shop1-->user2
  user1-->card1
  user2-->card2
  user2-->card3

出力はこんな感じ

改行を利用しまくってて、割と見た目は悪いです。しかも使いにくい。なんか他にいいものがあればいいのですが、、、
ですが、一応上記の感じでオブジェクト図は書くことができます!

思ったのはタイトル部分に太文字とかを利用するのはアリかなと思います
それだけでも見やすくできるのかなって感じですね

ドメインモデル図

ドメインモデルはER図のテンプレートを利用することで簡単に書くことができます!

erDiagram
    SHOP {
        string name "ショップ名"
        string address "ショップ住所"
    }

    USER {
        string name "ユーザー名"
        string gender "性別"
        date birthday "誕生日"
    }

    CARD {
        string name "カード名"
        string description "カード説明"
        string imageUrl "カード画像URL"
        int point "ポイント数"
    }

    SHOP ||--o{ USER : ""
    USER ||--o{ CARD : ""

図は以下の感じになります

ドメインモデル図の書き方はER図に似ているものがあるのでテンプレートが流用できる感じですね。
用意されてる要素が少ない分、似てるものは流用する形で作成していけば意外とどんな図でも書けそうです!

ER図の詳しい書き方は以下のサイトとかが参考になると思います!
https://zenn.dev/aldagram_tech/articles/a10166f763d30e

株式会社ソニックムーブ

Discussion