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
Refactor Like A Boss: A Few Techniques for Ever...
Search
PromptWorks
February 21, 2014
Programming
2.3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Refactor Like A Boss: A Few Techniques for Everyday Ruby Hacking
Presented by Greg Sterndale.
http://promptworks.com
PromptWorks
February 21, 2014
More Decks by PromptWorks
See All by PromptWorks
PromptWorks Talk Tuesdays: Yvonne Chen 1/24/17 "Agile-Retros"
promptworks
0
110
PromptWorks Talk Tuesdays: Ray Zane 1/17/17 "Elixir Is Cool"
promptworks
0
110
PromptWorks Talk Tuesdays: Ray Zane 9/13/16 "Elixir Processes"
promptworks
0
3.5k
PromptWorks Talk Tuesdays: Dustin Ingram 8/30/16 "What is an ADR?"
promptworks
1
180
PromptWorks Talk Tuesdays: Dustin Ingram 8/23/16 "Detecting Asteroids with Neural Networks in TensorFlow"
promptworks
1
150
Getting to know Arel: Active Record's nerdy little brother
promptworks
1
130
Writing DSLs with Parslet - NYC.rb
promptworks
0
2.5k
Straight Up Rspec: A Neat Ruby BDD Tool
promptworks
0
60
Double Trouble: Clarity on Test Doubles
promptworks
0
2.4k
Other Decks in Programming
See All in Programming
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.5k
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
200
技術的負債解消で開発者の未来を開く- AIの力でコード刷新
kmd2kmd
0
120
AI駆動開発を妨げる技術的負債の解消アプローチ / ai-refactoring-approach
minodriven
15
7.3k
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
190
act1-costs.pdf
sumedhbala
0
120
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
610
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
13
6.3k
AI 輔助遺留系統現代化的經驗分享
jame2408
1
1k
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
410
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
750
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
170
Featured
See All Featured
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
150
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
Agile that works and the tools we love
rasmusluckow
331
22k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
The agentic SEO stack - context over prompts
schlessera
0
830
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
Practical Orchestrator
shlominoach
191
11k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Visualization
eitanlees
152
17k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.5k
Transcript
Refactor Like A Boss a few techniques for everyday Ruby
hacking
Refactoring The process of changing code without modifying behavior
Ungoals of refactoring • Brevity for the sake of brevity
• To demonstrate mastery of Ruby or design patterns
Goals of refactoring • Improve readability • Improve maintainability •
Improve extensibility • Promote an expressive API • Reduce complexity
Ruby freebies
if 1 > 0 @foo = 'bar' else @foo =
'baz' end ! @foo # => 'bar' DRY Assignment
@foo = if 1 > 0 'bar' else 'baz' end
! @foo # => 'bar' DRY Assignment
@foo = case 1 when 0..1 'bar' else 'baz' end
! @foo # => 'bar' DRY Assignment
@foo = 1 > 0 ? 'bar' : 'qux' !
@foo # => 'bar' Ternary operator
def postive?(number) number > 0 ? 'yes' : 'no' end
! positive?(100) # => 'yes' Ternary operator
def foo? if @foo true else false end end Bang
bang
def foo? @foo ? true : false end Bang bang
def foo? !!@foo end Bang bang
if not @foo @foo = 'bar' end Conditional assignment
unless @foo @foo = 'bar' end Conditional assignment
@foo = 'bar' unless @foo Conditional assignment
@foo ||= 'bar' Conditional assignment
Parallel assignment @foo = 'baz' @bar = 'qux' # =>
"baz" # => "qux"
Parallel assignment @foo, @bar = 'baz', 'qux' # => ["baz",
"qux"] ! @foo # => "baz"
Multiple return def get_with_benchmark(uri) res = nil bench = Benchmark.measure
do res = Net::HTTP.get_response(uri) end return res, bench.real end ! @response, @benchmark = get_with_benchmark(@uri) # => [#<Net::HTTPOK 200 OK>, 0.123]
def my_safe_method begin do_something_dangerous() true rescue false end end Implied
begin
def my_safe_method do_something_dangerous() true rescue false end Implied begin
def self.likelihood_of_rain Hpricot::XML(weather_xml)/'probability-of-rain' rescue Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError return false end
! def self.likelihood_of_snow Hpricot::XML(weather_xml)/'probability-of-snow' rescue Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError return false end Exception lists
NET_EXCEPTIONS = [ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError ] ! def self.likelihood_of_rain
Hpricot::XML(weather_xml)/'probability-of-rain' rescue NET_EXCEPTIONS return false end ! def self.likelihood_of_snow Hpricot::XML(weather_xml)/'probability-of-snow' rescue NET_EXCEPTIONS return false end Exception lists
(1..5).map{|number| number.to_s } # => ["1", "2", "3", "4", "5"]
Symbol to Proc
(1..5).map(&:to_s) # => ["1", "2", "3", "4", "5"] Symbol to
Proc
def fibonacci_sum sum = 0 [1,1,2,3,5,8,13].each{|int| sum += int }
sum end ! fibonacci_sum() # => 33 MapReduce
def fibonacci_sum [1,1,2,3,5,8,13].reduce(0){|sum, int| sum + int } end !
fibonacci_sum() # => 33 MapReduce
{:foo => 'bar'}.inject({}) do |memo, (key, value)| memo[value] = key
memo end ! # => {"bar" => :foo} MapReduce
match_data = 'my lil string'.match(/my (\w+) (\w+)/) match_data.captures[0] # =>
"lil" match_data.captures[1] # => "string" match_data.captures[2] # => nil Regex captures
'my lil string'.match(/my (\w+) (\w+)/) $1 # => "lil" $2
# => "string" $3 # => nil Regex captures
'my lil string' =~ /my (\w+) (\w+)/ $1 # =>
"lil" $2 # => "string" $3 # => nil Regex captures
def Resource.create resource = Resource.new resource.save resource end # =>
#<Resource:0xffffff> tap
def Resource.create Resource.new.tap{|resource| resource.save } end # => #<Resource:0xffffff> tap
sprintf("%d as hexadecimal: %04x", 123, 123) # => "123 as
hexadecimal: 007b" ! "%d as hexadecimal: %04x" % [123, 123] # => "123 as hexadecimal: 007b" ! "%s string" % ['my'] # => "my string" sprintf
def cerealize(val) if val.is_a?(Numeric) || val.is_a?(String) val elsif val.is_a?(Enumerable) val.to_json
else val.to_s end end case equality
def cerealize(val) case val when Numeric, String val when Enumerable
val.to_json else val.to_s end end case equality
if command =~ /sudo/ raise 'Danger!' elsif command =~ /^rm
/ puts 'Are you sure?' else puts 'Run it.' end case equality
case command when /sudo/ raise 'Danger!' when /^rm / puts
'Are you sure?' else puts 'Run it.' end case equality
Splat Array def shopping_list(ingredients) unless ingredients.is_a?(Array) ingredients = [ingredients] end
ingredients.join(", ") end ! shopping_list("eggs") # => "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon"
Splat Array def shopping_list(ingredients) [ingredients].flatten.join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! !
Splat Array def shopping_list(ingredients) [*ingredients].join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! !
Splat args def shopping_list(*ingredients) ingredients.join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! shopping_list("eggs", "bacon") # => "eggs, bacon"
Rails freebies
if @user.name and
[email protected]
? puts @user.name else puts "no name"
end blank?
if @user.name.blank? puts "no name" else puts @user.name end blank?
if @user.name.present? puts @user.name else puts "no name" end present?
puts @user.name.presence || "no name" presence
truncate opening = "A long time ago in a galaxy
far, far away" if opening.size > 20 opening[0..16] + "..." end # => "A long time ago i..."
truncate opening = "A long time ago in a galaxy
far, far away" opening.truncate(20) # => "A long time ago i..." !
truncate opening = "A long time ago in a galaxy
far, far away" opening.truncate(20, :separator => ' ') # => "A long time ago..." !
@existing = User.find_by_email(@new.email) @existing.destroy if @existing try
User.find_by_email(@new.email).try(:destroy) try
in? if admin_roles.include? @user.role puts "Hi Admin!" end
in? if @user.role.in? admin_roles puts "Hi Admin!" end
class User ! has_one :account ! def balance self.account.balance end
! def balance=(amount) self.account.balance=(amount) end ! end Delegation
class User ! has_one :account ! delegate :balance, :balance=, :to
=> :account ! end Delegation
class Avatar ! def file_size if @file_size return @file_size else
result = some_expensive_calculation result += more_expensive_calculation @file_size = result end end ! end Memoization
class Avatar ! extend ActiveSupport::Memoizable ! def file_size result =
some_expensive_calculation result += more_expensive_calculation end memoize :file_size ! end Memoization
! alias_method :translate_without_log, :translate ! def translate_with_log(*args) result = translate_without_log(*args)
Rails.logger.info result result end ! alias_method :translate, :translate_with_log alias_method_chain
def translate_with_log(*args) result = translate_without_log(*args) Rails.logger.info result result end !
alias_method_chain :translate, :log alias_method_chain
class Resource class < self ! def host=(name) @host =
hame end def host @host end ! end end class_attribute
class Resource class < self ! attr_accessor :host ! end
end class_attribute
class Resource ! class_attribute :host ! end class_attribute
Hash#symbolize_keys my_hash = { 'foo' => 123 }.symbolize_keys my_hash['foo'] #
=> nil my_hash[:foo] # => 123
Hash#stringify_keys my_hash = { :foo => 123 }.stringify_keys my_hash['foo'] #
=> 123 my_hash[:foo] # => nil
HashWithIndifferentAccess my_hash = { :foo => 123 } my_hash['foo'] #
=> nil my_hash[:foo] # => 123
HashWithIndifferentAccess my_hash = { :foo => 123 }.with_indifferent_access my_hash['foo'] #
=> 123 my_hash[:foo] # => 123
forty_two my_array = [] my_array[41] = "the answer" ! my_array[41]
# => "the answer"
forty_two my_array = [] my_array[41] = "the answer" ! my_array.forty_two
# => "the answer"
slideshare github irc gsterndale gsterndale sternicus