UMLを学ぶETロボコンメンバーに送るUML講座5〜シーケンス図〜 

#シーケンス図とは
シーケンス図とは、**時系列に沿って行われる、オブジェクト同士のメッセージのやり取りによってどのようにシステムが実現されているのかを表現するための図**です。

クラス図では静的にシステムを見つめましたが、**シーケンス図ではシステムの動的な側面**を表現します。

<img width="575" alt="スクリーンショット 2019-03-05 11.24.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/adb410cf-0b2c-8690-e751-1f784449abb2.png">

上記図は、シーケンス図の範囲を示す外枠です。**フレーム**と呼ばれます。
左上に書かれている相互作用名には、この**シーケンス図が何を達成するのかを記述します**。

例えば、ETロボコンであれば、ライントレースする、といった感じに書きます。

ちなみにsdとはSequence Diagram（シーケンスダイアグラム）の略らしいです。

#シーケンス図の要素
###ライフライン
ライフラインとは、**システムにおけるオブジェクト同士のメッセージ送受信をする元になるもの**です。
クラスのインスタンスと対応していると考えてもらって構いません。

<img width="184" alt="スクリーンショット 2019-03-11 16.26.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/d6b164d2-cc07-3347-20a1-c6bf6a0124f1.png">

表記は、図のように四角形の下に破線がついたものです。
**「：（コロン）」の左側が役割名で、右側を分類子名といいます**。

役割名は**そのライフラインがどのような役割を果たすのか**を記述します。
分類子名は**そのライフラインがどのクラスから生成されたものであるのか**を記述します。

**役割名と分類子名のどちらか片一方は省略可能です**。
必要に応じて省略しましょう。
分類子名のみを書く場合には、それが分類子名であることを表すために、**「：”分類子名”」と書く点に注意してください**。

<img width="539" alt="スクリーンショット 2019-03-11 16.24.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/6197304f-a556-7e1e-c2f0-1ef9443dd6ba.png">


###メッセージと実行指定
####メッセージ
**クラス図で言うところの操作は、シーケンス図で言うところのメッセージと対応しています**。
プログラミングででいうと、メッセージの使用はクラスのメソッドの利用と対応します。

<img width="630" alt="スクリーンショット 2019-03-11 16.37.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/748f77fa-777e-18b6-4748-d5d5423c9f4d.png">

メッセージの構文は以下の通りです。
**"属性" = "メッセージ名"（"パラメータ名" = "引数値", ...） : "戻り値"**

**属性は、戻り値を受け取る変数名です**。

メッセージ名はそのままです。**そのメッセージによってどのような処理が行われるのかを表現します**。

パラメータ名は、**メッセージに引数として渡されるパラメータがどのような意味、利用目的を持ったものであるのかを表現します**。
引数値には、どのような値が入るのか、具体的に示します。

例えば、「本を登録する」というメッセージがあったとするなら、「本を登録する（タイトル＝”吾輩は猫である”）」と記述することができます。
このパラメータ名と値は省略できます。どちらか一方のみの省略も可能なので、表現したい物事、必要な詳細度に応じて省略していきましょう。

なお、のちに言いますが、属性と戻り値も省略できるので、「本を登録する（タイトル＝”吾輩は猫である”）」のようになっています。

戻り値は、**メッセージを送信した結果どのような値が返ってくるのかを表現するもの**です。
プログラムを記述する際の関数の戻り値と対応しています。
戻り値がない場合には省略してしまいましょう。

**省略可能なものは、属性、引数、戻り値**です。
ここでいう引数はパラメータ名とその値のことです。先ほど記述したようにどちらか一方の省略も可能です。

####実行指定
ライフラインがメッセージを他のオブジェクトに送る時、ライフラインの点線上には**実行指定**と呼ばれる白い四角が生成されます。

インスタンス間の協調動作として、メッセージを送ったらそのメッセージに応じてまた他のインスタンスにメッセージを送る、というように実際のプログラムは動くわけですが、実行指定は、そういったメッセージのやり取りが完全に終わるところまで伸ばさねばなりません。

他クラスのインスタンスに移譲した処理が終われば元の実行中プログラムに戻ってくるわけですからね。

つまり、

<img width="605" alt="スクリーンショット 2019-03-11 16.54.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/1fe6a3cb-a451-2f9b-58e3-2408783c3dd4.png">


のように大元の実行指定が作った実行指定が終わっていない段階で実行指定を小さく書くことには問題があります。このような場合は、

<img width="619" alt="スクリーンショット 2019-03-11 16.54.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/70383449-3d92-273c-40a7-90d105965955.png">


のように他のクラスに移譲した処理が終了し終わるところまで、大元の実行指定は伸ばさなければなりません。

#####同期メッセージ
同期メッセージとは、**送信したメッセージが終了するまで次の処理に移らない性質を持つメッセージ**です。

これまでのメッセージの説明で出てきたものは全て同期メッセージです。

見てきたように、同期メッセージの場合は**矢印の先が黒塗りの三角形になる**ことに注意してください。

非同期処理などを行わない場合は、こちらの方を利用します。
**プログラムは逐次処理が基本なので、以下で説明する非同期メッセージよりもこちらを使用する頻度の方が多いです**。

###メッセージの種類
#####非同期メッセージ
非同期メッセージとは、**送信したメッセージの終了を待たずに次の処理に移る性質を持つメッセージ**です。

これにより、非同期で処理を行っていくことを表現できるわけですね。

<img width="633" alt="スクリーンショット 2019-03-11 16.57.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/ebfb5bfc-0f2d-a345-aec6-f3eb3e1a7799.png">


図のように、**非同期メッセージの矢印の形式は、矢羽形式になっています**。
このように記述すると、本の登録が完了するのを待たずに他のメッセージを他のライフラインに向けて送信することができるということになります。

#####リプライメッセージ
リプライメッセージとは、送信したメッセージが終了したことを表現するものです。

<img width="631" alt="スクリーンショット 2019-03-11 17.02.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/f7b2e971-c7b8-8241-d78d-bfaf612eb661.png">


メッセージを送信してきたライフラインに対して点線の矢印を返します。
同期メッセージだろうと非同期メッセージだろうと点線で、普通の矢羽で記述します。

リプライメッセージは省略も可能です。

なんのメッセージが終了したのかを示す注釈表示が存在するようですが、ぶっちゃけ元のメッセージを見ればでわかるので説明しません。

#####生成メッセージ
クラスからインスタンスを生成するような時に使用します。
点線矢印の先に生成するライフラインを記述します。

<img width="382" alt="スクリーンショット 2019-03-11 20.19.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/f5094ecf-f655-1849-5170-02d51847eb5c.png">

上記シーケンス図はスーパーマ◯オブラザーズ的なゲームを参考に考えてみました。
ステージが操作キャラクターの敵を生成するような場合、このような記述になります。

#####ファウンドメッセージ
ファウンドメッセージは、メッセージの**送信側を省略して書くメッセージ**のことです。

<img width="372" alt="スクリーンショット 2019-03-11 20.31.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/404ddc56-7cc9-ec50-bb98-810a8ead1be4.png">


黒い丸で送信側を表現し、矢羽をライフラインの点線状に向かわせます。
送信側のライフラインを話題にする必要がない場合などに使用すると良いと思われます。

例えば、ステージライフラインでの処理を説明したいような時には、上記例のようにファウンドメッセージを用いることで、ステージに入るまでの動作については省略して示すことができるようになります。

#####ロストメッセージ
ロストメッセージは、メッセージの**受信側を省略するメッセージ**のことです。

<img width="413" alt="スクリーンショット 2019-03-11 20.46.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/24261aaf-8362-a618-f8f7-8a8686e4ba88.png">


メッセージの矢印の先に黒い丸をつけます。この丸が受信側のライフラインを示します。
メッセージ送受信の流れをそれ以上追う追う必要がないような場合に使用すると良いでしょう。

上記例のように、コースでの協調動作が話題になっているならば、そこからの動作については記述する必要がありませんので、ロストメッセージを用いています。

###破棄イベント
**破棄イベントはライフラインの削除**を表現します。

<img width="198" alt="スクリーンショット 2019-03-11 20.50.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/2e09368c-e4c2-78d7-b6d7-3931992df084.png">


このように、ライフラインの下にバッテンを書くことで破棄イベントの表現となります。

C++などの言語では、new宣言を使いメモリを動的に作成してインスタンスの作成を行ったりします（他のプログラミング言語も内部的にはメモリを確保してるでしょうが）。
インスタンスが不要になった場合、deleteを利用してメモリの解放を行います。
この時の動作が破棄イベントと対応づけられます。


###結合フラグメント
結合フラグメントとは、**制御構造を表現するための領域**です。

<img width="686" alt="スクリーンショット 2019-03-11 21.08.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/38e23bf4-b159-0ff8-dba5-007e991227a0.png">


図はプログラミング言語でいうif-else文を表現する結合フラグメント、alt(オルタナティブ)の表現方法になります。
図のように、実行指定をフレーム（四角形）で囲むことによって、その区間がaltの作用範囲であることを表します。

**フレーム（四角形で囲った領域）が結合フラグメントの影響範囲です**。

#####条件分岐を表現するオルタナティブ(alt)
**プログラミング言語でいう、if-else文、if-else if-else文など（ただしif単体を除く）を表現するのがオルタナティブ(alt)**です。

<img width="687" alt="スクリーンショット 2019-03-11 21.12.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/1ddc02c5-d650-e2d1-af5e-41e260a5f33d.png">


図のようにaltフレーム内で条件を増やす場合には点線で区切っていくことで分岐数を増やすことができます。

各領域に["相互作用制約"]を書き、その条件が満たされた場合にその領域に入ります。
相互作用制約とは、if("条件")の条件と同じだと思ってもらえれば問題ありません。

#####ある条件時だけ追加の処理を行うオプション(option)
alt異なり、**ある条件が満たされた時に一定の処理を追加で行うような場合には、optionを利用します**。

<img width="608" alt="スクリーンショット 2019-03-11 21.43.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/4e2f6d5a-1518-05f9-c8e0-d8f438c1ce08.png">


ほとんどaltと変わりません。
**option領域の処理を行うかどうかを決定する["相互作用制約"]を記述して、option領域内に相互作用制約が満たされた場合の処理を記述します**。
変わっているのは、if-else文で言うところの、else 要素を書くことができないと言う点です。

altとoptionについては、より適している表現を選択してモデルを書いていきましょう。


#####ループ文を表現する(loop)
**プログラミング言語でいうwhile文、do-while文などのループ機構を実現するのがループ（loop）**です。

<img width="585" alt="スクリーンショット 2019-03-11 21.49.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/53635185-9a50-ec3a-4121-0373900a16ea.png">

[”相互作用制約”]と、loop("最小回数","最大回数")による繰り返しの指定が可能です。

相互作用制約による繰り返しの指定は、while文の条件式を想像してもらえればわかりやすいと思います。
**条件式が真になっている間だけ、loop領域の処理が繰り返されます**
上記図のループは相互作用制約が真の時に繰り返される例です。

loopによる繰り返し回数の指定では、色々なものがあります。

- loop: 無限ループ
- loop(6): 6回繰り返す
- loop(1,*): 一回以上

loop("最小回数","最大回数")による指定では、最低でも"最小回数"分は繰り返しの処理を行い、最大で"最大回数"分の繰り返しを行うことを意味します。

この二つの指定方法はloopの方は必ず書かなければなりませんが、相互制約条件は必ずしも書く必要がありません。loopだけの指定で要件を満たせる場合もあるからです。

#####処理の中断~ブレイク（break）~
**ブレイクはループから抜ける際に利用するもの**です。
loopで無限ループの指定があったことからわかるように、きちんとbreakも用意されているのですね。

<img width="590" alt="スクリーンショット 2019-03-11 21.59.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/7267b7a5-fdd3-1b31-e764-bbc60a11f732.png">


”相互制約条件”が満たされた場合に、break領域内の処理を行ってループ領域から抜けます。
ブレイクはループから抜けるためのものなので、当然ループのフレーム内でしか使用することができませんのでご注意を。

#####並行実行~パラレル（par）~
パラレルは、並列して処理を実行することを表現します。

<img width="436" alt="スクリーンショット 2019-03-11 22.19.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/39c90866-265f-74ac-af50-79e4276fc79a.png">

点線で分割された領域内の処理が並列実行されることを表現します。

#####独立した処理〜クリティカル領域(critical)
クリティカル領域は、その**領域内の処理が他から干渉されずに実行されることを保証する表記方法**です。

<img width="435" alt="スクリーンショット 2019-03-11 22.20.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/a06c55c8-30f6-b636-86e9-949b92261b3d.png">

使い方は今までよくわからなかったのですが、並列処理（par）などを実行する際、並列で処理するがために論理的な整合性が失われる場合があります。

そのような場合には、criticalを利用することで、クリティカル領域でやり取りされる処理を保護することができます。

###全体の流れを追いやすくする相互作用の利用(ref)
**シーケンス図が大きくなってくると全体像を捉えることが難しくなってきます**。
**そこで使用するのが相互作用の利用（ref）です**。
またrefを利用することで汎用性の高い処理をいろんな場面で再利用することができるようになったりします。

<img width="783" alt="スクリーンショット 2019-03-11 23.16.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/120edbb4-52f1-c4dc-f52f-b36ac6697c58.png">


上記の図はマ◯オブラザーズ的なゲームでコースを提供する場合のシーケンス図を考えてみた例です（だいぶ雑ですが）。
図が大きくなりすぎるので（半分建前）相互作用の利用を使うことで、「コースで遊ぶ」ことについて分割しています。

上記図の相互作用の利用で用いている相互作用名、「コースで遊ぶ」と対応しているシーケンス図が以下になります。

<img width="474" alt="スクリーンショット 2019-03-11 23.16.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/84e55eac-2b5d-1b4e-eb78-c1829048da79.png">

このように、**refフレームに伸ばしたメッセージが、対応するシーケンス図（コースで遊ぶ）のフレームからライフラインへ伸ばすメッセージになります**。

全体の流れがわかりやすくなっていることに相互作用の利用の力を感じてください。

refフレーム内の相互作用名、「コースで遊ぶ」と、シーケンス図の名前が対応していること、refフレームに伸ばされた「コースに入る（）」というメッセージ名が「コースで遊ぶ」のシーケンス図の最初のメッセージと一致しているということもポイントです。

注意点として、**refフレームの上に関係のあるライフラインを書く必要がありますが、必ずしも全てのライフラインを書く必要はないです**。

某人に相談したら全部書く必要はないと言われてしまいました。
**全体を表すシーケンス図から送られるメッセージを受け取るライフラインだけ、refフレームの上に書けば良いです**。
気をつけよう（自戒）。

#書く時に注意すること
####クラス図との対応関係
シーケンス図とクラス図は対応しています。片方を修正するともう一方の図も修正する必要が出てくる可能性があるので、気をつけましょう。

よく聞くのは、クラス図のクラス名とシーケンス図のライフライン名がタイオウシテイナイヨとか、
クラス図に書いてない操作がシーケンスでデテキテルヨとか、
まあ色々ありますが、要は**二つの図は関連しあってるので修正の影響がもう一方の図に影響をしてないかを逐一チェックすることが必要である**、ということです。気をつけましょう。

####シーケンス図は具体的な処理そのものを記述するものではない
シーケンス図は、ライフライン同士のメッセージのやり取りを表現するためのものであって、実装時のような具体的な処理は記述しません。

例えば、メッセージとして、「結果＝足し算する（"５", "4"）:整数」などといったことは書きません。
そういった関数がライフラインに用意されているなら別ですが、何れにせよ細かすぎる内容はシーケンス図で表すものではありません。

そういう場合はアクティビティ図を用いると良いでしょう。

##まとめ
- シーケンス図は時系列でライフライン（インスタンス）のメッセージ（メンバ関数）のやり取りを表現する図である。
- クラス図とシーケンス図は対応関係にあるので、両者の一貫性、整合性に気をつけて書く必要がある。

# UMLを学ぶETロボコンメンバーに送るUML講座を終える前に
5回にわたってUMLについて自分の解釈を述べてきましたが、これは二年程度（より厳密にいうなら一年程度）UMLを勉強して、ETロボコンに使った人の知識にすぎません。

間違いなどもあると思いますので、やっぱり参考書を買って勉強することを一つお勧めします。

ですが、自分の経験からくる解釈が理解の助けになるとは思っています。
なってるといいな。

またわからないことがあったらサポートしますので聞いてください。