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
SimpleDelegator活用のご提案
Search
Fujimura Daisuke
December 14, 2019
Programming
0
1.6k
SimpleDelegator活用のご提案
平成Ruby会議 01
https://github.com/fujimura/heisei_ruby_kaigi_01_simple_delegator
Fujimura Daisuke
December 14, 2019
Tweet
Share
More Decks by Fujimura Daisuke
See All by Fujimura Daisuke
庭と負債
fujimura
4
2.1k
AIの時代で我々はどのようにコードを書くのか
fujimura
4
950
SaaSを作るという仕事について
fujimura
13
6.1k
一文字エイリアスのすすめ
fujimura
0
410
現役CTOが語る!RubyKaigiの楽しみ方
fujimura
0
1.2k
いかにして文系新卒エンジニアが「大きな問い」を大事にするCTOになったのか
fujimura
2
720
Kaigi on Rails 2022 - 既存Railsアプリ攻略法 CTOが見ること・やること・考えること
fujimura
14
4.9k
入門 名前
fujimura
25
14k
それPostgreSQLでできるよ @ Rails Developer Meetup 2018 Day 1
fujimura
10
3.9k
Other Decks in Programming
See All in Programming
VitestのIn-Source Testingが便利
taro28
6
2.1k
Bedrock×MCPで社内ブログ執筆文化を育てたい!
har1101
6
1k
地域ITコミュニティの活性化とAWSに移行してみた話
yuukis
0
240
Building Scalable Mobile Projects: Fast Builds, High Reusability and Clear Ownership
cyrilmottier
2
290
Memory API : Patterns, Performance et Cas d'Utilisation
josepaumard
0
140
ウォンテッドリーの「ココロオドル」モバイル開発 / Wantedly's "kokoro odoru" mobile development
kubode
1
140
海外のアプリで見かけたかっこいいTransitionを真似てみる
shogotakasaki
1
170
Dissecting and Reconstructing Ruby Syntactic Structures
ydah
1
740
Lambda(Python)の リファクタリングが好きなんです
komakichi
3
200
サービスレベルを管理してアジャイルを加速しよう!! / slm-accelerate-agility
tomoyakitaura
1
180
Golangci-lint v2爆誕: 君たちはどうすべきか
logica0419
1
130
Thank you <💅>, What's the Next?
ahoxa
1
490
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
StorybookのUI Testing Handbookを読んだ
zakiyama
29
5.6k
Optimising Largest Contentful Paint
csswizardry
36
3.2k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
178
53k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
119
51k
Unsuck your backbone
ammeep
670
57k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
13
1.4k
The Invisible Side of Design
smashingmag
299
50k
GitHub's CSS Performance
jonrohan
1030
460k
Making Projects Easy
brettharned
116
6.1k
How GitHub (no longer) Works
holman
314
140k
Transcript
SimpleDelegator 活⽤のご提案 平成Ruby会議 01 Daisuke Fujimura 2019-12-14
⾃⼰紹介 藤村⼤介 https://twitter.com/ffu_ https://github.com/fujimura スタートアップ数社 ⇨ マチマチCTO ⇨ フリーランス Ruby歴11年
現在は数社で技術顧問のお仕事 最近はPythonとYAMLを書いている WEB+DB PRESS Vol.110 名前付け⼤全を書いた
今⽇のお話 SimpleDelegatorは便利なのにあまり使われていない印象があるので宣伝したい!
SimpleDelegator とは オブジェクト指向でいうところの「委譲」ができるライブラリ Ruby標準ライブラリ ‘delegate’ に含まれる
基本的な使⽤例 出典: https://ruby-doc.org/stdlib-2.6.5/libdoc/delegate/rdoc/SimpleDelegator.html class User def born_on Date.new(1989, 9, 10)
end end class UserDecorator < SimpleDelegator def birth_year born_on.year end end decorated_user = UserDecorator.new(User.new) decorated_user.birth_year #=> 1989 decorated_user.__getobj__ #=> #<User: ...>
何が便利なの 局所的な振る舞いを後から追加することができる 部分的にしか使わない実装で元のクラスを膨らませないで済む デコレーターを簡単に書ける その他、⼩技がいくつか
具体例
例:インターフェイスを揃えたい 既存のオブジェクトのインターフェイスが期待しているものと異なる APIのレスポンスがオブジェクトで、モデルとインターフェイスが違うケース 簡単にデコレーターを書けました class Entry < SimpleDelegator def title
subject end end entries = api.get('/entries/').map { |r| Entry.new(r) } puts entries.first.title # => `subject` の値
例:ソート順を変えたい 特定の箇所で既存のオブジェクトのソート順を変えたい デコレーターはインターフェイスだけでなく挙動を拡張することもできます class UserSortedByBirthday < SimpleDelegator def <=>(other) birthday
> other.birthday end end users = User.limit(10).map {|u| UserSortedByBirthday.new(u) } users.sort #=> 誕⽣⽇で並べ替えられる
例:アクセサを⾜したい 元のクラスにアクセサは定義したくない クラスを読み下していって「これのアクセサは⼀体…?」となりがち 後にそのアクセサが悪⽤されて副作⽤パズルが発⽣したりするけど、これなら防げる 局所化は最⾼ class UserWithToken < SimpleDelegator attr_accessor
:token end token = generate_token users = User.limit(10).map {|user| u = UserWithTimestamp.new(user) u.token = token u } users.first.token #=> ⽣成したトークン
例:現在のユーザーによってオブジェクトの値を 変えたい オブジェクトの振る舞いを他のオブジェクトによって変えたい post に状態をもたせる実装よりも影響範囲が少ない Post#comments_for(user) という実装も考えられるけど、パーソナライズする 箇所が増えるといちいち渡すのが⾯倒 局所化は最⾼ class
PersonalizedPost < SimpleDelegator def initialize(post, user) @user = user __setobj__(post) end def comments __getobj__.comments.filter {|c| !c.author.blocked_by?(@user) } end end posts = Post.first(10).map {|p| PersonalizedPost.new(p, current_user) } posts.first.comments # ブロックされたユーザーのコメントは現れない
例:クエリオブジェクト作るの⾯倒 これは完全に⼩技 DailyNewCommentQuery.new(...).result というようなクエリオブジェクトあ るある実装より簡潔 class DailyNewComment < SimpleDelegator def
initialize(user, start_at) comments = user.visible_comments.where( 'created_at >= :from AND created_at < :to', from: start_at, to: 24.hours.since(start_at) ) __setobj__(comments) end end comments = DailyNewComment.new(user, start_at)
まとめ SimpleDelegatorは便利 局所化進めていきましょう
補⾜ 遅いってマジ? DelegateClassとの違いは?わからん!誰か教えてくれ!