見出し画像

Now in REALITY Tech #16 REALITY iOSの設計レビューで活用しているPlantUML

中長期規模の機能開発で設計レビューが必要な際、設計イメージが図示されているとレビュワーとの認識齟齬が発生しづらいです。UML描画ツールであるPlantUMLの活用法についてREALITY iOSチームの事例をまとめていきます。

概要

ここ1ヶ月で3つほど記事を投稿しているかむいです。
今週の『Now in REALITY Tech』はiOSチームが担当します。

REALITY iOSチームの設計レビューでは説明を円滑に行うためにUML図を活用しているのですが、描画ツールとしてPlantUMLを使っています。
普段の設計レビューでの活用事例について書いていこうと思います。

PlantUML is 何

クラス図やシーケンス図などのUMLを素早く描画するためのDSLです。


使えるエディターは色々あるようですが、かむいはVS Codeを利用しています。Kibelaの様にWikiに直接PlantUMLを埋め込めるものもあるみたいです。

クラス図

・使用頻度: ★★☆
・必須度: ★☆☆
・git管理: 無し

画像3

クラスの名前や関係性を見てもらう際に使います。設計レビュー段階では具体的な実装までイメージ出来ていなくても、インターフェース部がある程度固まっていれば良いので、登場するオブジェクトの大半はインターフェース部で構成されています。
既存のクラスも登場させる必要がある場合はオブジェクトの背景色を変えて表現したりもします。大枠の括りはDomainの枠組みを表しています。

設計初期段階と最終的な実装はインターフェース部を含め変更されることが多いため、git管理するドキュメントには含みません。

枠を表現するためにnamespace, packageが用意されていますが、個人的にrectangleを使うことも多いです(見た目的な違いしかないですが)。

@startuml

package Hoge {
  package Domain {
    class Hoge {
      - id: HogeId 
    }
    class HogeId {
      - value: Int
    }
    Hoge -d-> HogeId
    interface HogeRepository {
      + find(by id: HogeId) -> Hoge
    }
    HogeRepository -d-> Hoge
  }

  package UseCase {
    interface HogeUseCase {
      + execute(by id: HogeId) -> Hoge
    }
    HogeUseCase -r-> HogeRepository
  }

  package Presentation {
    class HogeViewController {
      - viewModel: HogeViewModelType
    }
    interface HogeViewModelType {
      - init(hogeUseCase: HogeUseCase) 
    }
    HogeViewModelType -r-> HogeUseCase
    HogeViewController -d-> HogeViewModelType
  }
}

@enduml

シーケンス図

・使用頻度: ★★☆
・必須度: ★★★
・git管理: 有り

画像1

オブジェクト間の処理の流れを時間軸に沿って表現できるため、APIまでの通信処理の流れと、その間に登場する人物について見てもらう際に使います。
図はシンプルな画面表示時に必要な情報の流れを説明していますが、複数のAPIを同期的に表現する時もあります。
ここである程度処理に必要なクラスも書いているため、説明が完結する場合はクラス図を用意しなくても良いケースも多いです。

このAPIとの通信部分は機能の肝であり、他の人がこの機能を調査する際にも通信を介したデータの流れがわかりやすいため、git管理の対象にしています。更新があればこのPlantUMLファイルも更新するようにしています。

@startuml
title: Hoge情報取得処理
hide footbox

actor User
User -> HogeViewController: init(viewModel: HogeViewModel)
activate HogeViewController
HogeViewController -> HogeViewModel: init(hogeId: HogeId)
activate HogeViewModel
HogeViewModel -> HogeUseCase: execute(by id: HogeId)
activate HogeUseCase
HogeUseCase -> HogeRepository: find(by id: HogeId)
activate HogeRepository
HogeRepository -> HogeApi: init(hogeId: Int)
activate HogeApi
HogeApi -> HogeRepository: Observable<Hoge>
deactivate HogeApi
HogeRepository -> HogeUseCase: Observable<Hoge>
deactivate HogeRepository
HogeUseCase -> HogeViewModel: Observable<Hoge>
deactivate HogeUseCase
HogeViewModel -> HogeViewController: Driver<Hoge?>

@enduml

アクティビティ図

・使用頻度: ★☆☆
・必須度: ★★☆
・git管理: 有り

画像2

機能の中でロジックが煩雑な場合、ユーザー操作を軸に内部で行われてる一連の流れを説明する際に使います。仕様が固まっていればここの図は大きく変更することは無いのと、コードを追うよりも処理の流れを理解しやすいため、この図もgit管理対象しています。個人的にも過去に担当した機能の内容を振り返る際に重宝しています。

@startuml

start 
partition Hoge {
:Hoge情報取得;
note left 
資料『Hoge』参照
endnote
:ID値取得;
:DelegateでWebViewに渡す;
}
partition WebView {
 if () then (Main)
 -[#blue]->
   :Aアイコン表示;
   :Aアイコン押下;
   if (Aの人数 > 0) then (true)
     partition A一覧Popup {
       :OKボタン押下;
       :ダイアログを閉じる;   
     }
   else (false)
     partition A人数0Popup {
       :OKボタン押下;
       :ダイアログを閉じる;
     }
   endif
 else (Web_Hoge_Delegate)
 -[#black,dashed]->
   if (新規B人数 > 0) then (true)
     partition B一覧View {
       :Bアイコン表示;
     }
     if (B残人数 > 0) then (true)
       :Bアイコン表示;
     else (false)
       :Bアイコン非表示;
     endif
   endif
 endif
}
end
@enduml

その他

レビューの際はエディターからPlantUMLファイルの画像出力してGithubのPull Request本文に貼り付けたりするのですが、オブジェクトの量が多いと画像の最大サイズでも見切れてしまったりすることもあります。
その際は画像対応せず、設定レビュー用に一時的にPlantUMLファイルをgit上にpushし、PlantUML Visializerで確認してもらうようにしています。

最後に

クラス図をPlantUMLで書いたらそれをastah*の様にSwiftのファイルに変換できたらなぁというボイラープレート自動生成を企んでいたりするのですが、次回はそういった自動化対策をこの場でお伝えできるように頑張りたいと思います。

『Now in REALITY Tech』ではREALITYのエンジニアが毎週持ち回りで担当している技術記事です。バックナンバーは #Now_in_REALITY_Tech から見れます。

またREALITYでは設計をチームへ伝搬する最適解を考えたり、設計を考えるのが大好きな方を募集しています。気軽にREALITYのエンジニアとお喋りしてみたいという方がいましたら以下のリンクをご覧くださいmm