Flutter アプリの将来のインフラ移行に備える 疎結合なソフトウェア・アーキテクチャ / Flutter code Architecture for Infrastructure Migration
by
Takahiro Ikeuchi
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Flutter アプリの将来のインフラ移行に備える 疎結合なソフトウェア・アーキテクチャ 株式会社Hakali 取締役CTO Takahiro Ikeuchi - 池内 孝啓 FlutterKaigi 2022
Slide 2
Slide 2 text
Agenda 自己紹介 - 2分 インフラ移行にどう備えるか - 5分 疎結合なソフトウェア・アーキテクチャを目指して - 20分 アンチパターン2選 - 5分 まとめ - 3分 1. 2. 3. 4. 5. 💡 資料およびサンプルコードは公開いたします 2
Slide 3
Slide 3 text
池内 孝啓(いけうち たかひろ) デジタル認知行動療法アプリ Awarefy CTO。 https://github.com/iktakahiro https://iktakahiro.dev/ 自己紹介 @iktakahiro https://www.awarefy.app 3
Slide 4
Slide 4 text
Android/iOS 両対応のプロダクト開発のため、2019年9月に Flutter を採用、以来となるFlutter歴3年。 Flutterと私 https://pub.dev/packages/iso_calendar https://pub.dev/packages/fargon2 OSS (pub.dev) 4
Slide 5
Slide 5 text
本日のテーマ インフラ移行にどう備えるか 5
Slide 6
Slide 6 text
少人数でプロダクトを開発してリリースまで もっていかなくちゃ... Firebase や Supabase がいいかも.... ベンダーロックインが心配だな.... 6
Slide 7
Slide 7 text
実録!Firebase to AWS 2020年5月にリリース時点でバックエンドは Firebase の 完全サーバーレス 2022年7月にAWSに移行 Amazon EKS x Amazon Aurora Serverless v2 サーバーサイドアプリを運用開始 7
Slide 8
Slide 8 text
Firebase 選定の理由 - 2019年 関心事を Flutter に限定したかった リリースまでのスピード! SDK もあるしよさそう 8
Slide 9
Slide 9 text
Firebase 移行の理由 - 2021年 ビジネスロジックの複雑化への対応 データマイグレーション時の負担の解消 運用面の諸々の強化 (バックアップ、リストア、セキュリティ etc) RDB 化を決意。 ※ ニーズとの相性の問題。Firestore はいいサービスです! 9
Slide 10
Slide 10 text
新インフラ - 2022年 クラウドインフラ選定に関する 詳細は割愛 ※
Slide 11
Slide 11 text
おもな変更点 バックエンドアプリのスクラッチ実装(Go + gRPC) インフラ基板の刷新(Amazon EKS) データストアの刷新(Amazon Aurora Serverless v2) ※ データマイグレーションの話は今回取り扱いません 11
Slide 12
Slide 12 text
Before モバイルアプリ Firestore 12
Slide 13
Slide 13 text
After モバイルアプリ Web App PostgreSQL 13
Slide 14
Slide 14 text
インフラ移行にどう備える(た)か? 14
Slide 15
Slide 15 text
結論 15
Slide 16
Slide 16 text
結論 インフラレイヤーの抽象化をしておく 16
Slide 17
Slide 17 text
結論 17 なるべく早期(できれば最初)から!
Slide 18
Slide 18 text
疎結合な ソフトウェア・アーキテクチャを目指して 18
Slide 19
Slide 19 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/ 依存性逆転の原則を用いてインフラを 最も外側に置く オニオン・アーキテクチャ テスト
Slide 20
Slide 20 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト Flutter (Widget) = プレゼンテーション層 Firebase などの mBaaS = インフラ層 20
Slide 21
Slide 21 text
Flutter Widget ユースケース リポジトリ(インターフェース) コードの依存関係 実際のデータの流れ Flutter Widget ユースケース リポジトリ(実装) 21
Slide 22
Slide 22 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト Entity Value Object Repository Service ドメイン層 ドメインモデルと リポジトリインターフェースの定義
Slide 23
Slide 23 text
ドメインモデル(Entity) ※ モデルやコードはすべて簡略化しています
Slide 24
Slide 24 text
リポジトリ(永続化処理)の抽象化 Dartとインターフェース : https://dart.dev/samples#interfaces-and-abstract-classes https://dart.dev/guides/language/language-tour#implicit-interfaces
Slide 25
Slide 25 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト DB HTTPS RESTFul gRPC インフラ層 リポジトリの実装 25
Slide 26
Slide 26 text
特定のシステムに紐付くものはすべてインフラ RDB(MySQL, PostgreSQL) NoSQL(Firestore, MongoDB) HTTPS / RESTFul API gRPC / Protocol Buffers SMTP SDK インフラ ≒ 具体
Slide 27
Slide 27 text
Firestore 向けリポジトリ(永続化処理)の実装 クラス名なども具体的なインフラの命名をつけておくと後々わかりやすい
Slide 28
Slide 28 text
Firestore 向け DTO Firestore のデータ(Map)と ドメインモデルを相互変換する
Slide 29
Slide 29 text
Dart と DTO (Data Transfer Object) インフラ層のデータ構造とドメインオブジェクトをマッピング JSON とオブジェクトの相互変換が必要な場合 freezed パッケ ージ周辺のツールが便利 toJson, fromJson が生える immutable なデータクラスとしての振る舞い https://pub.dev/packages/freezed
Slide 30
Slide 30 text
リポジトリ(インフラ層)抽象化の意義 ドメインオブジェクトの隔離とテスタビリティの確保が主目的 副次的にインフラ変更に強くなる SOLID 原則 : 抽象に依存せよ 30
Slide 31
Slide 31 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト ユースケース CQRS ユースケース層 ユースケースのインターフェースの 定義およびその実装
Slide 32
Slide 32 text
ユースケース(インターフェース) ここでも欠かさず抽象化。プレゼンテーション層のテストがやりやすく なります。 ※
Slide 33
Slide 33 text
ユースケース(実装) リポジトリのインターフェースに依存(実装には依存しない)
Slide 34
Slide 34 text
ユースケースの初期化と登録 のちほど取り出して使います。
Slide 35
Slide 35 text
ドメインオブジェクトからのインフラ層の隔離はOK NEXT : プレゼンテーション層 35
Slide 36
Slide 36 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト UI(View) View Model Controller Routing プレゼンテーション層
Slide 37
Slide 37 text
View View Model Flutter Widget Riverpod プレゼンテーション層の View と View Model ※ 状態管理は Riverpod である必要はないです。他の選択肢でもOK
Slide 38
Slide 38 text
Flutter Widget ユースケース リポジトリ(インターフェース) コードの依存関係 実際のデータの流れ Flutter Widget ユースケース リポジトリ(実装) View Model (Riverpod) View Model (Riverpod)
Slide 39
Slide 39 text
Riverpod + StateNotifier Riverpod StateNotifier freezed の3点セット
Slide 40
Slide 40 text
View Model からユースケースを利用 ユースケースのインターフェースに依存(実装には依存しない) 40
Slide 41
Slide 41 text
Riverpod + Hooks View Model の メソッドと状態にアクセス
Slide 42
Slide 42 text
ドメイン ユースケース プレゼンテーション(UI ) インフラ インフラ層をふくめ 各レイヤーが疎結合な状態を達成 テスト バックエンドに関する変更の場合、 インフラ層のみの変更で対応可能 ※ もちろん理想的にいけば、の場合
Slide 43
Slide 43 text
インフラを差し替えてみよう
Slide 44
Slide 44 text
SQLite 向けリポジトリ(永続化処理)の実装 リポジトリを二重に実装する 意味はありませんが、例です SQLite のデータ(Map)と ドメインモデルを相互変換する
Slide 45
Slide 45 text
SQLite 向け DTO 45
Slide 46
Slide 46 text
これを...
Slide 47
Slide 47 text
インフラの差し替え!! こうする!!
Slide 48
Slide 48 text
No content
Slide 49
Slide 49 text
モバイルアプリ Web App PostgreSQL モバイルアプリから見るとここから 先がインフラ層
Slide 50
Slide 50 text
アンチパターン2選 50
Slide 51
Slide 51 text
アンチパターン : UIとインフラの密結合 サンプルコードではよくある(?)やつ
Slide 52
Slide 52 text
インフラ層の変更に Widget が直接影響を受けてしまう 実質的には1つのインフラ(DB)にのみ対応 テストが書きにくい、書けない コード量が最小限になる デメリット : メリット : アンチパターン : UIとインフラの密結合 💡 プロトタイピングでは有効な面も(それでもおすすめはしません)
Slide 53
Slide 53 text
アンチパターン : 全知全能モデル MVCフレームワークや O/R Mapper を使うとなりがち
Slide 54
Slide 54 text
アンチパターン : 全知全能モデル 複数のレイヤーの関心事が含まれてしまう DBの都合でモデルに変更が入る、とか クラス定義が1つで済む デメリット : メリット : 💡 DTOに辛みを感じたらスニペット利用やコード生成などで 単純作業コストを減らそう。
Slide 55
Slide 55 text
まとめ 55
Slide 56
Slide 56 text
今日話したことまとめ インフラ移行は意外と起こる コードーベースの初期設計から疎結合に保つことが大事 Flutter/Dart でオニオン・アーキテクチャは手軽に実践可能! 56
Slide 57
Slide 57 text
結論
Slide 58
Slide 58 text
ありがとうございました! https://github.com/iktakahiro/flutter-starter https://github.com/iktakahiro https://iktakahiro.dev/ @iktakahiro サンプルコード 58