マーメイド#11 状態遷移図1

**ひとりマーメイド11日目**
**状態遷移図1**

## 概要
マーメイドエンジニアのひろきです。こんにちは。
最近流行り（流行らせたい）のマーメイドについて理解を深めていこうと思います。

この記事では状態遷移図の記述について紹介します！

↓↓前回の記事はこちら

https://qiita.com/hirokiwa/items/2bfd3644dc3747419196

## マーメイドで記述する状態遷移図
前回の記事ではクラス図の記法について紹介しました。

今日は状態遷移図の基本的な記述について紹介します。状態遷移図はシステムの動作を記述する図です。

```:mermaid
stateDiagram-v2
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

```mermaid
stateDiagram-v2
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```
## 状態遷移図の見方
状態遷移図はシステムの動作を状態の変化に沿って表現します。

以下の例においてシステムは3つの状態を保持します。

|||
|---|---|
|Wait|待機|
|Do|実行|
|Stop|停止|

```mermaid
stateDiagram-v2
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

プログラムがスタートするとまず待機状態に遷移し、そこから実行状態に移ります。何事もなければそのまま終了し、問題が発生すると停止状態に遷移します。停止状態からは再び実行状態に戻ることもあれば、そのまま終了することもあります。待機状態から停止状態に遷移することはありません。

## ダイアグラムの宣言
状態遷移図は`stateDiagram-v2`で宣言します。
```:mermaid
stateDiagram-v2
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

```mermaid
stateDiagram-v2
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

一部古いレンダラーでは`stateDiagram`と宣言することがあります。
```:mermaid
stateDiagram
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

```mermaid
stateDiagram
    [*] --> Wait
    Wait --> Do
    Stop --> Do
    Do --> Stop
    Do --> [*]
    Stop --> [*]
```

どちらも基本的には同じ出力になりますが、原則最新の`stateDiagram-v2`を使用します。

## 状態の宣言
状態の宣言をします。
`STATE_ID`
ここでは`s1`が状態のIDとなり、それがそのままダイアグラムに反映されます。
```:mermaid
stateDiagram-v2
    s1
```
```mermaid
stateDiagram-v2
    s1
```
状態のIDとダイアグラムを別の表示にしたい場合は以下のように記述します。
`state "DISPLAY" as STATE_ID`
```:mermaid
stateDiagram-v2
    state "Do" as s1
```
```mermaid
stateDiagram-v2
    state "Do" as s1
```

以下のように簡略形で記述することもできます。筆者はこっち派です。
`STATE_ID: DISPLAY`
```:mermaid
stateDiagram-v2
    s1: Do
```
```mermaid
stateDiagram-v2
    s1: Do
```

## 遷移
矢印で状態の遷移を表現します。他のダイアグラムではさまざまなパターンの矢印が提供されていますが、状態遷移図の矢印は1種類です。

以下のように記述します。
`-->`
```:mermaid
stateDiagram-v2
    s1　--> s2
```
```mermaid
stateDiagram-v2
    s1　--> s2
```

## テキストの挿入
`STATE1 --> STATE2: TEXT`
```:mermaid
stateDiagram-v2
    s1　--> s2: 遷移しまーす
```
```mermaid
stateDiagram-v2
    s1　--> s2: 遷移しまーす
```

## 開始と終了
状態遷移図では遷移の開始と停止を表すノードが準備されています。フローチャートとの大きな違いです。

開始・終了共に同様の記述で表現されます。
`[*]`
```:mermaid
stateDiagram-v2
    [*]　--> s1
    s1　--> [*]
```
```mermaid
stateDiagram-v2
    [*]　--> s1
    s1　--> [*]
```

開始・終了の区別は`-->`の右か左かで決まります。

|||
|---|---|
|[*] --> s1|開始|
|s1 --> [*]|終了|

そのため`[*]`を乱立させても正しく開始と終了を区別してくれます。
```:mermaid
stateDiagram-v2
    [*] --> s1
    [*] --> [*]
    s2  --> [*]
    s1  --> s2
    s3  --> [*]
    [*] --> s2
    s2  --> s3
    s1  --> [*]
```
```mermaid
stateDiagram-v2
    [*] --> s1
    [*] --> [*]
    s2  --> [*]
    s1 --> s2
    s3 --> [*]
    [*] --> s2
    s2 --> s3
    s1  --> [*]
```
## 複合状態
1つの状態が内部状態を持つことがあり、これを複合状態といいます。

複合状態の宣言は`{}`で記述を囲みます。
`state STATE_ID {}`
```:mermaid
stateDiagram-v2
    [*] --> s1
    state s1 {
        [*] --> s2
        s2  --> [*]
    }
```
```mermaid
stateDiagram-v2
    [*] --> s1
    state s1 {
        [*] --> s2
        s2  --> [*]
    }
```
また複合状態の中で`[*]`を使用すると新たな開始・終了ノードが配置されます。

複合状態でも状態のIDとダイアグラムを別の表示にすることができます。
`STATE_ID DISPLAY`
```:mermaid
stateDiagram-v2
    s1: 状態1
    [*] --> s1
    state s1 {
        s2: 状態2
        [*] --> s2
        s2  --> [*]
    }
```
```mermaid
stateDiagram-v2
    s1: 状態1
    [*] --> s1
    state s1 {
        s2: 状態2
        [*] --> s2
        s2  --> [*]
    }
```
ただし複合状態に省略記法を適用することはできません。

## 多重複合状態
複合状態を多重に記述することもできます。
```:mermaid
stateDiagram-v2
    [*] --> s1
    state s1 {
        [*] --> s2
        state s2 {
            [*] --> s3
            state s3 {
                [*] --> s4
                s4  --> [*]
            }
        }
    }
```
```mermaid
stateDiagram-v2
    [*] --> s1
    state s1 {
        [*] --> s2
        state s2 {
            [*] --> s3
            state s3 {
                [*] --> s4
                s4  --> [*]
            }
        }
    }
```
## 複合状態同士の遷移
複合状態も通常の状態と同様に1つのノードとして扱うことができます。
```:mermaid
stateDiagram-v2
    [*] --> s1
    s1  --> s2
    s1  --> s3

    state s1{
        [*] --> [*]
    }
    state s2{
        [*] --> [*]
    }
    state s3{
        [*] --> [*]
    }
```
```mermaid
stateDiagram-v2
    [*] --> s1
    s1  --> s2
    s1  --> s3

    state s1{
        [*] --> [*]
    }
    state s2{
        [*] --> [*]
    }
    state s3{
        [*] --> [*]
    }
```

## 定義できない遷移
内部状態から他の複合状態の内部状態に遷移することはできません。

```mermaid
stateDiagram-v2
    [*] --> s1
    s1  --> s2
    s1  --> s3

    state s1{
        [*] --> [*]
    }
    state s2{
        [*]      --> inner_s2
        inner_s2 --> [*]
    }
    state s3{
        [*]      --> inner_s3
        inner_s3 --> [*]
    }
```
ここで`inner_s2`から`inner_s3`への遷移は定義できないということになります。しかしマーメイドは想定されていない記述でも案外レンダリングしてくれることが多いので、無理矢理記述してみます。

```:mermaid
stateDiagram-v2
    [*] --> s1
    s1  --> s2
    s1  --> s3

    state s1{
        [*] --> [*]
    }
    state s2{
        [*]      --> inner_s2
        inner_s2 --> [*]
    }
    state s3{
        [*]      --> inner_s3
        inner_s2 --> inner_s3
        inner_s3 --> [*]
    }
```
```mermaid
stateDiagram-v2
    [*] --> s1
    s1  --> s2
    s1  --> s3

    state s1{
        [*] --> [*]
    }
    state s2{
        [*]      --> inner_s2
        inner_s2 --> [*]
    }
    state s3{
        [*]      --> inner_s3
        inner_s2 --> inner_s3
        inner_s3 --> [*]
    }
```
変な遷移図が完成しました。

## まとめ
状態遷移図の基本的な記法を紹介しました。

↓↓次回の記事はこちら!!

https://qiita.com/hirokiwa/private/b7739d54551ce1656dd1

## 参考

https://mermaid-js.github.io/mermaid/#/