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
2.7k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
状態と共に暮らす:ステートフルへの挑戦
ypresto
April 23, 2025
More Decks by ypresto
See All by ypresto
TypeScriptはどのようにどこまで推論できるのか ─ とにかく as は禁止で
ypresto
3
970
バクラク最古参プロダクトで重ねた技術投資を振り返る
ypresto
0
250
Why React!?? Next.jsそしてReactを改めてイチから選ぶ
ypresto
12
5.2k
ts-morph実践:型を利用するcodemodのテクニック
ypresto
1
1.2k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
4.4k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
4.8k
Next.js のページ遷移を全力で止める
ypresto
15
12k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
24
9.7k
アクセシビリティとE2Eテスト
ypresto
0
180
Other Decks in Programming
See All in Programming
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
470
Modding RubyKaigi for Myself
yui_knk
0
900
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
260
Oxcを導入して開発体験が向上した話
yug1224
4
290
GitHub Copilot CLIのいいところ
htkym
2
1.3k
ふつうのFeature Flag実践入門
irof
7
3.6k
運用エージェントは "作る" から "育てる" へ - 記憶と自己進化の3層設計パターン / self-evolving-agents-three-layer-agent-design
gawa
12
3.5k
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
180
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.3k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
1.6k
AIチームを指揮するOSS「TAKT」活用術 / How to Use “TAKT,” an OSS Tool for Orchestrating AI Teams
nrslib
6
840
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.8k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
250
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
820
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
55k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
240
Building Adaptive Systems
keathley
44
3k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
600
The Mindset for Success: Future Career Progression
greggifford
PRO
0
350
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
530
Statistics for Hackers
jakevdp
799
230k
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