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
Backbone.Model に 型をつけて剥がす - Typing to destroy B...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
fsubal
September 20, 2019
Programming
1.2k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Backbone.Model に 型をつけて剥がす - Typing to destroy Backbone.Model
2019年9月20日の社内勉強会の資料です
fsubal
September 20, 2019
More Decks by fsubal
See All by fsubal
負債になりにくいCSSをデザイナとつくるには?
fsubal
11
3.6k
Webデザインと フロントエンド技術🔰勉強会
fsubal
2
350
Tailwind CSSを本気でカスタマイズする方法
fsubal
17
7.9k
デザインシステムで Tailwind CSSとCSS in JSに分散投資をしたら良かった話
fsubal
20
7.5k
『Tailwind CSS実践入門』 出版記念基調講演
fsubal
9
5.4k
Sprockets CSSもやめる なぜ / Why stop using Sprockets for CSS too
fsubal
3
1.7k
The Majestic MPA
fsubal
8
3.4k
SVG + React でつくる レイヤーの自由変形 / Layer Transformation with React + SVG
fsubal
1
9.9k
カリー化はナンの役に立つのか
fsubal
27
9.3k
Other Decks in Programming
See All in Programming
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
110
Webフレームワークの ベンチマークについて
yusukebe
0
150
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
330
さぁV100、メモリをお食べ・・・
nilpe
0
130
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
520
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
510
OSもどきOS
arkw
0
470
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
110
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
260
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
100
Oxcを導入して開発体験が向上した話
yug1224
4
300
Copilot CLI の継戦能力を高める コンテキスト管理
nozomutu
1
1.2k
Featured
See All Featured
A better future with KSS
kneath
240
18k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Designing for Performance
lara
611
70k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
380
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.7k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
1.6k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
770
Transcript
Backbone.Model に 型をつけて剥がす Sub title pixiv Inc. subal 2019.9.20
2 誰 • pixivFACTORY • TypeScript と SVG と React、時々
Rails • 型芸、SVG芸、hooks 芸の話ができます subal
3 型芸で負債を倒す話
4
5 pixivFACTORY BOOKS
6 pixivFACTORY BOOKS • 同人誌作成機能。グッズと並ぶ、 pixivFACTORY の二大柱 • 同人誌プラン検索/入稿画面が React
+ Redux • ただし、2015年に設計された React + Redux アプリケーション • アップデートの結果表面的な記法は新しくなっている(Babel, ES6 Classes) ◦ しかし本質的な設計は…? ◦ それに、グッズ側は TypeScript で書くのが当たり前に変わっている
7 設計上の課題 • mixin の名残がある ◦ React.createClass は流石にやめているが、constructor で this
を lodash/extend している • Redux の store に Backbone.Model のインスタンスが入っている ◦ Immutable.js ならまだ分かるけど、Backbone.Model です ▪ まぁ私は Immutable.js も嫌いなのであったらあったで剥がしますけど • 他にもいろいろあるが、とりあえず ↑ を何とかする。まずはそれから
8 とりあえずのゴール • reducer で Backbone.Model を作らない • store に
Backbone.Model を持たない • コンポーネントに Backbone.Model を持ち込ませない • TS化し、型のついたただの json にする
9 現状
10
11 セッターで型をキャストする 仕組み ( ActiveModel::Attributes みたいなやつ ) モデルのデフォルト値
12 プロパティとは別にメソッドっぽいのが生えるケースがある
13 たとえばここが、number と勝手に推論される状況を作りたい
14 おっとこんなところにデ フォルト値が
15 extend() の引数内の defaults から、 返り値の型を推論する
16
17
18
19
20 1個ずつ解説します みたいな型定義で倒せるのですが…
21 Model のインスタンスの型を考える • Backbone.Model のプロパティは(厳密には違うけど)だいたい keyof defaults • 仮に、extend()
の引数を option とするとき… ◦ defaults の型は typeof option['defaults'] ◦ これを仮に P と置く ◦ すると、インスタンスの型はそれをジェネリクスに受け取る TypedModelInstance<P> と置くことができる ◦ その型は get<K extends keyof P>(key: K): K[P] というメソッドを持つはず
22 これにより、model.get('hoge') で hoge が defaults に書かれてないキーならば、 コンパイルエラーになる
23 Model のインスタンスの型を考える 2 • Backbone.Model の set は特殊で、以下の二つの記法が許容される (うげぇ…)
◦ model.set('page_size', 12) ◦ model.set({ page_size: 12 }) • TypeScript にはメソッドの型をオーバーロードする仕組みがあるので、両対応で書くことは 可能
24
25 Model のインスタンスの型を考える 3 • toJSON の型は、少なくとも推論されたすべてのプロパティを含む型を返すはず ◦ さっきの言葉で言えば、とりあえず P
あるいは P を継承した型であるはず ◦ 実は、Backbone.Model はプロパティとは別に getters という仕組みがあり、本当は それらも toJSON に含まれる ▪ が、一旦無視してすすめる
26
27 クラスの型を考える • Backbone.Model.extend() は「クラスを作る関数」 ◦ なので、返り値がクラス(あるいは newable なオブジェクト)と考える必要がある ◦
TypeScript は、任意の型に対して、それを new で呼んだときの返り値を定義するこ とができる ◦ Book クラスは ReturnType<typeof Backbone.Model.extend({ ... })> のような方法 で推論されるし、インスタンスの型は new の型定義から推論される
28
29 ここまでやると、 コンパイラは Book という「クラス」がどうい う構造かを理解し始める
30 Reducer から剥がしていく • model クラスをやめてただの JSON にしたあとで、返り値の型が変わらないことを保証した い ◦
Jest のスナップショットテストを使う • 剥がした後に残る JSON の型を、interface State として書いておきたい ◦ まぁ infer を使って出てきた結果をコピーするとか … ◦ 推論結果を参考に頑張って書くしかない( optional なキーとか推論しきれてない箇所 はあるので )
31 テストのコツ • もともと、backbone.model を生で使ったテストは書かれていたが、これは使わないことに した ◦ 剥がした後も有効であり続けるテストでないと意味がない ◦ toJSON
した結果をスナップショットテストして、 ▪ それが剥がした後も通る ▪ あるいは、落ちるけど差分が意図したものであることを検証したい
32
33
34 • props にまで Backbone のモデルインスタンスが渡っている箇所がある • コンポーネントの外に追い出したい • reducer
にしか現れない状況を作った上で、reducer を倒すみたいな感じにしたい コンポーネントに露出している model
35 toJSON するだけの selector を書く
36 useSelector を使って末端から型付け
37 • 一部の画面 / model だけしか置き換えてないのでまだまだ • 終わったらあの型定義はちゃんと捨てる ◦ 登りきった後は梯子を投げ捨てなければならない
今後
38 戦いはまだまだこれから…!
39 • とりあえず、全部ではないが Backbone.Model を剥がしながら型付け・モダン化が進ん でいる • TypeScript の型システムは無限に便利なのであーいうものでも型がつけられてしまう •
スナップショットテストはライブラリを消すときの強い味方 • useSelector は最高 まとめ
40 • 一つには優先度の問題 ◦ 「他の改修を一切留めてやるべきか」といういつもの話 • もう一つは、実はこっちのほうが事故らないかもという考え ◦ 古くて型のないコードを「読解して」書き直すのと、古いコードの実装から型を「 推論さ
せて」安全にするアプローチ ▪ 前者(書き直し)のほうが良いと自信を持って言えたか?うーん … ▪ 真面目に読むの嫌なのでコンパイラにやらせるは一つの方法としてある Q. Why not フルスクラッチ?
Backbone.Model に 型をつけて剥がす Sub title pixiv Inc. subal 2019.9.20