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
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.8k
カリー化はナンの役に立つのか
fsubal
27
9.2k
Other Decks in Programming
See All in Programming
10 Tips of AWS ~Gen AI on AWS~
licux
5
540
Kingdom of the Machine
yui_knk
2
1.4k
Road to RubyKaigi: Play Hard(ware)
makicamel
1
550
t *testing.T は どこからやってくるの?
otakakot
1
900
PHPer、Cloudflare に引っ越す
suguruooki
1
140
Building on Bluesky's AT Protocol with Ruby
mackuba
0
100
Structured Concurrency, Scoped Values and Joiners in the JDK 25 26 27
josepaumard
1
140
Claude CodeでETLジョブ実行テストを自動化してみた
yoshikikasama
0
1.1k
過去のレビュー知見をSkillsで資産化した話
pkshadeck
PRO
1
1.4k
ハーネスエンジニアリングにどう向き合うか 〜ルールファイルを超えて開発プロセスを設計する〜 / How to approach harness engineering
rkaga
28
19k
運転動画を検索可能にする〜Cosmos-Embed1とDatabricks Vector Searchで〜/cosmos-embed1-databricks-vector-search
studio_graph
1
650
2026年のソフトウェア開発を考える(2026/05版) / Software Engineering Scrum Fest Niigata 2026 Edition
twada
PRO
21
11k
Featured
See All Featured
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
370
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
320
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.1k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
180
How to train your dragon (web standard)
notwaldorf
97
6.6k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.7k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.5k
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