狠狠撸

狠狠撸Share a Scribd company logo
状態管理の
コレオグラフィ
April 24, 2018
@Takepepe
吉井 健文
@Takepepe
DeNA
デザイン本部
デザイン戦略部
エンジニアリングG
先日 DeNA TechCon2018
という場で、状態管理関連の
発表をさせて頂きました。
サービス開発における フロントエンド?ドメイン駆动设计の実践
今日はその内容の一部を抜粋、
噛み砕きLTします。
横断的関心事を含む
状態管理の設計について
注記:
Redux 想定で解説しますが、
Redux に限った話ではないです。
例題:
3 tree から得られる値で
POST制御せよ。
type TodoItem = {
value: string | null,
createdAt: Date
}
type Store = {
todos: {
items: TodoItem[],
inputValue: string | null,
},
user: {
id: number,
name: string,
registered: boolean
},
gui: {
modal: {
visible: boolean,
componentName: string
}
}
}
// 送信可能とする状態
const isPostEnabled =
todos.inputValue !== null &&
todos.inputValue !== '' &&
user.registered === true &&
gui.modal.visible === false
辞めたいパターン
3 tree を mapStateToProps
connect で云々...
3 tree を getState
thunk で云々...
_人人人人人人人_
> 状態の散在 <
 ̄Y^Y^Y^Y^Y^Y ̄
そもそも「isPostEnabled」が
管理されておらず、
責務が宙ぶらりん。
まず、参照されるものとして
これを管理する必要がある。
下流 tree で「isPostEnabled」
を保持する。
type TodoItem = {
value: string | null,
createdAt: Date
}
type Store = {
todos: {
items: TodoItem[],
inputValue: string | null,
},
user: {
id: number,
name: string,
registered: boolean
},
gui: {
modal: {
visible: boolean,
componentName: string
}
},
app: { // 下流 tree
isPostEnabled: boolean // 爆誕
}
}
// 送信可能とする状態
const isPostEnabled =
todos.inputValue !== null &&
todos.inputValue !== '' &&
user.registered === true &&
gui.modal.visible === false
书き込みは…
関係者各位の Reducer で
変更に応じて… ????????
combineReducers してて
他所の State 参照出来ないので、
npm i redux-thunk しても?
combineReducers してて
他所の State 参照出来ないので、
npm i redux-thunk しても?
理由は後述
ロジック?書き込みは どこで?
コレオグラフィで!
コレオグラフィ?
コレオグラフィー
コレオグラフィー(英: Choreography)
?振付師(ダンス?バレエや舞踊などで使われる踊りの振り付けを行う職業)
?人文字
※ wikipedia 调べ
マイクロサービス
アーキテクチャ
FYI: 4.5 オーケストレーションとコレオグラフィ
pub/sub による モデリング。
関係者各位の変化を
サービス層で購読する。
todos user gui
app
app service (logic)
購読 購読 購読
app
app service (logic)
todos user gui
購読 購読 購読
foo
購読
bar
購読
A service
... ... ...... ...
B service
... ... ...... ...
app
app service (logic)
BA
_人人人人人人人人人人人人_
> 要は dispatch コンボ <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
購読イベントが発生した時、
関与する状態をサービス層で
全く新しい値へと変換。
影響は tree 内に閉ざされ、
tree が保持する値として
自然なものに。
必要なもの
redux-observable
redux-saga
async / await ( + subscriber )
の、いずれか。
慣れていればコード概要は
大体想像つくはず…!
?自動で振る舞ってくれる
?2次3次購読も無限
?設計パターンなので
 ライブラリ不問
※ 特定のイベントが購読できる下地は必要
※ thunk 単体だと购読できないので厳しい
?tree毎のテストが楽(疎)
?疎なのでスケール耐性高め
※ e2eテストは必要
?Props 削減 で幸せ
?View のテストも当然楽に
イベント駆动の恩恵は大きい
Redux 使ってないって?
変化を購読できれば不問。
(MobX.reaction とか)
const todosStore = new TodosStore()
const userStore = new UserStore()
const guiStore = new GUIStore()
const appStore = new AppStore(todosStore, userStore, guiStore)
const fooStore = new fooStore(appStore)
const barStore = new barStore(appStore)
MobX にありがちな 共有カーネルパターンからの脱却
const todosStore = new TodosStore()
const userStore = new UserStore()
const guiStore = new GUIStore()
const appStore = new AppStore()
const fooStore = new fooStore()
const barStore = new barStore()
runAppService(appStore, todosStore, userStore, guiStore)
runFooService(fooStore, appStore)
runBarService(barStore, appStore)
Store 各位の UnitTest が単純 = Store が純粋に
例の如く、银の弾丸ではない。
?他所の雑な dispatch は NG※
?参照関係の doc化検討 (UML?)
?サービス層寄りの貧血症
※ 属する tree の変更のみを許可する運用カバー
詳細は懇親会または
過去の発表資料
Qiita@Takepepe で。

More Related Content

状态管理のコレオグラフィ