Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
状態と共に暮らす:ステートフルへの挑戦
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ypresto
April 23, 2025
Programming
2.9k
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
1.2k
バクラク最古参プロダクトで重ねた技術投資を振り返る
ypresto
0
300
Why React!?? Next.jsそしてReactを改めてイチから選ぶ
ypresto
12
5.2k
ts-morph実践:型を利用するcodemodのテクニック
ypresto
1
1.3k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
4.5k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
4.9k
Next.js のページ遷移を全力で止める
ypresto
15
13k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
24
9.9k
アクセシビリティとE2Eテスト
ypresto
0
200
Other Decks in Programming
See All in Programming
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
570
AHC070解法紹介
eijirou
0
150
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
440
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
530
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
590
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
390
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
330
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
120
Agents on Rails - Rails at Scale 2026
irinanazarova
0
320
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
290
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
120
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
400
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.2k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Skip the Path - Find Your Career Trail
mkilby
1
240
The SEO Collaboration Effect
kristinabergwall1
1
580
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Building Flexible Design Systems
yeseniaperezcruz
330
41k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
450
A designer walks into a library…
pauljervisheath
211
25k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
490
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
Code Reviewing Like a Champion
maltzj
528
40k
Optimising Largest Contentful Paint
csswizardry
37
4k
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