Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Domain Driven reDux - or Redux as CQRS
Search
fsubal
December 08, 2018
Programming
1
1.5k
Domain Driven reDux - or Redux as CQRS
ピクシブ社内エンジニア勉強会(2018-12-07)の資料です
fsubal
December 08, 2018
Tweet
Share
More Decks by fsubal
See All by fsubal
負債になりにくいCSSをデザイナとつくるには?
fsubal
11
3.4k
Webデザインと フロントエンド技術🔰勉強会
fsubal
2
310
Tailwind CSSを本気でカスタマイズする方法
fsubal
17
7.6k
デザインシステムで Tailwind CSSとCSS in JSに分散投資をしたら良かった話
fsubal
20
7.3k
『Tailwind CSS実践入門』 出版記念基調講演
fsubal
9
5.3k
Sprockets CSSもやめる なぜ / Why stop using Sprockets for CSS too
fsubal
3
1.6k
The Majestic MPA
fsubal
8
3.3k
Backbone.Model に 型をつけて剥がす - Typing to destroy Backbone.Model
fsubal
1
1.1k
SVG + React でつくる レイヤーの自由変形 / Layer Transformation with React + SVG
fsubal
1
9.5k
Other Decks in Programming
See All in Programming
Tinkerbellから学ぶ、Podで DHCPをリッスンする手法
tomokon
0
120
手軽に積ん読を増やすには?/読みたい本と付き合うには?
o0h
PRO
1
170
AIコーディングエージェント(skywork)
kondai24
0
150
新卒エンジニアのプルリクエスト with AI駆動
fukunaga2025
0
200
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
120
Navigation 3: 적응형 UI를 위한 앱 탐색
fornewid
1
220
20 years of Symfony, what's next?
fabpot
2
350
【CA.ai #3】Google ADKを活用したAI Agent開発と運用知見
harappa80
0
290
ID管理機能開発の裏側 高速にSaaS連携を実現したチームのAI活用編
atzzcokek
0
210
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
6
2.1k
Full-Cycle Reactivity in Angular: SignalStore mit Signal Forms und Resources
manfredsteyer
PRO
0
120
SwiftUIで本格音ゲー実装してみた
hypebeans
0
110
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.3k
Agile that works and the tools we love
rasmusluckow
331
21k
Testing 201, or: Great Expectations
jmmastey
46
7.8k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
The Pragmatic Product Professional
lauravandoore
37
7.1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Writing Fast Ruby
sferik
630
62k
Facilitating Awesome Meetings
lara
57
6.7k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
How to train your dragon (web standard)
notwaldorf
97
6.4k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
Transcript
Domain Driven reDux あるいは Redux as CQRS pixiv Inc. f_subal
2018/12/07
2 誰 • pixivFACTORY フロントエンド • 巨大Reactコンポーネント建造業 • グッズ制作画面とか作ってます @f_subal
3
4 グッズの種類 グッズの仕様 テンプレート 材質 ページ レイヤー グッズの バリエーション アイテム
ドメインロジックが厚い フロントエンドを作っていく話 5
• Redux は ただのクライアントサイド CQRS だよ • C と Q
をドメインごとに切ると捗るよ ◦ けど純粋な ducks パターンはきついよ • ドメインモデルはプレーンな json と純粋関数で持つと良いよ • ある程度 Redux 習熟してる人向けです 6 話すこと
7
• みんな大好き状態管理層(強いグローバル変数) • 単方向データフローと相性がいい • フロントエンドでCQRSするやつ ◦ そのための pub /
sub と middleware の仕組みを提供するライブラリ ◦ https://speakerdeck.com/yamatatsu/reduxdebizinesurozitukuwogorigorishu-ku ?slide=12 8 Redux ってなんだっけ
9 http://krasimirtsonev.com/blog/articl e/my-take-on-redux-architecture
10 ThunkAction ( ≒ C 更新系) Selector ( ≒ Q
参照系) Action (ドメインイベント) http://krasimirtsonev.com/blog/articl e/my-take-on-redux-architecture
• CQRS とは ◦ Command(更新系)と Query(参照系)で実装を分離しようぜっていう考え ◦ 同じエンティティでも更新系と参照系では関心が異なるという前提に基づく • flux
は「データが単方向に流れる」という点から説明されることが多いが ◦ 実は Store の更新と参照を別のフローに分離したという点が結構重要 11 Redux as CQRS
Action 12
• flux における Action には2つの意味がある ◦ Domain Event を発行する ActionCreator
◦ UseCase としての Action( ex: redux-thunk, redux-saga, redux-observable ) • アプリケーション内で「起こった出来事」を表す ◦ ので、過去形で命名するようにしている • UseCase としての Action は、複数の Domain Event を投げることがある 13 Action = 更新系
• Action = アプリケーション内で「起こった出来事」 ◦ ので、過去形 or 完了形で命名するようにする ◦ 命令
とか 処理を表す名前にすると、実装者が責務を誤解する • ◎ → USER_PROFILE_LOADED // よい • △ → FETCH_USER_COMPLETE // まだマシ • × → FETCH_USER_BY_ID // やめて 14 Action = 起こった出来事
15
16
• 以下、暗に redux-thunk の使用を想定する • 「Ajax リクエストをして成功したら USER_LOADED を、失敗したら USER_LOADING_FAILED
を dispatch したい」みたいな、複数の action を発行しうる一連 の手続き • CQRS の C( Command )の部分 • Action との統一の都合上こちらも過去形で命名している 17 ThunkAction = ユースケース
18
• Redux 始めた人が最初に悩むやつ • Action と Reducer に何をどこまでやらせるか曖昧になりがち • ベストプラクティスとして
reducer には複雑な処理を書かない、と言われるが ◦ 言われるだけでなんでダメなのか分かってない人もいると思う ◦ 各種ドキュメントはあんまりこの辺教えてくれない 19 Action と reducer の責務問題
• case SET_NEW_ITEM: みたいな命名をしていると、あたかも reducer で副作用を起こし ていいかのような誤解が生じる ◦ SET_* 系の命名マジでやめたほうがいいと思う
• case NEW_ITEM_LOADED: と命名すれば、ロード自体はもう終わっていて、良いから後 は store に反映して、という理解になりやすい(たぶん) • 「アプリケーションで起こった出来事に反応して自身を更新」という構造にする 20 Action と reducer の混同は命名で矯正できる よ(過激派)
21
• 特定のドメインで起こりうる出来事の一覧を enum + ActionCreator として定義 ◦ 過去形で表現されるドメインイベントの一覧 • 複数の
Action を発行することのできるユースケースを Thunk Action として定義 ◦ 統一のため thunk も過去形で命名している ◦ ex) userProfileRequested() という thunk を投げると、USER_PROFILE_LOADED が dispatch される • reducer は Action の発生を見守る(何か起きたら自身を更新する) 22 factory における Action + Reducer
参照系 23
• 前提として Redux の Store はでかい • アプリケーションドメインが全部入った 1枚のJSON 24
Selector = 参照系
25 グッズの種類 グッズの仕様 テンプレート 材質 ページ レイヤー グッズの バリエーション アイテム
• コンポーネントがこのでっかい JSON から値を引く際、Store の内部構造を知らなくても すっと引ける仕組みが欲しい • これが selector(実装には自動メモ化機能などがついた reselect
が使われる) • CQRS の Q の部分(参照系のビジネスロジック) 26 Selector = 参照系
27
ドメインごとに切る 28
• action, reducer, selector をどういう構成で置くかはプロジェクトごとに結構違う • 一番良く見るのは次の形式 /actions user.ts /reducers
user.ts /selectors 29 redux のディレクトリ構成
• ファイル移動が多くなりがち • 「俺は user が規約に同意したことを true にしたいだけなのに、なんでディレクトリ 4つもま たいでるの、アホなの」問題
• 対抗策としていわゆる ducks パターンという設計が出てきた 30 /actions 形式の問題
• 同じドメインの action, reducer, selector を1ファイルにまとめる設計 • 各 ducks は完全に中に閉じる(基本相互に関係しあわない)
/modules /user duck.ts /item duck.ts 31 ducks パターン
32 https://webbibouroku.com/Blog/Article/redux-ducks
• ducks パターンだと流石に閉じすぎててつらいということから出てきた(多分) • ドメインごとに切る点は踏襲してるが、ファイルは別々 /domains /user action.ts reducer.ts selector.ts
33 re-ducks パターン
• だいたい re-ducks パターンの変形 • 各ドメインは相互に干渉し会える ◦ 「Product の thunk
が Specification の actionを発行」とかを許容している ◦ 純粋な ducks パターンで 1 ファイルにまとめる と ↑ がやりずらくなるのでやめた 34 factory のファイル構成
• 実はリニューアル前の旧エディタは /actions のようにディレクトリを切っていた • 結局の所 Store 内の 1個の値を更新するのにファイル移動が異常に多くて萎えた •
新しい設計でもファイル移動は発生するが、同じドメインなら同じフォルダなので面倒さは 少ない • ドメインごとにフォルダを切ったことでコンテキストが境界づけられたのも良かった • 結論おすすめです 35 factory のファイル構成
ところで 36
• 型定義 + 関数 + 定数 の集まり • みんなよく types.ts
とか userUtil.ts とか constants.ts とか作るけど、あれを1ファイルに纏 めたもの • action と selector、あるいはコンポーネントからも 呼べる共通関数とかおける • 別の機会にこれだけで話したい …かも 37 model.ts って何や
38
まとめ 39
• Redux は ただのクライアントサイド CQRS だよ • C と Q
をドメインごとに切ると捗るよ(けど純粋な ducks パターンはきついよ ) • ドメインモデルを純粋な形で持つようにすると良いよ 40 まとめ
Redux as CQRS あるいはドメイン駆動 Redux pixiv Inc. f_subal 2018/12/07