カテゴリー
その他

PlantUMLのアクティビティ図でrepeatのbackwardキーワードと動線が正常に出力されない話し

今やっている業務の作業フローがこんがらがってきたので、整理しようと思って図に書き出してみた。この際、きれいに出力しようと思った。

最初はInkSpaceで一から書いていこうとしたが、箱を3つ書いたみたところでめげた。次にやったのは、VS Codeの拡張機能で動くPlantUMLのアクティビティ図である。PlantUMLはInkSpaceやIllustrator、Visio、LibreOfficeのDrawのようなドローアプリケーションで図を描く必要もなく、テキストで描いていけば自動的にアクティビティ図(それ以外のUMLの図でも)を描いてくれる優れものである。

PlantUMLのアクティビティ図には動線の機能があるので、自分とお客さんの役割を分担した上での業務フロー図が描けそうなので早速描いてみた。動線とはこのような図である。PlantUMLのサイトからの抜粋である。

これをPlantUMLのアクティビティ図のコードではこんな感じである。

@startuml
|Swimlane1|
start
:foo1;
|#AntiqueWhite|Swimlane2|
:foo2;
:foo3;
|Swimlane1|
:foo4;
|Swimlane2|
:foo5;
stop
@enduml

これは簡単と、このまま進めていったら、問題が発生。フローを戻したりが自由にできないのでした。

PlantUMLではシーケンス(順序)、判断(IF)、前後判定の繰り返し(repeat)くらいの昔流行ったgoto文を廃止した構造化プログラミング(例外的にgoto文は残っているけど)のプログラム制御しか用意されていない。今回は、例えば、処理後に判定してNGだったら、何かしらの処理をしてから、また元の処理に戻すなんてことをやりたい。これを考えてみると、後判定の繰り返しで、判定でOKになるまで繰り返す。繰り返す前にNGのメール送信処理を実行したい。これは判定後の処理で書いてみるとこのような感じになる。

@startuml
start

repeat
  :何かの処理;
  backward:処理NGメール;
repeat while (処理判定?)
:処理OKメール;
stop;
@enduml

出力されたアクティビティ図はこのような図になる。

次に担当Aと担当Bに役割を振り分けるように動線で表現してみる。処理は担当Bが行って、その処理が正しく行われたかの判定とその結果のメール送信は担当Aとなる。担当BはNGメールが来たら再度何かの処理を行う。

@startuml
|A|
start
|B|
repeat
  :何かの処理;
  |A|
  backward:処理NGメール;
repeat while (処理判定?)
:処理OKメール;
stop;
@enduml

これを出力したアクティビティ図はぐちゃぐちゃになる。PlantUMLのサイトにあるライブプレビューでも同じ結果である。ライブラリは一緒なのかな?

まあ、このようはフローはアクティビティ図からいうと変則的な図だと思うからPlantUMLではサポート外である。何かいい書き方があるのかな?

仕方ないので、SVGファイルに一旦出力して、出力したSVGファイルをInkSpaceで開いて手で修正した。

でも、このような処理を通常のプログラミングでどうやっているか考えてみると、処理を無限ループで回して最後に判定し、OKならbreakで無限ループから抜け出している。PlantUMLではbreakが書けないしな。

そもそもPlantUMLのアクティビティ図の書き方は新しく変わったみたい。いまだベータ版となっている。昔と比べてだいぶメンテナンスしやすくなったみたい。ただし、いろいろと制約が増えてしまったようでもあるらしい。

追記

PlantUMLのフォーラムを覗いていたら、どうやらループでbreakができるらしい。ドキュメントに載っていない。こんなコードを書くと

@startuml
start

while()
  :何かの処理;
 
  if (処理OK?) then (yes)
    break
  else (no)
   :処理NGメール;
  endif

endwhile
:処理OKメール;

stop;
@enduml

こんなアクティビティ図が出力される。

これに動線をつけてみると、

@startuml
|a|
|b|

|a|
start

|b|
while()

  :何かの処理;
 
  |a|
  if (処理OK?) then (yes)
    break
  else (no)
    :処理NGメール;
  endif

endwhile

:処理OKメール;

stop;
@enduml

このような惜しい感じになる。もう一歩足りない。

やはり、動線はまだ上手く動いていないのか?