Upgrade to Pro — share decks privately, control downloads, hide ads and more …

hooks riverpod + state notifier + freezed でのド...

hooks riverpod + state notifier + freezed でのドメイン駆動設計

大規模アプリを作るときの指針として、hooks_riverpod、state_notifier、freezedを使ってドメイン駆動設計を取り入れた場合の実装例を紹介。2021/12 Flutter大学の勉強会にて登壇した資料

tokku5552

May 11, 2022
Tweet

More Decks by tokku5552

Other Decks in Programming

Transcript

  1. 目次 • ドメイン駆動設計の概要 ◦ ドメイン駆動設計とは? ◦ レイヤードアーキテクチャ ◦ DDD固有のパターン •

    各パッケージの説明 ◦ hooks_riverpod ◦ state_notifier ◦ freezed • 実践 • テスト(WIP)
  2. 自己紹介 とっく(@tokkuu) • 都内AdTech企業でフルスタックに働い て います。 • 業務ではphp/python/go(全部読むくら い。書けるとは言っていない )、

    AWS(EC2/ELB/RDS/Route53/Lambd a/ElastiCache/Kinesis/CloudFormatio n/EventBridge/CloudWatch)とか、 docker/ansible/terraformとかやってま す • Flutterは個人のみだけど1年くらい 鬼ロク: https://angless-production.web.app/ COUPLE TODO: https://couple-todo-product.web.app/
  3. レイヤードアーキテクチャ - ドメイン設計の概要 • プレゼンテーション層 ◦ ユーザーへの情報の表示 ◦ ユーザーからの入力の解釈 ◦

    外部アクタは人間ではなく別のシステムの場合もある • アプリケーション層 ◦ ビジネスにとって意味があるものか他のアプリケーション層と相互作用をする作業を行う ◦ ビジネスルールや知識自体は含まず、あくまでドメインオブジェクトに作業を委譲して調整を行う • ドメイン層 ◦ ビジネスルールを表す ◦ ビジネスの状態をここで制御する ◦ 永続化(DBに格納したり)は行わない • インフラストラクチャ層 ◦ 上位のレイヤを支える一般的な技術機能 ◦ 永続化やメッセージ送信などを担う
  4. DDD固有のパターン - ドメイン設計の概要 • エンティティ ◦ 同一性をもつ(==で比較できる) ◦ 連続性をもつ(可変である) •

    値オブジェクト ◦ 不変である ◦ 同一性を持たない ◦ 値オブジェクト同士の関連は持たせない • サービス ◦ エンティティにも値オブジェクトにも属さないものやふるまい ◦ 引数と結果はドメインオブジェクト ◦ ドメインレイヤに居るとは限らない。アプリケーションサービスやインフラストラクチャサービスなども考えられる ◦ どのレイヤにも属させず、 SINGLETONとして定義した方が分かりやすい場面もある • モジュール ◦ 他と低結合で高凝集の集まり
  5. DDD固有のパターン - ドメイン設計の概要 • 集約 ◦ 関連オブジェクトの集まり ◦ データを変更するための単位 ◦

    集約にはルートと境界がある ◦ 境界は集約の内部になにがあるかを定義するもの ◦ ルートは集約に含まれている特定の1エンティティ ◦ ルートエンティティはグローバルな同一性を持つ ◦ 境界内部のエンティティは集約内でのみ一意となるローカルな同一性を持つ ◦ 境界外のエンティティは集約ルートのみ参照を持つことができ、境界内部への参照を持つことはできな い • ファクトリ ◦ オブジェクトの生成自体を行うもの ◦ オブジェクトの生成はそのオブジェクトの責務ではない ◦ クライアント側で生成を行ってしまうとオブジェクトの詳細をクライアントが知ることになってしまってこれ も不自然 • リポジトリ ◦ データベースやストレージへの永続化をカプセル化して隠蔽する ◦ 集約ルートに対してリポジトリを提供する ◦ オブジェクトそのものを返さずとも、集計結果などを返すこともある
  6. hooks_riverpod - 各パッケージの説明 • Providerと同じ作者が作った Riverpodのhooks版 ◦ 最近1.0.0(stable)がリリースされました! • 今回紹介しきれない

    hooksの紹介を少しだけ... ◦ もともとReactにReact Hooksという状態管理の機能がある ◦ それを真似たもの ◦ 特徴としてはコード量が少なくなったり、手軽にメモ化(インスタンスのキャッシュ化をして再描画時されなくなる) • useEffect ◦ 監視する要素を指定できる ◦ 要素を指定しなければ最初の一回だけ実行することになる(こちらの用途が多い?) • useMemorized ◦ インスタンスをキャッシュするようになり、Widgetの再構築時でもこいつは再構築されなくなる • useFuture、useStream ◦ FutureBuilderとかStreamBuilderでかくよりもすっきり書ける ◦ useMemorizedと併用することで、再描画を防ぐことも出来る
  7. state_notifier - 各パッケージの説明 • これもProviderと同じ作者が作った ValueNotifierの自作版 • Flutter大学でおなじみChangeNotifierと同じような感じで使う • ChangeNotifier

    ◦ 複数の値を持てる ◦ notifyListener()を都度読んで、変更を通知しないと再描画されない • ValueNotifier ◦ Flutterに組み込まれている機能 ◦ 単一の値しか持てない ◦ ProviderやRiverpodと一緒に使おうと思うと、 ValueNotifierProviderなるものはないので、実質 StateNotifier一択 • StateNotifier ◦ ValueNotifierとほぼ同じだが、パフォーマンス的にこちらの方がいいらしい ◦ ProviderやRiverpodと一緒に使える
  8. freezed - 各パッケージの説明 • これもProviderと同じ作者が作ったパッケージ • immutable(不変)なクラスを自動生成してくれる便利なパッケージ • StateNotifierを使う場合、Stateとして保持する値はimmutableの方が都合が良い ◦

    例えば編集途中でキャンセルした場合などに、immutableであればそれを破棄するだけで いいが、mutable(可変)であれば他の箇所で影響が出ないように実装しておかないとバグを 生む可能性がある。immutableであれば破棄してしまえば良いので、気にしなくてもそのよ うなバグは起こりえない(https://medium.com/flutter-jp/state-1daa7fd66b94) • その他にもjson_serializableと併用して、toJson/fromJsonなどのメソッドを自動生成してくれたり して、コードを書く量を減らせる
  9. TodoItem エンティティ Title 値オブジェクト Detail 値オブジェクト TodoId 値オブジェクト 集約 集約ルート

    TodoAppService アプリケーション サービス TodoListState 状態(ListをStateNotifier で扱うため) TodoListReposit ory リポジトリ Firestore TodoListNotifier ViewModel https://github.com/tokku5552/flutter_ddd_riverpod アプリケーション層 TodoListPage UI プレゼンテーション層 インフラストラクチャ層 Factory ドメイン層
  10. まとめ • Todoアプリのような単純なアプリでは全く良さが伝わっていないかと思いますが、大規模で複雑になれ ばなるほど効力を発揮するはずです (より安全に書けるので ) • 今回の内容はFlutter大学アドベントカレンダーで公開予定の以下の記事に沿っています。 途中まで書いているので、もしよければご覧ください ◦

    https://qiita.com/tokkun5552/private/5dcb79e5283a67c2b2fe ▪ 現在限定共有設定。公開日になったら解放されます ▪ アドベントカレンダー (https://qiita.com/advent-calendar/2021/flutteruniv) • DDDはやはり実装コストが高いので、もう少し単純にしてもよさそう ◦ 特に今回はStateNotifierを使うためにわざわざ集約したので、無駄な感じがすごい • アドベントカレンダーまでにはテストのやり方まで書くつもりなのでご期待ください! ご清聴ありがとうございました!