ローソンデジタルイノベーション テックブログ

ローソンデジタルイノベーション(LDI)の技術ブログです

在宅勤務報告システムで採用したFlutterアプリ開発におけるアーキテクチャについて紹介します!

はじめに

こんにちは、ローソンデジタルイノベーション(LDI)でiOSエンジニアを担当している山形です。
今回は以下の記事でご紹介した在宅勤務報告システムの開発で採用したFlutterアプリのアーキテクチャについて記事にしたいと思います。 techblog.ldi.co.jp

採用したアーキテクチャ

以下の2つのアーキテクチャを採用しそれを組み合わせた形で開発しました。

Clean Architecture

ビジネスルールであるEntityを中心に置き、外側のレイヤから内側に向かってのみ依存する状態を維持することで関心の分離を行いプログラムの再利用や変更を容易にすること、またテストの容易性を向上させることを目的とした概念です。
私たちは業務でAndroid, iOSアプリを開発していますがClean Architectureを採用しており、Flutterにおいてもこうしたメリットを享受することができるため採用しました。

MVVM(Model, View, ViewModel)

プログラムを3つのレイヤに分けてそれぞれの責務を分担することでビジネスロジックとプレゼンテーションロジックをUIから切り離してテストの容易性やメンテナンス性を向上させることを目的とした概念です。
ViewとViewModelはデータバインディングすることによって実現することがほとんどかと思います。
FlutterにおいてもMVVMはGUI(Graphical User Interface)を持ったアプリを開発する上でこうしたメリットを享受することができるため採用しました。

Flutter界隈ではRiverpodという状態管理ライブラリがデファクトスタンダードかなと思います。
MVVMの中でどうやって状態管理していくのかが悩みどころですね。
一例として在宅勤務報告システムではどう実現したのか記事にしていますのでぜひ読んでみてください!

techblog.ldi.co.jp

どうやって組み合わせるの?

Clean Architecture, MVVMともにアーキテクチャを考える上での概念です。
それをどう落とし込んでいくかは難しいところでこれだ!といった正解はないのかなと思います。
では私たちはどのようにClean Architecture, MVVMの形に落とし込んでいったのかご紹介します。

Clean Architecture

まず、Clean Architectureの考え方のもと以下の3層構造にレイヤ分けを行いました。
アプリケーション全体のルールとしてこの3層レイヤと依存の方向は絶対のルールとなり、開発者はこれを拠り所として開発を行っていきます。

レイヤ 意味
Presentation UIに関わる画面の実装や表示のためのロジックを実装します。
Domain ビジネスロジックを実装します。Clean Architectureにおけるビジネスルールの定義であるEntityはこのレイヤに属するため依存方向の中心はこのレイヤに向かっていきます。
Data DBやWeb APIなどのデータソースへアクセスするためのロジックを実装します。ここではRepositoryパターンを適用する形で実装しました。

依存の関係と合わせて図に起こすと以下のようなイメージになります。

依存方向
依存方向
Data
Domain
Presentation

MVVM

次にMVVMの形で実現するためModel, View, ViewModelの3層レイヤをClean Architectureの考え方をもとに分けた3層レイヤに落とし込んで行きます。
Model, View, ViewModelはそれぞれPresentationとDomainレイヤに属するようにしました。

レイヤ 意味
Model Domainレイヤに属します。
ビジネスルールの定義であるEntityを取り扱うことができ、ここにビジネスロジックを実装します。
View Presentationレイヤに属します。
画面をここで実装します。ViewはViewModelを保持しViewModelから受け取った情報を表示します。
ViewModel Presentationレイヤに属します。
画面表示のために必要なロジックを実装します。ViewModelはModelを保持しModelから受け取った情報をViewに必要な形式に変換して渡します。

図に起こすと以下のようになります。

依存方向
Domain
Model
Entity
Presentation
ViewModel
View

最終形(Clean Architecture+MVVM)

ここから最終的に必要なものは何か考え付け足していった結果、以下の図ような形に落ち着きました。

Data
Domain
Presentation
呼び出し
呼び出し
呼び出し
呼び出し
↑インターフェースの実装
呼び出し
呼び出し
Repository
Web API
Local Storage
Model
Entity
Repository Interface
View
ViewModel

特に注目していただきたいのが、Repository Interfaceの登場です。
MVVMではView → ViewModel → Modelの順で処理を実行していきますがClean Architectureの考え方ではDomainレイヤにあるEntityが依存関係の中心にあります。
DomainレイヤからDataレイヤへの依存があってはいけません。
これを解決するためにDomainレイヤにRepositoryのInterfaceを用意しDataレイヤでこれを実装していきます。
こうすることで依存方向をDataレイヤからDomainレイヤに向けることができ、開発の土台が出来上がりました。  
これは依存性逆転の原則(Dependency inversion principle)というテクニックです。

以上で在宅勤務報告システムの開発で採用したFlutterアプリのアーキテクチャの説明を終わります。

実装してみて感じたこと

メリット

アーキテクチャ設計を立ち上げの時期にしっかりやっておくと実装をある程度標準化できるため、担当者によって実装のばらつきを抑えることができました。
これはとても良いことで、アーキテクチャ設計に沿って依存の方向は正しいか、必要な単位でクラス分割されているかなど、実装時はもちろんコードレビュー時にもチェックすることで、一定の品質を保つことができます。

デメリット

Clean ArchitectureやMVVMなどアーキテクチャ設計によって実装を標準化することで小さな機能でもクラス数がどうしても多くなってしまいます。
関心の分離を実現し拡張性やテストの容易性を保ち継続的に成長させるシステムにするには致し方のないことですが、工数はその分膨らんでしまうかなと思います。
なので、継続的に長く運用するシステムはしっかりアーキテクチャ設計を行い、一定期間運用しサービスを停止する予定のあるシステムはシンプルなアーキテクチャ設計にすると良いですね。

最後に

ここまで記事を読んでいただきありがとうございます!
まだまだ書き足りないことが色々ありますが、今後もローソンデジタルイノベーションでは技術ブログを更新していきますので、是非「読者になる」で応援していただけますと幸いです。