Atom と PlantUML で快適シーケンス図駆動開発ライフ
サーバーサイド開発担当のエンジニアが「設計と実装を進めようとしている」という背景で話を進めます。
PlantUMLは強い
「認識合わせ」という名目でホワイトボードに図を書いて会話することがよくあります。共通言語で会話してあいまいなところを少なくしたら、マネージャーも安心感がありますし、プログラマも自分がやるべきことに集中できますね。
…3日経ちました。あのとき描かれていたホワイトボードの図のとおりに、実装することになりました。認識の齟齬をなくしてくれた貴重な図です。写真に撮りました。どこに保存してたっけ。やっぱり変更したくなったらどうしましょう。またホワイトボードに書き起こす?私はやりたくありません。
そこで、UML図 が登場します。
私はもともと、UML図作成に積極的ではありませんでした、というのも、
- 描画ツールを使いたくない
- 差分管理ができないのが辛い
- メンテするのがいやだ
という考えがあったからです。
UML図は、ツールやサービスで描画がサポートされているものも数多くあるのですが、矢印の太さや、長さ、コンポーネントの配置はできればおまかせしたいところです。そこで今回はPlantUMLが定める記法でUMLのテキストを書いて、それを図に変換します。また、plantuml-viewerを使ってリアルタイムプレビューできるようにします。
テキストで書けると差分管理できるようになる点が良いです。履歴が残るのはありがたいです。また、差分管理ができるということは、GitHubの機能を使えるということです。すなわち、変更に対して レビューをしてもらえ、コメントをもらえます。 描画ツールでやろうとするとレビュー方法に工夫が必要ですし、もらったコメントの管理が大変です。GitHubの仕組みに乗せてしまうことでそのあたりの課題が一気に解決できます。
シーケンス図は強い
UMLには種々の図がありますが、こと設計〜開発段階においては シーケンス図 が強力です。どのようなコンポーネントがあって、それらがどうやりとりするかを視覚的に捉えることができるためです。
シーケンス図というとオブジェクトがあって、そのオブジェクトのメソッドを実行すると他のオブジェクトが生成される…といったような図をイメージするかもしれませんが、ここではもっと大きな粒度、データベースや、外部APIといったサイズをオブジェクトにします。クラスやメソッドレベルのやりとりはコードで十分表現可能 である一方、コンポーネント間のやりとりは外部仕様として日本語ベースになっている ことが多く、たとえ厳密だとしても可読性が低いです。シーケンス図はそれを補完するのに役立ちます。
みてわかるように、それほど正確に書き込みをしているわけではありません。各コンポーネントがどういうやりとりをしていて、そのときどんな情報を受け渡しているか、という程度です。これで十分です。 設計書はこのシーケンス図に加えてコンポーネントの境界についてインターフェースを明記すると良いでしょう。
やること
せっかくなので、この記事ではPlantUMLを使い始めてからシーケンス図を作って、レビューをもらい開発を開始するまでの流れを例として示そううと思います。以下の順で話を進めます。
- PlantUMLを導入する
- Atomプラグイン plantuml-viewer を使いながら編集する
- シーケンス図を生成する
- GitHubでレビューしてもらう
1. PlantUMLを導入する
JARで提供されています。ダウンロードページから落としてください。このJARはテキストに記載したUMLのDSLを画像へ変換する際に使います。
2. Atomプラグイン plantuml-viewer を使いながら編集する
まずパッケージをインストールします。
デフォルトでは Option + Control + p
でプレビューウィンドウが立ち上がります。.pu
などのPlantUMLに由来する拡張子に反応してくれるようです。あとは、編集ウィンドウで作業するとすぐにプレビューへ反映されます。
3. シーケンス図を生成する
編集しおわったら、画像ファイルを作成します。生成した画像ファイルを、Markdownの仕様書に埋め込むように使います。
$ cd /path/to/plantUML/file $ java -Dfile.encoding=UTF-8 -jar ~/installed/plantuml/path/plantuml.jar ./*pu -o out
*
これで、out
ディレクトリに画像ファイルが生成されます。
GitHubでレビューしてもらう
ドキュメントのリポジトリをでシーケンス図をレビューしてもらいます。リポジトリがなければ作りましょう。生成した画像ファイルを使って、簡単な設計書をつくりました。
ソースコードと同じようにドキュメントのプルリクを出します。プルリクにコメントが付きます。
効果を発揮するのはここです。画像だけみてもどこが修正されたからわかりづらいですが、もとはテキストで記載されているので、どこが修正されたか一目瞭然です。これは非常に強力な特長だと感じました。
無事に指摘対応がおわり、マージされました。マージされたシーケンス図をベースに、開発を進めます。快適!
おまけ
UML図は、こんなシーンでも役に立ちます。
マネージャー:「ごめん、外部システムからとってきたデータってキャッシュするんだっけ?」
しますよ。シーケンス図に書いてました。TTLは1分に設定してます、というように、プログラミング時に役立つだけでなく、仕様の再確認をする際の証憑にもなります。
開発者:「ずいぶんと複雑なクラス関係になってしまった。プルリク送るときに説明したほうがいいかな」
簡単なクラス図をプルリクエストにそえることで、クラス関係の見通しがよくなります。
この記事で使ったPlantUML
@startuml{news-after-login.png} '画像変換するときにここで指定したファイル名になる。 title ニュース一覧取得API(ログイン後) hide footbox 'シーケンスの縦線の下部にシーケンスボックスを出すかどうか指定する。よほど長いものでない限りいらないだろう actor Webアプリ as user 'actorにすると人っぽい見かけになる participant API as api 'participantにすると四角になる database Redis as redis 'databaseにするとストレージっぽい見かけになる database DynamoDB as dynamo 'as の左部が表示名、右部が変数名 participant NewsAPI as news user -> api : ニュース一覧取得リクエスト ' -> 同期メッセージという意味になる。 activate api ' オブジェクト生成的な意味合いになる。 api -> redis : AccessToken note right : db:9, ttl:60s redis --> api : userId api -> dynamo : userId note right : table:metadata '矢印の右側にコメントボックスを表示してそこにコメントを表示する、という意味 dynamo --> api : ユーザープロフィール group 公開ニュースの取得 '区切りがわかりにくくなってしまう場合はgroup - endで囲うとよい api -> redis : 公開ニュース取得 note right : db:11,ttl:60s redis --> api : 公開ニュースのJSON alt キャッシュなし '分岐を表現したいときは分岐ケースをalt - endで囲う api -> news : 公開ニュース取得 news --> api : 公開ニュース api -> redis : 公開ニュースキャッシュ end end group ユーザニュースの取得 api -> redis : ユーザニュース取得 note right : db:11,ttl:60s redis --> api : ユーザニュースのJSON alt キャッシュなし api -> news : ユーザニュース取得 news --> api : ユーザニュース api -> redis : ユーザニュースキャッシュ end end api -> api : プロフィールから配信ニュース抽出、\n公開開始日時でソート api --> user : ニュース一覧 @enduml
他の記法やシーケンス図以外のUML図についてはこちらのサイトを参考にしてください。