【コードで分かるUMLシリーズ】シーケンス図の書きかた（loopの正しい書きかた＆コード実装例＆EA,astahでのアドバイス）

#はじめに
シーケンス図って、Webで画像検索すると様々な書きかたがされていて、何が正しいのだか分からなくなってしまいます。
そこで、今回は、UML仕様書に書いてあるLoopの書きかたを見てみます。

#UML仕様書の記述
シーケンス図のループは、UML仕様書では「複合フラグメント」の項目に書かれています。
UML2.0仕様書2.1対応 オーム社より

##セマンティクス
>interactionOperatorのloopは、CombinedFragmentがループを表すことを意味する。loopオペランドは、何度か繰り返される。ガードは、論理式と同様に、最小と最大のループの反復の数を持つことができる。セマンティクスとしては、ループは（ガードのイテレーション式にある）最低「minint」の回数だけ反復した後、論理式がfalse(偽)であればループは終了する。

##記法
>`'loop['('<minint>[','<maxint>]')']`
 `<minint>`    ::=負でない整数
 `<maxint>`    ::=負でない整数(`<minint>以上 | '*'`
 `'*'`は無限の意
`<minint>`だけがある場合、`<minint> = <maxint> = <integer>`であることを意味する。
loopだけの場合、最大値は無限で最小値は0であることを意味する。

また、セマンティクスに出てきた「ガード」の記法については、UML仕様書では**相互作用オペランド**の項に「図を参照」と書かれています。その図を見ると、ガード条件はオペランド内に`[  ]`で書くことが分かります。

>InteractionOperandの例は、図14.11を参照すること
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/e4e9ad46-9050-b793-7e7d-fc8e048b9479.png)

#これらを分かりやすく直すと
つまり書きかたに、いくつかのパターンがあって、それぞれ以下のような意味になる、ということです。
実用的なイメージが湧くように、コード例も付けました。

##loop ( min , max )
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/18d66ff7-6b70-aa1c-33f9-dc5cfedf7ea1.png)
loopに入ったら最低でも3回は処理を繰り返し、その後[ x == true ]が偽になったらループから抜ける。
ループは最大の5回繰り返したら終了する。


```csharp:loop1.cs
for( int i = 0 ; i < 5 ; i ++ ){
    if( ( i >= 3 ) && (!(x == true)) ){
        break;
    }
    // 処理
}
```
無理やり1行にすると、こんな感じ。

```csharp:loop1.cs
for( int i = 0 ; (!( ( i >= 3 && i < 5 ) && (!(x == true)) )) || (i < 5) ; i ++ ){
    // 処理
}
```

ごく一般的にプログラミングされるループは、次のような感じかと思うのですが、

```csharp:loop_normal.cs
for( int i = 0 ; i < 5 ; i ++ ){
    if( x == false ){
        break;
    }
    // 処理
}
```
UMLで正しく描くと
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/691547d4-b1b8-222b-a8cf-dff94641c04d.png)
となり、minに 0を書かなくてはなりません。
※ `0 , `を書かないと下の loop ( min )の意味になってしまいますので注意してください。

##loop ( min , * )
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/d7b1e33f-9e2d-66b8-9b37-7414456e3fb2.png)
loopに入ったら最低でも3回は処理を繰り返し、その後[ x == true ]が偽になったらループから抜ける。

```csharp:loop2.cs
for( int i = 0 ;  ; i ++ ){
    if( ( i >= 3 ) && (!(x == true)) ){
        break;
    }
    // 処理
}
```
または、

```csharp:loop2.cs
for( int i = 0 ; !( i >= 3 && ( !(x == true) ) ) ; i ++ ){
    // 処理
}
```

##loop ( min )
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/1af9c882-69d8-e719-9dc0-a16a170d683c.png)
loopに入ったら3回処理を繰り返す。
※UML仕様書に特段の記載を見つけられなかったが、この場合はガード条件[ x == true ]を入れても意味をなさないと考えられる。

```csharp:loop3.cs
for( int i = 0 ; i < 3 ; i ++ ){
    // 処理
}
```
##loop
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/5175c8a6-1717-274d-3d19-a8fd6e17a728.png)
loopに入ったあと処理を繰り返し、[ x == true ]が偽になったらループから抜ける。

```csharp:loop4.cs
while( x == true ){
    // 処理
}
```

#おわりに
UMLのループって、意外と奥深いですね。
プログラミング言語のループ文でも、minをサポートしてくれればいいのに、と思いました。
ハードウェア周りの制御では、
「最低何回は処理を回して、そのあとは条件で抜けるのが基本だけれど、タイムアウト処理として最大回数回ったら抜ける」
とか、あったら便利そう。

#現場からのつぶやき(2020/4/9 追記)
いやはや、現場では、モデリングツールは通常 EA(Enterprise Artchtect)か、astahが使われています。
しかし、どちらのツールも、UML仕様に完全準拠していないんですよね...( T T ) 。
なので、現場は、混乱しやすいのだと思います。
ですので、こんな風にすれば？　と現場に伝えている内容を、以下に記します。

##astahの現状
astahでそのままloopを描くと、こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/3f6fe019-7020-7708-ebc6-495e389c6608.png)
loopの右にガード条件が表示されます。
これは、UML仕様と合っていませんね。

##EAの現状
EAでそのままloopを描くと、こんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/6ada167e-359b-1901-c8d5-9763ee624ff6.png)
複合フラグメントの名前の欄に入力した文字が、loopの回数のエリアに表示されて、
ガード条件は、きちんと表示されていますね。

##提案
よくありがちなのが、
astahならば、
loopの右側に、[〇〇の間]とか書いていたり、
EAならば、
名前のところに「〇〇の間」とか日本語で書いていて、
ガード条件には、ほぼ同じことを、式で書いていたり、抜ける条件を書いている人もいます。

ツールを使って開発しているチーム内で、
UML仕様の表記を共通理解して、ツールに合わせた使いかたをするローカルルールにするのが、ベターかと思います。
それを、以下に記します。

##astahでの書きかたローカルルール

astahならば、ガード条件の中に、**loop [ (1,2) [xxx == true] ]**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/b77b1c39-cf18-66ad-90b0-57e653b8656a.png)

##EAでの書きかたローカルルール

EAならば、名前の欄に**「(1,2)」**、ガードの欄に **[xxx == true]**と書く、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/1f9f9b9f-81d4-5693-84ed-42594ee74537.png)　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197297/e847125c-90b1-9a81-1640-f86dd2d8b4fa.png)


のように、
ルール付けしてはどうでしょうか。