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.7k
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
現役スタートアップCTOが解説する、ソフトウェア開発という仕事の理論・実践・キャリア
fujimura
0
68
庭と負債
fujimura
4
2.4k
AIの時代で我々はどのようにコードを書くのか
fujimura
4
1k
SaaSを作るという仕事について
fujimura
13
6.4k
一文字エイリアスのすすめ
fujimura
0
450
現役CTOが語る!RubyKaigiの楽しみ方
fujimura
0
1.3k
いかにして文系新卒エンジニアが「大きな問い」を大事にするCTOになったのか
fujimura
2
750
Kaigi on Rails 2022 - 既存Railsアプリ攻略法 CTOが見ること・やること・考えること
fujimura
14
5.3k
入門 名前
fujimura
25
14k
Other Decks in Programming
See All in Programming
One Enishi After Another
snoozer05
PRO
0
130
Developer Joy - The New Paradigm
hollycummins
1
230
Flutterで分数(Fraction)を表示する方法
koukimiura
0
140
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
3
920
オープンソースソフトウェアへの解像度🔬
utam0k
16
3.1k
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
250
CSC305 Lecture 08
javiergs
PRO
0
250
CSC509 Lecture 04
javiergs
PRO
0
300
Google Opalで使える37のライブラリ
mickey_kubo
2
110
CSC305 Lecture 06
javiergs
PRO
0
250
AI Agent 時代的開發者生存指南
eddie
3
2k
技術的負債の正体を知って向き合う
irof
0
200
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
34
2.3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
115
20k
Building Applications with DynamoDB
mza
96
6.7k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
30
2.9k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Documentation Writing (for coders)
carmenintech
75
5.1k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.2k
Agile that works and the tools we love
rasmusluckow
331
21k
Building an army of robots
kneath
306
46k
Thoughts on Productivity
jonyablonski
70
4.9k
Facilitating Awesome Meetings
lara
56
6.6k
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との違いは?わからん!誰か教えてくれ!