2021-12-08に更新

実践UML記述法:シーケンス図で継承元(親クラス)のメッセージ(メソッド)を利用する際の書き方について

TL; DR

クラス名::メソッド名 なんてどうでしょう?

本題:シーケンス図で継承元(親クラス)のメッセージを利用する

シーケンス図のメッセージは、ライフラインがクラス図のクラスと紐付いている場合、クラスの操作を使うことが一般的かと思います。

クラス図の例 シーケンス図の例

2つだけのクラスを持つクラス図とシーケンス図

@startuml
title クラス図の例

skinparam classAttributeIconSize 0

class 利用者 {
}

class クラス {
  + 操作()
}

クラス "1 - used" <-- "1" 利用者
@enduml
@startuml
title シーケンス図の例

participant ": 利用者" as 利用者
participant "used : クラス" as クラス

利用者 -> クラス: 操作()
@enduml

しかし、継承元クラス(親クラス)のメッセージを利用する際、クラスとしては持っていない(かのように見える)メソッドを呼出すように書く必要があります。

継承が1つ存在するクラス図の例 継承が1つ存在するシーケンス図の例

継承が1つ存在するクラス図とシーケンス図

@startuml
title 継承が1つ存在するクラス図の例

skinparam classAttributeIconSize 0

class 利用者 {
}

class 親クラス {
  + 操作()
}

class クラス {
}

親クラス <|-- クラス
クラス "1 - used" <-- "1" 利用者
@enduml
@startuml
title 継承が1つ存在するシーケンス図の例

participant ": 利用者" as 利用者
participant "used : クラス" as クラス

利用者 -> クラス: 操作()
note right: 表記上の違いが無い
@enduml

上記はわかりやすい例ですが、下記のように継承とメッセージが複数存在すると、どのクラスのどのメソッドが使われているのか把握しづらくなります。
特に、子クラスのメソッドで親クラスのメソッドを呼出すような形は、どれがどのクラスで実装されているのか把握しづらいです。

継承が複数存在して視認性が悪いクラス図の例 継承が複数存在して視認性が悪いシーケンス図の例

継承が複数存在して視認性が悪いクラス図とシーケンス図

@startuml
title 継承が複数存在して視認性が悪いクラス図の例

skinparam classAttributeIconSize 0

class 利用者 {
}

class 高祖父母クラス {
  + create()
}

class 曽祖父母クラス {
  + read()
}

class 祖父母クラス {
  + update()
}

class 親クラス {
  + delete()
}

class クラス {
  + 操作()
}

高祖父母クラス <|-- 曽祖父母クラス
曽祖父母クラス <|-- 祖父母クラス
祖父母クラス <|-- 親クラス
親クラス <|-- クラス
クラス "1 - used" <-- "1" 利用者
@enduml
@startuml
title 継承が複数存在して視認性が悪いシーケンス図の例

participant ": 利用者" as 利用者
participant "used : クラス" as クラス

利用者 -> クラス: 操作()
note right: それぞれのメッセージが\nどのクラスのものか\n把握が難しい
クラス -> クラス: read()
クラス -> クラス: delete()
クラス -> クラス: create()
クラス -> クラス: update()
@enduml

また、上記のような状態において、UML2系で記法の定義はされていません。

現状で最新のUML2.5.1では、メッセージの記法は以下のように定義されています。
request-message-label という部分が今回のターゲットとなるメッセージラベルです。
中身を確認すると、メソッド名に該当する message-name、引数に該当する input-argument-list の2つしか存在しません。
クラス図の属性や操作には prop-modifier という名で詳細を記述できるため以下様にもできるのですが、シーケンス図のメッセージには上記の様な補足も書けないことになっています。

<message-label> ::= <request-message-label> | <reply-message-label> | ‘*’

<request-message-label> ::= <message-name> [‘(‘[<input-argument-list>] ’)’]
<input-argument-list> ::= <input-argument> [‘,’<input-argument>*]
<input-argument> ::= [<in-parameter-name> ‘=’] <value-specification> | ‘-’

; <reply-message-label> の定義は省略する

About the Unified Modeling Language Specification Version 2.5.1

解決策

ここで、 message-name の定義を考えてみます。
定義は以下の通りです。

The message-name appearing in a request-message-label is the name property of the Message.
If the Message has a signature, this will be the name of the Operation or Signal referenced by the signature.
Otherwise the name is unconstrained.

request-message-labelに表示されるmessage-nameは、そのMessageのnameプロパティです。
Messageにシグネチャがある場合は、そのシグネチャで参照されるOperationやSignalの名前になります。
それ以外の場合、名前は制約を受けません。

ここでいう「シグネチャで参照されるOperationやSignal」は、多くはライフラインに紐付くクラスの操作(つまりメソッド)です。

操作を記述する際、クラス名の記載の有無についてまで明記はありません。
しかし、UMLの仕様書にも多く書かれている記述として クラス名::操作名 という書き方が使える様です。
であれば、メッセージ名としても同様の記述を使えば良いのではないでしょうか?

継承が複数存在するが視認性をある程度補えるシーケンス図の例

継承が複数存在するが視認性をある程度補えるシーケンス図

@startuml
title 継承が複数存在するが視認性をある程度補えるシーケンス図の例

participant ": 利用者" as 利用者
participant "used : クラス" as クラス

利用者 -> クラス: 操作()
クラス -> クラス: 曽祖父母クラス::read()
クラス -> クラス: 親クラス::delete()
クラス -> クラス: 高祖父母クラス::create()
クラス -> クラス: 祖父母クラス::update()
@enduml

結論

クラス図におけるクラスの属性や操作の補足的記法をベースに考えることが多いため、シーケンス図でも同様の書き方ができないかを調べた挙句、シンプルな記法を思いつきました。
遠回りした気もしますが、お蔭でさまざまな定義などの再学習もできたため、結果的には良かったと思います。
仕様書、万歳!

ツイッターでシェア
みんなに共有、忘れないようにメモ

view_list 実践UML記述法
第1回 実践UML記述法:UMLのクラス図における関係の考察
第2回 実践UML記述法:スクリプト言語(Python, Perl, PHPなどなど)における可視性をUMLで記述する1考察
第3回 実践UML記述法:ユースケース図におけるユースケース間の関係の書き方を疑似コードから逆変換して考える
第4回 実践UML記述法:シーケンス図で継承元(親クラス)のメッセージ(メソッド)を利用する際の書き方について

Morichan

Qrunch 移転組です。

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント