システム設計でよく使われるシーケンス図。先輩に書けと言われたけど、「そもそもシーケンス図って何?」、「必要性は?」、「どう書けば良いの?」という方も多いのではないでしょうか。
シーケンス図は、オブジェクト指向のソフトウェア設計では必須と言える重要なものです。難しいイメージを持っている方も多いですが、ポイントさえ抑えればけして難しいものではありません。若手エンジニアでも十分書くことができます。
この記事では、シーケンス図の基礎知識から書き方までどの記事よりも詳しく解説します。この記事を読み終えたとき、若手エンジニアもシーケンス図を書けるようになっているでしょう。この記事を参考に、シーケンス図を書いてみましょう。
1.シーケンス図とは
シーケンス図とは、オブジェクト指向のソフトウェア標準設計手法群である「UML(統一モデリング言語)」の1つで、プログラムの処理の概要や流れを設計する際に使われる手法です。仕様書がない既存システムの分析に使われることもあります。UMLの中では「相互作用図」の1つに位置づけられています。
オブジェクト指向のソフトウェア設計において、シーケンス図を作成することはグローバルスタンダードと言っても過言ではないほど重要なものです。しっかりシーケンス図の基本を抑えておきましょう。
2.シーケンス図の3つのメリット
ここではシーケンス図がなぜ必要なのかそのメリットについて解説します。
2.1.プログラムの処理概要を整理できる
プログラムコードはあっという間に数千、数万行を超えます。設計なしに行き当たりばったりでコーディングすることは、「品質の悪いシステム」を作ることに他なりません。コーディングに掛かる工数や仕様変更時の改修工数も増えるでしょう。シーケンス図を使ってプログラムの処理概要(ロジック)を整理することは、最適なシステムを作成する第一歩です。
2.2.仕様レビュー・顧客へのエビデンス
コーディング前に仕様をレビューすることは当たり前ですが、何を使ってレビューするかがとても重要です。シーケンス図は、視覚的に優れた図であり、開発チームでの仕様レビューにも適しています。シーケンス図を作成することで、開発メンバーやレビュアーに仕様を的確に伝えることができるでしょう。
また、一般的に顧客(ユーザー)はシステムの内部構造への興味が低いですが、後工程でのトラブルを回避するために顧客との仕様合意に用いても良いでしょう。提出しておくだけでもメリットがあります。
2.3.保守フェーズや追加開発時に仕様を確認することができる
シーケンス図は、保守フェーズや追加開発時の「既存仕様」の把握に非常に役立ちます。プログラムコードは数万数十万行以上になることも稀ではありません。プログラムコードから仕様を紐解くにはとても時間が掛かります。シーケンス図があることで、コーディングした人以外が簡単に仕様を把握することができるようになります。
3.シーケンス図のデメリット
シーケンス図を作成するデメリットは特にありません。仕様が変わった時にドキュメントを更新する手間が増えますが必要な作業です。仕様変更時はリバースエンジニアリングツールでシーケンス図を自動作成することにより、更新工数を減らすという方法もあります。
4.シーケンス図の基本ルール
シーケンス図は、ライフラインやメッセージという「構成要素」と、オブジェクトのつながりや処理内容を表現する「複合フラグメント」を組合せて書きます。
この章では、「構成要素」と「複合フラグメント」のルール(種類)について解説します。シーケンス図の基本ルールは世界共通ですのでしっかり覚えておきましょう。
下図は、店員が商品を検索し商品詳細を参照するというシーケンス図の例です。
4.1.構成要素
構成要素は、ライフライン、実行仕様、停止、メッセージという大きく4種類あります。それぞれの要素の意味は下記のとおりです。
ライフライン
オブジェクトやクラスを表現する時に使用します。 箱の中は、「オブジェクト名:クラス名」という書き方をします。 オブジェクト名かクラス名どちらか一方のみの場合は省略できます。 |
実行仕様
ライフラインで処理が実行されていることを意味します。 実行仕様は別名「制御フォーカス」とも呼ばれます。 ライフライン上に配置します。 |
停止
ライフラインの消滅を意味します。 処理が終わりライフラインを破棄する際などに使います。 |
同期メッセージ
オブジェクトに対する処理命令(メソッドの起動命令)を意味します。 「同期メッセージ」は、このメッセージの処理が終了するまで 次のメッセージを起動させない仕様の時に使います。 実行元のライフラインはこのメッセージが終了するまで待機します。 メッセージ名の後ろに括弧をつけて引数を記載します。 |
非同期メッセージ
オブジェクトに対する処理命令(メソッドの起動命令)を意味します。 |
応答メッセージ
実行した処理の戻り値を意味します。 |
4.2.複合フラグメント
複合フラグメントとは、オブジェクトの処理内容を表現するためのものです。プログラムコード内で書かれる条件分岐や並行処理、ループ処理などを視覚化するために使います。
シーケンス図上で表現する際は、記号(略名)を用いて記載します。記号は大文字で使うことも小文字で使うこともあります。大文字小文字に意味の違いはありません。会社ごとのドキュメント規約に従って記載して下さい。
名称 |
記号 |
処理内容 |
Alternatives |
alt |
条件による分岐処理(if else) |
Assertion |
assert |
絶対処理(定義されたロジックが必ず成り立たつ処理) |
Parallel |
par |
並行処理 |
Consider |
consider |
コアとなる重要な処理 |
Option |
opt |
条件が満たされた時のみ実行される処理(if) |
Reference |
ref |
別のシーケンス図を参照 |
Loop |
loop |
ループ処理 |
Break |
break |
条件が満たされた時点で中断される処理 |
Negative |
neg |
否定処理(通常発生しない処理) |
Critical Region |
critical |
割り込みや中断を許さない排他処理 |
Ignore |
ignore |
実行時に無視する処理。 |
この章では、「構成要素」と「複合フラグメント」という、シーケンス図を書く際の基本ルールについて解説しました。シーケンス図は、「構成要素」と「複合フラグメント」を組合せて書きます。次の章では、ケース別のシーケンス図を詳しく解説していきます。
5.シーケンス図の書き方
この章では、シーケンス図の書き方を理解できるようケース別の例を使って解説します。
5.1.条件分岐(Alternative)
条件分岐を表現する際は、「alt」複合フラグメントを使って表現します。
分岐の条件は[](ガードという括弧)内に記載し、各処理を点線で区切って記載します。
下図は、小売店舗におけるクーポン利用時の販売金額の計算処理を表した例です。
クーポンを読み込んだ際に有効期限をチェックし、期限内か期限外かで処理を分岐します。
5.2.アサーション(Assertion)
アサーションを表現する際は、「assert」複合フラグメントを使って表現します。アサーション内容(成立しなければならない結果)は{}内に記載します。
下図は小売店における在庫の更新処理を表した例です。販売確定時に、販売した数量が必ず在庫から引落とされなければなりません。つまり、「在庫数 = 在庫数 – 販売数」を成立させる必要があります。
5.3.並列処理(Parallel)
並行処理は、「par」複合フラグメントを使って表現します。並列で実行される処理は点線で区切ります。
下図は小売店における店舗在庫の更新処理を表した例です。販売確定時に受払いトランと在庫マスタを同時に更新します。
5.4.重要処理(Consider)
重要処理は「Consider」複合フラグメントを使って表現します。「有効処理」と表現されることもあります。Consider{メッセージ名1,メッセージ名2…}と記載します。
下図は小売店における店舗在庫の更新処理を表した例です。販売確定時に受払いトランと在庫テーブルを必ず更新しなければなりません。
5.5.条件指定(Option)
条件が満たされた時のみ実行される処理は、「opt」複合フラグメントを使って表現します。
実行条件は[ ](ガードという括弧)内に記述します。
下図は免税店における免税対応を表した例です。購入者が外国人だった場合に、店員はPOSレジ上で免税ボタンを押し免税システムと連携させます。POSレジと免税システムの連動は、POSレジで免税ボタンが押された場合のみ行われます。
5.6.外部参照(Reference)
外部参照は、「ref」複合フラグメントを使って表現します。refで囲まれている部分の処理は、別のシーケンス図を参照して下さいという意味になります。
下図は免税店における免税対応を表した例です。POSレジと免税システムの連携処理は複雑なため、個別のシーケンス図で詳細を表現しています。
5.7.ループ処理(Loop)
ループ処理(繰り返し処理)は、「loop」複合フラグメントで表現します。ループの回数は、[開始条件,終了条件]という形で記述します。
下図は小売店におけるレジ処理を表した例です。商品数が1点以上あった場合、商品数だけ処理を繰り返します。
5.8.中断処理(break)
中断処理は、「break」複合フラグメントで表現します。中断条件は、ガードという[]の中に記述します。
下図は出荷処理を表した例です。出荷しようとした商品の在庫がなかった場合に処理を中断しメッセージを表示します。
5.9.否定処理(negative)
否定処理は、「neg」複合フラグメントで表現します。否定処理(negative)は、通常発生しない処理(本来実行されない処理)を意味します。
下図は販売確定時の受払いトランと在庫マスタの更新処理を表した例です。在庫マスタは「在庫数 = 在庫数 – 販売数」というロジックで更新されますが、何らかの問題で整合性が取れない更新が行われた際に整合性エラー処理を行います。
5.10排他処理(critical)
排他処理は「critical」複合フラグメントを使って表現します。
下図は、出荷指示登録時の在庫マスタと出荷指示テーブルの更新処理です。データの整合性を担保するために、在庫マスタと出荷指示テーブルの更新対象レコードに排他処理を行います。
この章では、ケース別にシーケンス図の書き方について解説してきました。分かりやすいよう簡略化した図で解説していますが、実際の設計時は、これらを組合せてシーケンス図を書いていきます。システムによってはシーケンス図が複雑化することも珍しくありません。
次の章では、シーケンス図を書く際の注意点について解説します。次の章を読んで最適なシーケンス図を書けるようになりましょう。
6.シーケンス図を書く際の5つの注意点
前章までシーケンス図の基本的な書き方について解説してきました。
この章では、シーケンス図を書く際の注意点について詳しく解説します。
6.1.必ずシナリオを明確にしてから作成する
シーケンス図を作成する前に、ユースケース図や業務フローなどを作りユーザーがどのようなシナリオでシステムを使うのか整理しましょう。シナリオが明確でない状態でシーケンス図を作成すると、精度の低いシーケンス図になってしまいます。後々シナリオに合わない仕様になってしまったという事にもなりかねません。
6.2.シーケンス図1つにつき1シナリオが基本
1つのシーケンス図につき1つのシナリオを表現するのが基本です。シーケンス図に分岐などを入れる事によって、1つのシーケンス図で複数のシナリオを表現することができますが、見易さ・可読性の観点から1シーケンス図につき1シナリオにするのが一般的です。
シナリオの数だけシーケンス図を作成することは大きな労力になりますが、「仕様を明確化する」「仕様バグを減らす」「仕様誤読をなくす」という大きなメリットがあります。つまり、コーディング後の手戻りが減ります。
6.3.長くなるシーケンス図は分解する
シナリオによっては、シーケンス図が横にも縦にも長くなってしまう事があります。1シーケンス図1シナリオを守っていても発生することがあります。そのような時は、「ref」などを使いシーケンス図を分解しましょう
A3用紙に収まらない長さになった時に分解を検討すると良いでしょう。
6.4.メッセージの書き方を定義しておく
メッセージを受取り側視点で書くのか、送信側視点で書くのかあらかじめ定義しておきましょう。メッセージの書き方を明確に決めておかないと、シーケンス図によって受取り側視点と送信側視点が混ざってしまい、開発者(コーディング担当)が混乱します。一般的には受取り側視点で書くことが多いです。
6.5.どこまで詳細に書くかあらかじめ定義しておく
シーケンス図は、詳細に書こうと思えば、変数への代入やメソッドに渡す具体的な引数など、どこまでも詳細に書くことができます。設計者と開発者(コーディング担当)が同じであれば良いですが、大きなプロジェクトではそうはいきません。
設計工数や後工程の品質にも関わってきますので、あらかじめ作成するシーケンス図の品質を責任者と定義しておきましょう。
7.まとめ
この記事では、シーケンス図の基礎知識から書き方までどの記事よりも詳しく解説してきました。始めてシーケンス図を書く方も、シーケンス図の書き方について理解が進んだのではないでしょうか。品質の高いシーケンス図を書くには、ポイントを抑えた上で数をこなす他ありません。次は、この記事を参考に、シーケンス図を書いてみましょう。