hooks_riverpod  
state_notifier  
freezed での
ドメイン駆動設計
Flutter大学共同勉強会No.25
目次
● ドメイン駆動設計の概要
○ ドメイン駆動設計とは?
○ レイヤードアーキテクチャ
○ DDD固有のパターン
● 各パッケージの説明
○ hooks_riverpod
○ state_notifier
○ freezed
● 実践
● テスト(WIP)
自己紹介
とっく(@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/
ドメイン駆動設計の概要
ドメイン駆動設計とは? - ドメイン設計の概要
● ドメインとは、解決したいビジネス上の課題を含んだ領域のこと。平たく
言うと業務知識のこと。
● ドメインの知識を抽象化したものをモデルと呼び、ドメイン知識をモデル
に起こすことをドメインモデリングとか単にモデリングと呼ぶ。
● ドメイン駆動設計とはようするにドメインをしっかり深堀して、ドメインを
中心にソフトウェアの設計を進めていく手法のこと
レイヤードアーキテクチャ - ドメイン設計の概要
● プレゼンテーション層
○ ユーザーへの情報の表示
○ ユーザーからの入力の解釈
○ 外部アクタは人間ではなく別のシステムの場合もある
● アプリケーション層
○ ビジネスにとって意味があるものか他のアプリケーション層と相互作用をする作業を行う
○ ビジネスルールや知識自体は含まず、あくまでドメインオブジェクトに作業を委譲して調整を行う
● ドメイン層
○ ビジネスルールを表す
○ ビジネスの状態をここで制御する
○ 永続化(DBに格納したり)は行わない
● インフラストラクチャ層
○ 上位のレイヤを支える一般的な技術機能
○ 永続化やメッセージ送信などを担う
DDD固有のパターン - ドメイン設計の概要
DDD固有のパターン - ドメイン設計の概要
● エンティティ
○ 同一性をもつ(==で比較できる)
○ 連続性をもつ(可変である)
● 値オブジェクト
○ 不変である
○ 同一性を持たない
○ 値オブジェクト同士の関連は持たせない
● サービス
○ エンティティにも値オブジェクトにも属さないものやふるまい
○ 引数と結果はドメインオブジェクト
○ ドメインレイヤに居るとは限らない。アプリケーションサービスやインフラストラクチャサービスなども考えられる
○ どのレイヤにも属させず、 SINGLETONとして定義した方が分かりやすい場面もある
● モジュール
○ 他と低結合で高凝集の集まり
DDD固有のパターン - ドメイン設計の概要
● 集約
○ 関連オブジェクトの集まり
○ データを変更するための単位
○ 集約にはルートと境界がある
○ 境界は集約の内部になにがあるかを定義するもの
○ ルートは集約に含まれている特定の1エンティティ
○ ルートエンティティはグローバルな同一性を持つ
○ 境界内部のエンティティは集約内でのみ一意となるローカルな同一性を持つ
○ 境界外のエンティティは集約ルートのみ参照を持つことができ、境界内部への参照を持つことはできな
い
● ファクトリ
○ オブジェクトの生成自体を行うもの
○ オブジェクトの生成はそのオブジェクトの責務ではない
○ クライアント側で生成を行ってしまうとオブジェクトの詳細をクライアントが知ることになってしまってこれ
も不自然
● リポジトリ
○ データベースやストレージへの永続化をカプセル化して隠蔽する
○ 集約ルートに対してリポジトリを提供する
○ オブジェクトそのものを返さずとも、集計結果などを返すこともある
各パッケージの説明
hooks_riverpod - 各パッケージの説明
● Providerと同じ作者が作った Riverpodのhooks版
○ 最近1.0.0(stable)がリリースされました!
● 今回紹介しきれない hooksの紹介を少しだけ...
○ もともとReactにReact Hooksという状態管理の機能がある
○ それを真似たもの
○ 特徴としてはコード量が少なくなったり、手軽にメモ化(インスタンスのキャッシュ化をして再描画時されなくなる)
● useEffect
○ 監視する要素を指定できる
○ 要素を指定しなければ最初の一回だけ実行することになる(こちらの用途が多い?)
● useMemorized
○ インスタンスをキャッシュするようになり、Widgetの再構築時でもこいつは再構築されなくなる
● useFuture、useStream
○ FutureBuilderとかStreamBuilderでかくよりもすっきり書ける
○ useMemorizedと併用することで、再描画を防ぐことも出来る
state_notifier - 各パッケージの説明
● これもProviderと同じ作者が作った ValueNotifierの自作版
● Flutter大学でおなじみChangeNotifierと同じような感じで使う
● ChangeNotifier
○ 複数の値を持てる
○ notifyListener()を都度読んで、変更を通知しないと再描画されない
● ValueNotifier
○ Flutterに組み込まれている機能
○ 単一の値しか持てない
○ ProviderやRiverpodと一緒に使おうと思うと、 ValueNotifierProviderなるものはないので、実質
StateNotifier一択
● StateNotifier
○ ValueNotifierとほぼ同じだが、パフォーマンス的にこちらの方がいいらしい
○ ProviderやRiverpodと一緒に使える
freezed - 各パッケージの説明
● これもProviderと同じ作者が作ったパッケージ
● immutable(不変)なクラスを自動生成してくれる便利なパッケージ
● StateNotifierを使う場合、Stateとして保持する値はimmutableの方が都合が良い
○ 例えば編集途中でキャンセルした場合などに、immutableであればそれを破棄するだけで
いいが、mutable(可変)であれば他の箇所で影響が出ないように実装しておかないとバグを
生む可能性がある。immutableであれば破棄してしまえば良いので、気にしなくてもそのよ
うなバグは起こりえない(https://medium.com/flutter-jp/state-1daa7fd66b94)
● その他にもjson_serializableと併用して、toJson/fromJsonなどのメソッドを自動生成してくれたり
して、コードを書く量を減らせる
実践
TodoItem
エンティティ
Title
値オブジェクト
Detail
値オブジェクト
TodoId
値オブジェクト
集約
集約ルート
TodoAppService
アプリケーション
サービス
TodoListState
状態(ListをStateNotifier
で扱うため)
TodoListReposit
ory
リポジトリ
Firestore
TodoListNotifier
ViewModel
https://github.com/tokku5552/flutter_ddd_riverpod
アプリケーション層
TodoListPage
UI
プレゼンテーション層
インフラストラクチャ層
Factory
ドメイン層
まとめ
● Todoアプリのような単純なアプリでは全く良さが伝わっていないかと思いますが、大規模で複雑になれ
ばなるほど効力を発揮するはずです (より安全に書けるので )
● 今回の内容はFlutter大学アドベントカレンダーで公開予定の以下の記事に沿っています。
途中まで書いているので、もしよければご覧ください
○ https://qiita.com/tokkun5552/private/5dcb79e5283a67c2b2fe
■ 現在限定共有設定。公開日になったら解放されます
■ アドベントカレンダー (https://qiita.com/advent-calendar/2021/flutteruniv)
● DDDはやはり実装コストが高いので、もう少し単純にしてもよさそう
○ 特に今回はStateNotifierを使うためにわざわざ集約したので、無駄な感じがすごい
● アドベントカレンダーまでにはテストのやり方まで書くつもりなのでご期待ください!
ご清聴ありがとうございました!

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