$30 off During Our Annual Pro Sale. View Details »

Flutter アプリの将来のインフラ移行に備える 疎結合なソフトウェア・アーキテクチャ / Flutter code Architecture for Infrastructure Migration

Flutter アプリの将来のインフラ移行に備える 疎結合なソフトウェア・アーキテクチャ / Flutter code Architecture for Infrastructure Migration

近年、モバイルアプリのクロスプラットフォーム対応を進める目的で Flutter が導入されることが増えてきています。くわえて、とりわけ少数のチームで開発を進める場合、開発効率を高めるために mBaaS が導入されることも少なくありません。そこで課題となるのが、中長期的な運用に足る拡張性やスケーラビリティと短期的な開発効率のバランスをどのように確保していくか、ということです。

本セッションでは、短期的な開発効率を高めつつも将来のインフラ移行に備えることが可能な疎結合なアーキテクチャを Flutter プロジェクトの初期から採用することを提案し、その具体的な設計やコードのサンプルを解説します。

- Flutter とオニオン・アーキテクチャ
- インフラ層を隔離することの意義とその方法
- 疎結合を実現する状態管理モデル(Riverpod, StateNotifier)

Takahiro Ikeuchi

November 18, 2022
Tweet

More Decks by Takahiro Ikeuchi

Other Decks in Technology

Transcript

  1. Flutter アプリの将来のインフラ移行に備える 疎結合なソフトウェア・アーキテクチャ 株式会社Hakali 取締役CTO Takahiro Ikeuchi - 池内 孝啓

    FlutterKaigi 2022
  2. Agenda 自己紹介 - 2分 インフラ移行にどう備えるか - 5分 疎結合なソフトウェア・アーキテクチャを目指して - 20分

    アンチパターン2選 - 5分 まとめ - 3分 1. 2. 3. 4. 5. 💡 資料およびサンプルコードは公開いたします 2
  3. 池内 孝啓(いけうち たかひろ) デジタル認知行動療法アプリ Awarefy CTO。 https://github.com/iktakahiro https://iktakahiro.dev/ 自己紹介 @iktakahiro

    https://www.awarefy.app 3
  4. Android/iOS 両対応のプロダクト開発のため、2019年9月に Flutter を採用、以来となるFlutter歴3年。 Flutterと私 https://pub.dev/packages/iso_calendar https://pub.dev/packages/fargon2 OSS (pub.dev) 4

  5. 本日のテーマ インフラ移行にどう備えるか 5

  6. 少人数でプロダクトを開発してリリースまで もっていかなくちゃ... Firebase や Supabase がいいかも.... ベンダーロックインが心配だな.... 6

  7. 実録!Firebase to AWS 2020年5月にリリース時点でバックエンドは Firebase の 完全サーバーレス 2022年7月にAWSに移行 Amazon EKS

    x Amazon Aurora Serverless v2 サーバーサイドアプリを運用開始 7
  8. Firebase 選定の理由 - 2019年 関心事を Flutter に限定したかった リリースまでのスピード! SDK もあるしよさそう

    8
  9. Firebase 移行の理由 - 2021年 ビジネスロジックの複雑化への対応 データマイグレーション時の負担の解消 運用面の諸々の強化 (バックアップ、リストア、セキュリティ etc) RDB

    化を決意。 ※ ニーズとの相性の問題。Firestore はいいサービスです! 9
  10. 新インフラ - 2022年 クラウドインフラ選定に関する 詳細は割愛 ※

  11. おもな変更点 バックエンドアプリのスクラッチ実装(Go + gRPC) インフラ基板の刷新(Amazon EKS) データストアの刷新(Amazon Aurora Serverless v2)

    ※ データマイグレーションの話は今回取り扱いません 11
  12. Before モバイルアプリ Firestore 12

  13. After モバイルアプリ Web App PostgreSQL 13

  14. インフラ移行にどう備える(た)か? 14

  15. 結論 15

  16. 結論 インフラレイヤーの抽象化をしておく 16

  17. 結論 17 なるべく早期(できれば最初)から!

  18. 疎結合な ソフトウェア・アーキテクチャを目指して 18

  19. ドメイン ユースケース プレゼンテーション(UI ) インフラ https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/ 依存性逆転の原則を用いてインフラを 最も外側に置く オニオン・アーキテクチャ テスト

  20. ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト Flutter (Widget) = プレゼンテーション層

    Firebase などの mBaaS = インフラ層 20
  21. Flutter Widget ユースケース リポジトリ(インターフェース) コードの依存関係 実際のデータの流れ Flutter Widget ユースケース リポジトリ(実装)

    21
  22. ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト Entity Value Object Repository

    Service ドメイン層 ドメインモデルと リポジトリインターフェースの定義
  23. ドメインモデル(Entity) ※ モデルやコードはすべて簡略化しています

  24. リポジトリ(永続化処理)の抽象化 Dartとインターフェース : https://dart.dev/samples#interfaces-and-abstract-classes https://dart.dev/guides/language/language-tour#implicit-interfaces

  25. ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト DB HTTPS RESTFul gRPC

    インフラ層 リポジトリの実装 25
  26. 特定のシステムに紐付くものはすべてインフラ RDB(MySQL, PostgreSQL) NoSQL(Firestore, MongoDB) HTTPS / RESTFul API gRPC

    / Protocol Buffers SMTP SDK インフラ ≒ 具体
  27. Firestore 向けリポジトリ(永続化処理)の実装 クラス名なども具体的なインフラの命名をつけておくと後々わかりやすい

  28. Firestore 向け DTO Firestore のデータ(Map)と ドメインモデルを相互変換する

  29. Dart と DTO (Data Transfer Object) インフラ層のデータ構造とドメインオブジェクトをマッピング JSON とオブジェクトの相互変換が必要な場合 freezed

    パッケ ージ周辺のツールが便利 toJson, fromJson が生える immutable なデータクラスとしての振る舞い https://pub.dev/packages/freezed
  30. リポジトリ(インフラ層)抽象化の意義 ドメインオブジェクトの隔離とテスタビリティの確保が主目的 副次的にインフラ変更に強くなる SOLID 原則 : 抽象に依存せよ 30

  31. ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト ユースケース CQRS ユースケース層 ユースケースのインターフェースの

    定義およびその実装
  32. ユースケース(インターフェース) ここでも欠かさず抽象化。プレゼンテーション層のテストがやりやすく なります。 ※

  33. ユースケース(実装) リポジトリのインターフェースに依存(実装には依存しない)

  34. ユースケースの初期化と登録 のちほど取り出して使います。

  35. ドメインオブジェクトからのインフラ層の隔離はOK NEXT : プレゼンテーション層 35

  36. ドメイン ユースケース プレゼンテーション(UI ) インフラ テスト UI(View) View Model Controller

    Routing プレゼンテーション層
  37. View View Model Flutter Widget Riverpod プレゼンテーション層の View と View

    Model ※ 状態管理は Riverpod である必要はないです。他の選択肢でもOK
  38. Flutter Widget ユースケース リポジトリ(インターフェース) コードの依存関係 実際のデータの流れ Flutter Widget ユースケース リポジトリ(実装)

    View Model (Riverpod) View Model (Riverpod)
  39. Riverpod + StateNotifier Riverpod StateNotifier freezed の3点セット

  40. View Model からユースケースを利用 ユースケースのインターフェースに依存(実装には依存しない) 40

  41. Riverpod + Hooks View Model の メソッドと状態にアクセス

  42. ドメイン ユースケース プレゼンテーション(UI ) インフラ インフラ層をふくめ 各レイヤーが疎結合な状態を達成 テスト バックエンドに関する変更の場合、 インフラ層のみの変更で対応可能

    ※ もちろん理想的にいけば、の場合
  43. インフラを差し替えてみよう

  44. SQLite 向けリポジトリ(永続化処理)の実装 リポジトリを二重に実装する 意味はありませんが、例です SQLite のデータ(Map)と ドメインモデルを相互変換する

  45. SQLite 向け DTO 45

  46. これを...

  47. インフラの差し替え!! こうする!!

  48. None
  49. モバイルアプリ Web App PostgreSQL モバイルアプリから見るとここから 先がインフラ層

  50. アンチパターン2選 50

  51. アンチパターン : UIとインフラの密結合 サンプルコードではよくある(?)やつ

  52. インフラ層の変更に Widget が直接影響を受けてしまう 実質的には1つのインフラ(DB)にのみ対応 テストが書きにくい、書けない コード量が最小限になる デメリット : メリット :

    アンチパターン : UIとインフラの密結合 💡 プロトタイピングでは有効な面も(それでもおすすめはしません)
  53. アンチパターン : 全知全能モデル MVCフレームワークや O/R Mapper を使うとなりがち

  54. アンチパターン : 全知全能モデル 複数のレイヤーの関心事が含まれてしまう DBの都合でモデルに変更が入る、とか クラス定義が1つで済む デメリット : メリット :

    💡 DTOに辛みを感じたらスニペット利用やコード生成などで 単純作業コストを減らそう。
  55. まとめ 55

  56. 今日話したことまとめ インフラ移行は意外と起こる コードーベースの初期設計から疎結合に保つことが大事 Flutter/Dart でオニオン・アーキテクチャは手軽に実践可能! 56

  57. 結論

  58. ありがとうございました! https://github.com/iktakahiro/flutter-starter https://github.com/iktakahiro https://iktakahiro.dev/ @iktakahiro サンプルコード 58