tag:crieit.net,2005:https://crieit.net/tags/%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E5%9B%B3/feed 「シーケンス図」の記事 - Crieit Crieitでタグ「シーケンス図」に投稿された最近の記事 2021-12-08T10:31:53+09:00 https://crieit.net/tags/%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E5%9B%B3/feed tag:crieit.net,2005:PublicArticle/17788 2021-11-26T19:37:42+09:00 2021-12-08T10:31:53+09:00 https://crieit.net/posts/UML-61a0b8f65e9fb 実践UML記述法:シーケンス図で継承元(親クラス)のメッセージ(メソッド)を利用する際の書き方について <h1 id="TL; DR"><a href="#TL%3B+DR">TL; DR</a></h1> <p><code>クラス名::メソッド名</code> なんてどうでしょう?</p> <h1 id="本題:シーケンス図で継承元(親クラス)のメッセージを利用する"><a href="#%E6%9C%AC%E9%A1%8C%EF%BC%9A%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E5%9B%B3%E3%81%A7%E7%B6%99%E6%89%BF%E5%85%83%EF%BC%88%E8%A6%AA%E3%82%AF%E3%83%A9%E3%82%B9%EF%BC%89%E3%81%AE%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B">本題:シーケンス図で継承元(親クラス)のメッセージを利用する</a></h1> <p>シーケンス図のメッセージは、ライフラインがクラス図のクラスと紐付いている場合、クラスの操作を使うことが一般的かと思います。</p> <p><img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNZSjFvnyyh7JJkVpjxyk77TattTN5p5sPbv1Ob5YRaAoJc9nSME9IL5cKcb9QcUoVbvmPbLgGe6N5nW6OMd7IkVJrdneg5LePgh5Yg8C18egA2WhV1iSk-JlNCqD44g479AXWgw2gN5gIbA2ZQwka2k4i8qBeVKl1IW6m40" alt="クラス図の例" /> <img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNZSjFrnyvx7JHiVDsz-tBJpwUpDZnlNFTdNpSLL05INcPnPa9XNeg1afV2qO-NpAIjUDBGgAIGM8tYeoagBKrCKh826hd_Sl19e74WjWiV51TUce6k74BTIU3QvzydUEHgQN0wfUIb0nm40" alt="シーケンス図の例" /></p> <p>2つだけのクラスを持つクラス図とシーケンス図</p> <pre><code class="puml">@startuml title クラス図の例 skinparam classAttributeIconSize 0 class 利用者 { } class クラス { + 操作() } クラス "1 - used" <-- "1" 利用者 @enduml </code></pre> <pre><code class="puml">@startuml title シーケンス図の例 participant ": 利用者" as 利用者 participant "used : クラス" as クラス 利用者 -> クラス: 操作() @enduml </code></pre> <p>しかし、継承元クラス(親クラス)のメッセージを利用する際、クラスとしては持っていない(かのように見える)メソッドを呼出すように書く必要があります。</p> <p><img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNY-RUQpplsF6tiC7pSkURfsnjCvAnutpdpSrFsuQVtZvfMFctO-dRtvSUEw9_kwkRYAipFp2XAB4dCLadCIYuiTIqgACfDAIr8za_FpWZEhKXKCkBZ0CWfFErO-dxBYHKEhGZLNBKpmnR9LS5E1uWeAsWhF9lS-sJj7GnEX2Au2eXD5ZqsDhYv20HT2GibGGLUXj3WrHKd1HbSNo5L2k83B8JKl1UXX0000" alt="継承が1つ存在するクラス図の例" /> <img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNY-RUQpplsF6tiC7pSkURfsnjCvAnutpdpSrFsuQVlZvZsFcpO-Rjxyk6ddqzcR7pUkUxAlcukh06X0Pd9cGM9UYOAIbSBJZfNFfwnuqT2gf91OZE2XAYijJarHi59utBJ-SVDAe74WjGWU5nTScuAk7KBSIk7PvDudU-TeQ7BbvPUaAXHbfcUKM2cyMBZYnOePJtPq0Ltqid7guyOMeFkVjom4ChWSKlDIWBu30000" alt="継承が1つ存在するシーケンス図の例" /></p> <p>継承が1つ存在するクラス図とシーケンス図</p> <pre><code class="puml">@startuml title 継承が1つ存在するクラス図の例 skinparam classAttributeIconSize 0 class 利用者 { } class 親クラス { + 操作() } class クラス { } 親クラス <|-- クラス クラス "1 - used" <-- "1" 利用者 @enduml </code></pre> <pre><code class="puml">@startuml title 継承が1つ存在するシーケンス図の例 participant ": 利用者" as 利用者 participant "used : クラス" as クラス 利用者 -> クラス: 操作() note right: 表記上の違いが無い @enduml </code></pre> <p>上記はわかりやすい例ですが、下記のように継承とメッセージが複数存在すると、どのクラスのどのメソッドが使われているのか把握しづらくなります。<br /> 特に、子クラスのメソッドで親クラスのメソッドを呼出すような形は、どれがどのクラスで実装されているのか把握しづらいです。</p> <p><img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuIh9BCb9LNY-RUQpplsF6tjUB6b_DdN3qxKpdivPyRXn-kF6PI-MJNknglTPmtAWxBEcLOyRMnuthN_SlF9nqywdipS_RbptP5yt5rTnTcPUGM9HOgv2SavYSR5ZIKbHPb9fIQfdSdvUS6PLge815nTOHk5fnyhdKrQyQ6XLgEQgXGc-N3tZ-T9fppksFLlV2pSUg411GLiXkIWriIHLGnEX-jdilJXL0nMd8Al5gR2q80NDs1VBLg4hIadDIKLLXAxYsUJU9tldG5HWzuLDZQukTYTpmKKnDM1HZKCfYhkvO1o4D48E8Q5agA2hK5gScgAaOAEh2-Gg8UA5oo4rBmMOD000" alt="継承が複数存在して視認性が悪いクラス図の例" /> <img src="http://www.plantuml.com/plantuml/png/VP7BIiD058RtynH3Lxhm1RAGFaWteJDe88uXcUmxCnMr5rnufrKeIcqALgNW1Iy-p6ccyIqyZP2WO3U7dFpVV6SEKusa6yfuooVIapwdyyTpk_y9gfDTxzhZ-_JsBEsFG9s26cR3aspSjOqRJAqUWsg2VWBp1le1p1JqIzgRWfhCFjg412ZrwbxW2aah3attaldHA6liLAWRbTrlB8uuemu5VGScGTs2BJj2YcDqRRtyxr1xs9szzrTMYTYMd8RUngP4Yxe0tG5rcTS9c04O0_erl-ypRb0Je19C2b7-hHTLjMl2jbhsO83SL-ygNxz92lBF_92x3AV_5pFkSycN07KKB0NYWFq0LIuOFjKt" alt="継承が複数存在して視認性が悪いシーケンス図の例" /></p> <p>継承が複数存在して視認性が悪いクラス図とシーケンス図</p> <pre><code class="puml">@startuml title 継承が複数存在して視認性が悪いクラス図の例 skinparam classAttributeIconSize 0 class 利用者 { } class 高祖父母クラス { + create() } class 曽祖父母クラス { + read() } class 祖父母クラス { + update() } class 親クラス { + delete() } class クラス { + 操作() } 高祖父母クラス <|-- 曽祖父母クラス 曽祖父母クラス <|-- 祖父母クラス 祖父母クラス <|-- 親クラス 親クラス <|-- クラス クラス "1 - used" <-- "1" 利用者 @enduml </code></pre> <pre><code class="puml">@startuml title 継承が複数存在して視認性が悪いシーケンス図の例 participant ": 利用者" as 利用者 participant "used : クラス" as クラス 利用者 -> クラス: 操作() note right: それぞれのメッセージが\nどのクラスのものか\n把握が難しい クラス -> クラス: read() クラス -> クラス: delete() クラス -> クラス: create() クラス -> クラス: update() @enduml </code></pre> <p>また、上記のような状態において、UML2系で記法の定義はされていません。</p> <p>現状で最新のUML2.5.1では、メッセージの記法は以下のように定義されています。<br /> <code>request-message-label</code> という部分が今回のターゲットとなるメッセージラベルです。<br /> 中身を確認すると、メソッド名に該当する <code>message-name</code>、引数に該当する <code>input-argument-list</code> の2つしか存在しません。<br /> クラス図の属性や操作には <code>prop-modifier</code> という名で詳細を記述できるため以下様にもできるのですが、シーケンス図のメッセージには上記の様な補足も書けないことになっています。</p> <pre><code class="bnf"><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> の定義は省略する </code></pre> <blockquote> <p><a target="_blank" rel="nofollow noopener" href="https://www.omg.org/spec/UML/2.5.1/About-UML/">About the Unified Modeling Language Specification Version 2.5.1</a></p> </blockquote> <h1 id="解決策"><a href="#%E8%A7%A3%E6%B1%BA%E7%AD%96">解決策</a></h1> <p>ここで、 <code>message-name</code> の定義を考えてみます。<br /> 定義は以下の通りです。</p> <blockquote> <p>The message-name appearing in a request-message-label is the name property of the Message.<br /> If the Message has a signature, this will be the name of the Operation or Signal referenced by the signature.<br /> Otherwise the name is unconstrained.</p> <p>request-message-labelに表示されるmessage-nameは、そのMessageのnameプロパティです。<br /> Messageにシグネチャがある場合は、そのシグネチャで参照されるOperationやSignalの名前になります。<br /> それ以外の場合、名前は制約を受けません。</p> </blockquote> <p>ここでいう「シグネチャで参照されるOperationやSignal」は、多くはライフラインに紐付くクラスの操作(つまりメソッド)です。</p> <p>操作を記述する際、クラス名の記載の有無についてまで明記はありません。<br /> しかし、UMLの仕様書にも多く書かれている記述として <code>クラス名::操作名</code> という書き方が使える様です。<br /> であれば、メッセージ名としても同様の記述を使えば良いのではないでしょうか?</p> <p><img src="http://www.plantuml.com/plantuml/png/VP5DIiD074VtSugXArruWIoaLmcTMGHY2SratvaWHc8sVfIMPgV6jA9L2XN5wc7-dGzluGIXerAo_3_UczzYkZ7p1omv2X4BM4YnNatKwIVmCtDpegwUvCDObZNm2OYyWTN8p0irl0Dn3bnOgEjSlbNckWIUDOvuWVGTn3EaIn2lShe4_hZvo16Ax4pG2oA_pt37mpARwSlQ38yxs8_TzLTBOagmXq4i89tPvnhNNGXjCtnmwBY7rKMnMPTx-sZB_WlJjRuTwMob5eN3te3wfAKorVoNJ6X86MtHl-x7kqPwTgMrsnKb4Vc9khHFx6zz0m00" alt="継承が複数存在するが視認性をある程度補えるシーケンス図の例" /></p> <p>継承が複数存在するが視認性をある程度補えるシーケンス図</p> <pre><code class="puml">@startuml title 継承が複数存在するが視認性をある程度補えるシーケンス図の例 participant ": 利用者" as 利用者 participant "used : クラス" as クラス 利用者 -> クラス: 操作() クラス -> クラス: 曽祖父母クラス::read() クラス -> クラス: 親クラス::delete() クラス -> クラス: 高祖父母クラス::create() クラス -> クラス: 祖父母クラス::update() @enduml </code></pre> <h1 id="結論"><a href="#%E7%B5%90%E8%AB%96">結論</a></h1> <p>クラス図におけるクラスの属性や操作の補足的記法をベースに考えることが多いため、シーケンス図でも同様の書き方ができないかを調べた挙句、シンプルな記法を思いつきました。<br /> 遠回りした気もしますが、お蔭でさまざまな定義などの再学習もできたため、結果的には良かったと思います。<br /> 仕様書、万歳!</p> Morichan