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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Fujimura Daisuke
December 14, 2019
Programming
1.8k
0
Share
SimpleDelegator活用のご提案
平成Ruby会議 01
https://github.com/fujimura/heisei_ruby_kaigi_01_simple_delegator
Fujimura Daisuke
December 14, 2019
More Decks by Fujimura Daisuke
See All by Fujimura Daisuke
現役スタートアップCTOが解説する、ソフトウェア開発という仕事の理論・実践・キャリア
fujimura
0
140
庭と負債
fujimura
4
2.6k
AIの時代で我々はどのようにコードを書くのか
fujimura
4
1.1k
SaaSを作るという仕事について
fujimura
13
6.5k
一文字エイリアスのすすめ
fujimura
0
520
現役CTOが語る!RubyKaigiの楽しみ方
fujimura
0
1.4k
いかにして文系新卒エンジニアが「大きな問い」を大事にするCTOになったのか
fujimura
2
810
Kaigi on Rails 2022 - 既存Railsアプリ攻略法 CTOが見ること・やること・考えること
fujimura
14
5.6k
入門 名前
fujimura
25
14k
Other Decks in Programming
See All in Programming
アクセシビリティ試験の"その後"を仕組み化する
yuuumiravy
1
200
実践ハーネスエンジニアリング:ステアリングループを実例から読み解く / Practical Harness Engineering: Understanding Steering Loops Through Real-World Examples
nrslib
5
4.9k
決定論 vs 確率論:Gemini 3 FlashとTF-IDFを組み合わせた「法規判定エンジン」の構築
shukob
0
160
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
360
Spec Driven Development | AI Summit Vilnius
danielsogl
PRO
1
150
運転動画を検索可能にする〜Cosmos-Embed1とDatabricks Vector Searchで〜/cosmos-embed1-databricks-vector-search
studio_graph
1
680
リセットCSSを1行消したらアクセシビリティが向上した話
pvcresin
4
500
Lightning-Fast Method Calls with Ruby 4.1 ZJIT / RubyKaigi 2026
k0kubun
3
2.7k
エラー処理の温故知新 / history of error handling technic
ryotanakaya
7
1.9k
空間オーディオの活用
objectiveaudio
0
150
Agent Skills を社内で育てる仕組み作り
jackchuka
1
1.8k
GitHubCopilotCLIをはじめよう.pdf
htkym
0
330
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.9k
How to Ace a Technical Interview
jacobian
281
24k
The Language of Interfaces
destraynor
162
26k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Code Review Best Practice
trishagee
74
20k
Music & Morning Musume
bryan
47
7.2k
Everyday Curiosity
cassininazir
0
200
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
70
39k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.8k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
1.9k
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との違いは?わからん!誰か教えてくれ!