Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
状態と共に暮らす:ステートフルへの挑戦
Search
ypresto
April 23, 2025
Programming
3
1.3k
状態と共に暮らす:ステートフルへの挑戦
ypresto
April 23, 2025
Tweet
Share
More Decks by ypresto
See All by ypresto
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
3.4k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
2.5k
Next.js のページ遷移を全力で止める
ypresto
15
8k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
21
7.7k
アクセシビリティとE2Eテスト
ypresto
0
100
VS Codeのプロセスモデルとデバッグ方法 - パフォーマンスと安定性を支えるアーキテクチャ
ypresto
1
480
TypeScriptの型定義をPRする技術
ypresto
1
740
Other Decks in Programming
See All in Programming
Designing Your Organization's Test Pyramid ( #scrumniigata )
teyamagu
PRO
5
1.6k
ASP.NETアプリケーションのモダナイゼーションについて
tomokusaba
0
270
Browser and UI #2 HTML/ARIA
ken7253
2
180
読書シェア会 vol.4 『ダイナミックリチーミング 第2版』
kotaro666
0
120
データベースの技術選定を突き詰める ~複数事例から考える最適なデータベースの選び方~
nnaka2992
3
2.2k
Golangci-lint v2爆誕: 君たちはどうすべきか
logica0419
1
280
「MCPを使ってる人」が より詳しくなるための解説
yamaguchidesu
0
250
ウォンテッドリーの「ココロオドル」モバイル開発 / Wantedly's "kokoro odoru" mobile development
kubode
2
650
generative-ai-use-cases(GenU)の推しポイント ~2025年4月版~
hideg
1
420
AI時代のリアーキテクチャ戦略 / Re-architecture Strategy in the AI Era
dachi023
0
130
Flutterでllama.cppをつかってローカルLLMを試してみた
sakuraidayo
0
150
VibeCoding時代のエンジニアリング
daisuketakeda
0
240
Featured
See All Featured
A Tale of Four Properties
chriscoyier
159
23k
KATA
mclloyd
29
14k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.4k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
179
53k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.7k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
Building Applications with DynamoDB
mza
94
6.4k
GraphQLとの向き合い方2022年版
quramy
46
14k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Transcript
© LayerX Inc. 状態と共に暮らす:ステートフルへの挑戦 ypresto @ LayerX Frontend Night -
Exploring State (2025/04/20)
© LayerX Inc. 2 ⾃⼰紹介 • LayerX バクラク事業部 ◦ 債務管理チーム
(請求書受取) ◦ ソフトウェアエンジニア ◦ 経理の⽅が利⽤するプロダクトの開発 • 趣味は主に写真とスプラ、⼦どもとおでかけ ypresto (プレスト)
© LayerX Inc. 3 フロントエンド=ステートフル フロントエンドとはステートフル、だからこそ難しい バックエンド ステートレスに設計し、状態は外部に任せる フロントエンド DOM、フォーム、非同期処理など、ステートフルが本体
© LayerX Inc. 4 フロントエンド=ステートフル • ロジックと状態が容易に結合、分解が困難 • 順番‧タイミング問題:setTimeout() •
単体テストが困難、結合テストの肥⼤化 • コンポーネント内がガチャガチャする...! useEffect()祭り!!! 複雑!!! 状態が中⼼に来ることで‧‧
None
© LayerX Inc. 6 状態という複雑さと共に暮らす • すべてのアプリケーションには、 それ以上減らせない複雑性がある • 本質的な複雑さは減らせず、移動しかできない
• 例:UIを簡単にすると、システムのロジックが複雑になる テスラーの複雑性保存則 https://www.nomodes.com/larry-tesler-consulting/complexity-law https://scrapbox.io/koushisa/複雑性保存の法則
Apollo 11 (1969) Crew Dragon Endeavour (2020) 参考: https://blog.btrax.com/jp/space-x-touchscreen https://airandspace.si.edu/collection-media/NASM-NASM2013-02663
https://www.youtube.com/live/H-l6f4wcv2I?feature=shared&t=21153
© LayerX Inc. 8 状態という複雑さと共に暮らす • ユーザー=システム要件を減らす? • システムの中で、 •
本質的でない複雑さが少なくなる場所 • 品質担保が容易な場所 • に移動する! 本質的な複雑さを「どこに移動するか」が⼤事
© LayerX Inc. 9 状態という複雑さと共に暮らす • 状態に対する本質的な操作は2種類! • 状態という複雑さから引き剥がす ステートフルの複雑性
状態 計算された 状態 (値) 変換ロジック イベントハンドラ リアクティブな接続 ⼿続き的な呼出‧変更 外界 (DOMなど) 状態の 参照‧変更 1. 状態から別の状態を計算 2. イベントに応じて 状態を変更
1. 状態から別の状態を計算する
© LayerX Inc. 11 リアクティブとDerived State 状態から状態を計算:Derived State
12 © LayerX Inc. リアクティブとDerived State:本質的でない複雑さの例 状態が変わるイベントハンドラで、 漏れずに呼ばないといけない
© LayerX Inc. 13 リアクティブとDerived State 実際の業務システムで同じこと⾔われたら‧‧
© LayerX Inc. 14 リアクティブとDerived State • イベントハンドラの網羅性やタイミング =本質的でない複雑さを意識しなくて済む •
複雑な関係性は、純粋関数に移動してテストする • 外界の複雑さは、(引数扱いの) hooksに移動する • 状態の組みたてができるのがリアクティブ リアクティブ:状態間の関係を普通のコードで表現 参考: https://zenn.dev/layerx/articles/22dd45dc69a57c
© LayerX Inc. 16 リアクティブとDerived State • 「状態間の関係」の表現に、余計なイベントハンドラが挟まる ◦ 更新漏れやタイミングの⼼配、テスタビリティ...
• よって、useState() を不必要に使⽤しない ◦ または (状態への参照が制限された) hooksに追い出す • 余談:フォームのリセットは、Dialogのライフサイクルに委ねたい useEffect() + 常にsetState() は、99%アンチパターン 状態1 状態2 状態1 useEffect(...) 別の状態変更 状態変更
Reactivity = Derived State with Confidence. リアクティブで 状態間の関係を簡潔‧安全に定義する
© LayerX Inc. 18 状態という複雑さと共に暮らす • 状態に対する本質的な操作は2種類! • 状態という複雑さから引き剥がす ステートフルの複雑性
状態 計算された 状態 (値) 変換ロジック イベントハンドラ リアクティブな接続 ⼿続き的な呼出‧変更 外界 (DOMなど) 状態の 参照‧変更 1. 状態から別の状態を計算 2. イベントに応じて 状態を変更
2. イベントに応じて状態を変更する
onChange={e => setState(e.target.value)}
制作‧著作:LayerX 終
© LayerX Inc. 22 Event const onChangeUserId = (userId) =>
{ setUserId(userId) setGroupId(users.find(u => u.id = userId)?.groups[0]?.id) # グループを初期値に設定する // 他のフィールドたちの書き換えもここに } 「便利」を実現するほど、複雑化するイベントハンドラ テスタビリティを諦めない..!
© LayerX Inc. 23 • みんな⼤好き (?) Reducer • nextState
= f(state, action) const reducer = action => { switch (action.payload.type) { case "setUser": return { userId: action.payload.userId, groupId: null } ... } • 「状態の変更」に純粋関数を強制するパターン ◦ 複数の (計算されない) 状態を同時に変えたい‧複雑なときに使いましょう イベントハンドラを純粋関数で表現する
24 © LayerX Inc. わたしたちのアプリケーションにて。 「旅費交通費」に合わせて 税区分を⾃動設定したい! 「旅費交通費」の デフォルトの税区分設定 外貨のときの
「不課税」税区分設定 適格の経過措置税区分の 対応関係設定 借⽅の勘定科⽬ 請求書の通貨 適格請求書? 借⽅の税区分 get get get set set get しかも税区分変わったら、 ほかも変えたい!!
Death. ⼿続き的な 状態操作祭り
© LayerX Inc. 26 Event • フォームへの「変更内容」を計算して返す純粋関数 ◦ transform() •
現在の状態や、1つまえのtransform()が返したdiffを引数で受ける ◦ apply(transform(transform(transform({ 借⽅勘定科⽬: 新しい値 }))) • 設定は、transformを作るときに引数として受ける • 分解でき、テストでき、いくつでも組み合わせられる • ASTの変換 (transformer) や、Goのhttp Middewareから着想 • reducerのような既存パターンに囚われず、アプリケーションの特性にあった設計を! ⽬的は純粋関数で表現することです! どう解決したか
Design Functional parts for your application. アプリケーションにあわせて、 ⼩さな純粋関数を組み合わせられるような パターンを発明する
© LayerX Inc. 28 • リアクティブを活⽤し、状態間の関係を意識して、分解して組み⽴てる • アプリケーションにあった状態変更ロジックの設計をし、⼿続き的な変更操作を減らす • 純粋関数に切り出せば、「複雑な部分」がテスタブルになる
• 余分な複雑さを減らし、複雑さを移動して、状態と上⼿に付き合っていきましょう..! まとめ
© LayerX Inc. 29 フロントエンド=ステートフル • 純粋関数で書かれた部分はテストしやすい https://www.destroyallsoftware.com/talks/boundaries • 外界に結合しない部分をぶ厚く中⼼に。そうでない殻の部分を薄く外に。
Functional Core, Imperative Shell