fluent refactoring (lone star ruby conf 2013)
DESCRIPTION
Fluency is "what you can say without having to think about how to say it." "Refactoring" is a language that describes ways to make your code better. I want to inspire you to learn more of that language, so you can make your code better without having to think about it. I'll walk you through the process of reworking a 50-line controller action that's hard to comprehend, let alone refactor. We'll tease apart fiendishly intertwined structures, embrace duplication, use dirty tricks to our advantage, and uncover responsibilities—and bugs!—that weren't obvious at first glance.TRANSCRIPT
![Page 1: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/1.jpg)
Fluent RefactoringSam Livingston-Gray
THERE WILL BE CODE!
It may bethis small
(1..100).each do |i| s = '' fizz = (i % 3).zero? buzz = (i % 5).zero? s << 'Fizz' if fizz s << 'Buzz' if buzz s << '!' if fizz || buzz s = i if s =~ /^$/ puts send
1
![Page 2: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/2.jpg)
Let’s Talk About Math!
2
![Page 3: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/3.jpg)
http://2012books.lardbucket.org/books/elementary-algebra/section_06/5d10b670d78abac93a4572dc0c2afb0f.jpg3
![Page 4: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/4.jpg)
http://www.wikihow.com/Image:Solve-for-X-Step-12.jpg4
![Page 5: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/5.jpg)
http://math.about.com/od/algebra/ss/birthday.htm5
![Page 6: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/6.jpg)
http://www.smosh.com/smosh-pit/photos/16-wonderfully-stupid-test-answers6
![Page 7: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/7.jpg)
Algebra
7
![Page 8: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/8.jpg)
Algebra Isn’t Math
8
![Page 9: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/9.jpg)
Algebra Isn’t all of Math
9
![Page 10: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/10.jpg)
Algebra ⊂ Math
Math
Algebra
10
![Page 11: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/11.jpg)
http://upload.wikimedia.org/wikipedia/commons/thumb/0/08/NautilusCutawayLogarithmicSpiral.jpg/793px-NautilusCutawayLogarithmicSpiral.jpg11
![Page 12: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/12.jpg)
http://upload.wikimedia.org/wikipedia/commons/a/a4/Mandelbrot_sequence_new.gif12
![Page 13: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/13.jpg)
http://mathequalslove.blogspot.com/2012/12/hexaflexagon-love.html13
![Page 14: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/14.jpg)
http://think-like-a-git.net/sections/graph-theory/seven-bridges-of-konigsberg.html14
![Page 15: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/15.jpg)
Math is a LanguageAlgebra is its Grammar
15
![Page 16: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/16.jpg)
Dick and Jane
16
![Page 17: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/17.jpg)
Fluent Refactoring
17
![Page 18: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/18.jpg)
http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/
Can I get a definition?
18
![Page 19: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/19.jpg)
Flu·en·cy (noun)What you can say when you’renot thinking about how to say it
19
![Page 20: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/20.jpg)
What you can say when you’rewoken up in the middle of the night
with a flashlight in your face
Flu·en·cy (noun)
20
![Page 21: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/21.jpg)
http://dailyawesimity.files.wordpress.com/2013/01/cat-stress-relief-4.jpg
Stress
21
![Page 22: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/22.jpg)
http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Level 1 Tarzan ata party
“Beer!”“Good party.”
Level 2 Going tothe party
"Where is the party?""How do I get to the party?"
Level 3 Discussingthe party
"What happened at the party last night?"
Level 4 Charlie Rose "Should parties be illegal?"
Levels of Proficiency
22
![Page 23: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/23.jpg)
Re·fac·tor·ing (noun)"...a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
-refactoring.com
23
![Page 24: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/24.jpg)
http://refactoring.com/
"...a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
24
![Page 25: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/25.jpg)
"Yeah, we're going to have to takea couple of weeks out of the schedule for refactoring, and that's probably going
to break some stuff."
Doin It Rong
25
![Page 26: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/26.jpg)
"Yeah, we're going to have to takea couple of weeks out of the schedule for refactoring, and that's probably going
to break some stuff."
Doin It Rong
26
![Page 27: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/27.jpg)
"Yeah, we're going to have to takea couple of weeks out of the schedule for refactoring, and that's probably going
to break some stuff."
Doin It Rong
27
![Page 28: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/28.jpg)
Re·fac·tor·ing (noun)"...a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
-refactoring.com
28
![Page 29: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/29.jpg)
http://refactoring.com/
"...a disciplined technique for restructuring an existing body of code, altering its internal structure
without changing its external behavior."
29
![Page 30: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/30.jpg)
Tests are implied.-Katrina Owen,
“Therapeutic Refactoring”
30
![Page 31: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/31.jpg)
Re·fac·tor·ing (noun)"...a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
-refactoring.com
31
![Page 32: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/32.jpg)
Re·fac·tor·ing (noun)"...a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
32
![Page 33: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/33.jpg)
Re·fac·tor·ing (noun)
A technique forrestructuring code
without changing behavior
33
![Page 34: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/34.jpg)
Re·fac·tor (verb)
To restructure codewithout changing behavior
34
![Page 35: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/35.jpg)
Tell a clearer storywith fewer details
35
![Page 36: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/36.jpg)
Re·fac·tor·ing (noun)
A language that describes ways to make your code
suck less.
36
![Page 37: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/37.jpg)
THESISES
37
![Page 38: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/38.jpg)
THESISESTHESES
38
![Page 39: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/39.jpg)
THESISESTHESESTHESII
39
![Page 40: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/40.jpg)
THESISESTHESESTHESII
MY POINT(S)
40
![Page 41: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/41.jpg)
You're probably already fluent in refactoring.
Level 1:Rename Variable; Rename Method.
41
![Page 42: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/42.jpg)
You can become more fluent in refactoring.
It just takes practice.
42
![Page 43: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/43.jpg)
Putting in the practice to become more fluent in refactoring is worth it.
Because you’ll be able to say more things when you’re under stress.
43
![Page 44: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/44.jpg)
Refactoring Session
44
![Page 45: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/45.jpg)
Used with:
• Permission
• Obfuscation
• Respect
Production Rails Code
45
![Page 46: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/46.jpg)
Schedule Cable Installs
46
![Page 47: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/47.jpg)
class InstallationsController < ActionController::Base # lots more stuff...
def schedule desired_date = params[:desired_date] if request.xhr? begin if @installation.pending_credit_check? render :json => {:errors => ["Cannot schedule installation while credit check is pending"]}, :status => 400 return end audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end end rescue ActiveRecord::RecordInvalid => e render :json => {:errors => [e.message] } rescue ArgumentError => e render :json => {:errors => ["Could not schedule installation. Start by making sure the desired date is on a business day."]} end else if @installation.pending_credit_check? flash[:error] = "Cannot schedule installation while credit check is pending" redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end end rescue => e flash[:error] = e.message end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end
# lots more stuff...end
47
![Page 48: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/48.jpg)
class InstallationsController < ActionController::Base # lots more stuff...
def schedule desired_date = params[:desired_date] if request.xhr? begin if @installation.pending_credit_check? render :json => {:errors => ["Cannot schedule installation while credit check is pending"]}, :status => 400 return end audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end end rescue ActiveRecord::RecordInvalid => e render :json => {:errors => [e.message] } rescue ArgumentError => e render :json => {:errors => ["Could not schedule installation. Start by making sure the desired date is on a business day."]} end else if @installation.pending_credit_check? flash[:error] = "Cannot schedule installation while credit check is pending" redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end end rescue => e flash[:error] = e.message end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end
# lots more stuff...end
Observations
~800 lines in file
~50 lines in method
Longest line: 177 chars
Indentation: 4-16 spaces
Nested control structures:
audit_trail_for
begin/rescue/end
if/else/end
48
![Page 49: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/49.jpg)
http://scientopia.org/blogs/whitecoatunderground/2009/06/10/my-head-just-asploded-twice/
Complexity
49
![Page 50: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/50.jpg)
http://shipitsquirrel.github.io/
Ship it!
50
![Page 51: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/51.jpg)
http://shipitsquirrel.github.io/
Ship Shit!
51
![Page 52: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/52.jpg)
http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html
~800 lines
52
![Page 53: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/53.jpg)
http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html
~800 lines
53
![Page 54: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/54.jpg)
Make the Job Smaller
54
![Page 55: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/55.jpg)
Replace Method with Method Object
55
![Page 56: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/56.jpg)
class InstallationsController < ActionController::Base def schedule # LOTS OF CODE endend
56
![Page 57: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/57.jpg)
class InstallationsController < ActionController::Base def schedule
endend
class ScheduleInstallation def call
endend
# LOTS OF CODE
57
![Page 58: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/58.jpg)
class InstallationsController < ActionController::Base def schedule
endend
class ScheduleInstallation def call
endend
# LOTS OF CODE
58
![Page 59: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/59.jpg)
class InstallationsController < ActionController::Base def schedule
endend
class ScheduleInstallation def call
endend
ScheduleInstallation.new.call
# LOTS OF CODE
59
![Page 60: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/60.jpg)
class ScheduleInstallation def call # LOTS OF CODE endend
60
![Page 61: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/61.jpg)
class ScheduleInstallation def initialize(controller) @controller = controller end
def call # LOTS OF CODE endend
61
![Page 62: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/62.jpg)
class ScheduleInstallation def initialize(controller) @controller = controller end
def call # LOTS OF CODE end
def method_missing(m, *a, &b) @controller.send(m, *a, &b) endend
62
![Page 63: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/63.jpg)
Code Archaeology
63
![Page 64: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/64.jpg)
if request.xhr? # ...20 lines...else # ...22 lines...end
64
![Page 65: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/65.jpg)
if request.xml_http_request? # ...20 lines...else # ...22 lines...end
65
![Page 66: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/66.jpg)
if request.xml_http_request? begin if @installation.pending_credit_check? render :json => #... return end #... endelse # ...22 lines...end
66
![Page 67: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/67.jpg)
if request.xhr? begin if @installation.pending_credit_check? render :json => #... return end #... endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin #...end
67
![Page 68: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/68.jpg)
if request.xhr? begin if @installation.pending_credit_check? render :json => #... return end #... endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin #...end
68
![Page 69: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/69.jpg)
if request.xhr? begin if @installation.pending_credit_check? render :json => #... return end #... endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin #...end
69
![Page 70: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/70.jpg)
if request.xhr? begin if @installation.pending_credit_check? render :json => #... return end #... endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => @installation.city_id, :view => "calendar") and return end begin #...end
70
![Page 71: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/71.jpg)
if request.xhr? begin if @installation.pending_credit_check? render :json => #... return end #... endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => return end begin #...end
if request.xhr? if @installation.pending_credit_check? render :json => #... return endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to(...) and return return endend
if request.xhr? #...else #...71
![Page 72: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/72.jpg)
if request.xhr? #...else #...end
if request.xhr? #...else #...end
ZOMGduplication!!!1!!
72
![Page 73: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/73.jpg)
if request.xhr? if @installation.pending_credit_check? #... endelse if @installation.pending_credit_check? #... endend
if request.xhr? #...else #...end
73
![Page 74: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/74.jpg)
Emphasis
74
![Page 75: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/75.jpg)
if request.xhr? if @installation.pending_credit_check? #... endelse if @installation.pending_credit_check? #... endend
75
![Page 76: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/76.jpg)
Flatten Nested Conditionals
source: Michael Feathers,writing for Dr. Dobbs
76
![Page 77: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/77.jpg)
if request.xhr? if @installation.pending_credit_check? render :json => #... return endelse if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return endend
77
![Page 78: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/78.jpg)
if ajax if pending_credit_check render :json => #... return endelse if pending_credit_check flash[:error] = #... redirect_to #... return endend
78
![Page 79: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/79.jpg)
if ajax if pending_credit_check render :json => #... return endelse if pending_credit_check flash[:error] = #... redirect_to #... return endend
if ajax if pending_credit_check render :json => #... return endendif not ajax if pending_credit_check flash[:error] = #... redirect_to #... return endend
79
![Page 80: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/80.jpg)
if ajax if pending_credit_check render :json => #... return endendif not ajax if pending_credit_check flash[:error] = #... redirect_to #... return endend
if ajax && pending_credit_check render :json => #... returnendif (not ajax) && pending_credit_check flash[:error] = #... redirect_to #... returnend
80
![Page 81: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/81.jpg)
if ajax && pending_credit_check render :json => #... returnendif (not ajax) && pending_credit_check flash[:error] = #... redirect_to #... returnend
if pending_credit_check if ajax render :json => #... return end if not ajax flash[:error] = #... redirect_to #... return endend
81
![Page 82: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/82.jpg)
if pending_credit_check if ajax render :json => #... return end if not ajax flash[:error] = #... redirect_to #... return endend
if pending_credit_check if ajax render :json => #... return else flash[:error] = #... redirect_to #... return endend
82
![Page 83: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/83.jpg)
if pending_credit_check if ajax render :json => #... return else flash[:error] = #... redirect_to #... return endend
if pending_credit_check if ajax render :json => #... else flash[:error] = #... redirect_to #... end returnend
83
![Page 84: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/84.jpg)
if ajax if pending_credit_check render :json => #... return endelse if pending_credit_check flash[:error] = #... redirect_to #... return endend
if pending_credit_check if ajax render :json => #... else flash[:error] = #... redirect_to #... end returnend
84
![Page 85: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/85.jpg)
if pending_credit_check if ajax render :json => #... else flash[:error] = #... redirect_to #... end returnend
if pending_credit_check cant_schedule_while_credit_check_pending returnend
85
![Page 86: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/86.jpg)
Exception Handling
86
![Page 87: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/87.jpg)
raise “wtf” if coin.toss.heads?begin raise “wtf” if coin.toss.heads?end
87
![Page 88: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/88.jpg)
begin raise “wtf” if coin.toss.heads?end
begin raise “wtf” if coin.toss.heads?rescue => e raise eend
88
![Page 89: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/89.jpg)
begin raise “wtf” if coin.toss.heads?rescue => e raise eend
89
![Page 90: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/90.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue #... endrescue => e raise eend
90
![Page 91: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/91.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? end endrescue => e raise eend
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? end endrescue => e if request.xhr? raise e else raise e endend91
![Page 92: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/92.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? end endrescue => e if request.xhr? raise e else raise e endend
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? # DO NOTHING else raise “yak” if Moon.gibbous? end endrescue => e if request.xhr? raise “tfw” if tuesday? else raise e endend92
![Page 93: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/93.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? # DO NOTHING else raise “yak” if Moon.gibbous? end endrescue => e if request.xhr? raise “tfw” if tuesday? else raise e endend
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? # DO NOTHING else # DO NOTHING end endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend93
![Page 94: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/94.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue if request.xhr? # DO NOTHING else # DO NOTHING end endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
begin begin raise “wtf” if coin.toss.heads? rescue # DO NOTHING endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
94
![Page 95: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/95.jpg)
begin begin raise “wtf” if coin.toss.heads? rescue # DO NOTHING endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
begin begin raise “wtf” if coin.toss.heads? endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
95
![Page 96: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/96.jpg)
begin begin raise “wtf” if coin.toss.heads? endrescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
begin raise “wtf” if coin.toss.heads?rescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
96
![Page 97: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/97.jpg)
begin raise “wtf” if coin.toss.heads?rescue => e if request.xhr? raise “tfw” if tuesday? else raise “yak” if Moon.gibbous? endend
begin raise “wtf” if coin.toss.heads?rescue => e handle_exception(e)end
97
![Page 98: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/98.jpg)
Training Montage
98
![Page 99: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/99.jpg)
class ScheduleInstallation def call desired_date = params[:desired_date] if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin if request.xhr? audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end end else audit_trail_for(current_user) do if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end rescue Exception => e handle_exception e end endend
99
![Page 100: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/100.jpg)
class ScheduleInstallation def call desired_date = params[:desired_date] if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do if request.xhr? if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end else if @installation.schedule!(desired_date, :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end rescue Exception => e handle_exception e end endend
100
![Page 101: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/101.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do if request.xhr? if @installation.schedule!(params[:desired_date], :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end else if @installation.schedule!(params[:desired_date], :installation_type => params[:installation_type], :city => @city) if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end rescue Exception => e handle_exception e end endend
101
![Page 102: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/102.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if request.xhr? if success if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } end else if success if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end rescue Exception => e handle_exception e end endend
102
![Page 103: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/103.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if success if request.xhr? if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end else if request.xhr? render :json => {:errors => [%Q{Could not update installation. #{@installation.errors.full_messages.join(' ')}}] } else flash[:error] = %Q{Could not schedule installation, check the phase of the moon} redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end end end rescue Exception => e handle_exception e end endend
103
![Page 104: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/104.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if success if request.xhr? if @installation.scheduled_date date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} end else if @installation.scheduled_date if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end else scheduling_failed end end rescue Exception => e handle_exception e end endend
104
![Page 105: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/105.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if success if @installation.scheduled_date if request.xhr? date = @installation.scheduled_date.in_time_zone(@installation.city.timezone).to_date render :json => {:errors => nil, :html => schedule_response(@installation, date)} else if @installation.customer_provided_equipment? flash[:success] = %Q{Installation scheduled} else flash[:success] = %Q{Installation scheduled! Don't forget to order the equipment also.} end end end if request.xhr? # do nothing else redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end else scheduling_failed end end rescue Exception => e handle_exception e end endend
105
![Page 106: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/106.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if success if @installation.scheduled_date scheduling_succeeded end if request.xhr? # do nothing else redirect_to(@installation.customer_provided_equipment? ? customer_provided_installations_path : installations_path(:city_id => @installation.city_id, :view => "calendar")) end else scheduling_failed end end rescue Exception => e handle_exception e end endend
106
![Page 107: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/107.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do success = schedule! if success if @installation.scheduled_date scheduling_succeeded end do_post_success_cleanup else scheduling_failed end end rescue Exception => e handle_exception e end endend
107
![Page 108: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/108.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do if schedule! if @installation.scheduled_date scheduling_succeeded end do_post_success_cleanup else scheduling_failed end end rescue Exception => e handle_exception e end endend
108
![Page 109: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/109.jpg)
class ScheduleInstallation def call if @installation.pending_credit_check? cant_schedule_while_credit_check_pending return end
begin audit_trail_for(current_user) do if schedule! if @installation.scheduled_date scheduling_succeeded end do_post_success_cleanup else scheduling_failed end end rescue Exception => e handle_exception e end endend
request.xhr?
109
![Page 110: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/110.jpg)
Under The Rug
110
![Page 111: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/111.jpg)
class ScheduleInstallation def cannot_schedule_while_#... if request.xhr? # ...1 line... else # ...2 lines... end end
def handle_exception(e) if request.xhr? # ...7 lines... else # ...2 lines... end end
def scheduling_failed if request.xhr? # ...1 line... else # ...2 lines... end end
def scheduling_succeeded if request.xhr? # ...2 lines... else # ...5 lines... end end
def do_post_success_cleanup if request.xhr? # DO NOTHING else # ...1 line... end end
end
111
![Page 112: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/112.jpg)
class ScheduleInstallation private
def scheduling_failed if request.xhr? render :json => {:errors => [#... else flash[:error] = #... redirect_to #... end endend
112
![Page 113: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/113.jpg)
Single Responsibility Principle
113
![Page 114: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/114.jpg)
ScheduleInstallationScheduleInstallationAnd
DoOneThingForAJAXRequestsAndDoSomethingElseForHTMLRequests
114
![Page 115: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/115.jpg)
ScheduleInstallationScheduleInstallation And
DoOneThingForAJAXRequests AndDoSomethingElseForHTMLRequests
115
![Page 116: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/116.jpg)
“Methods, like classes, should have a single
responsibility.”-Sandi Metz
116
![Page 117: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/117.jpg)
http://en.wikipedia.org/wiki/File:Bill_%26_Ted%27s_Excellent_Adventure_(Original_Motion_Picture_Soundtrack).jpg117
![Page 118: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/118.jpg)
http://en.wikipedia.org/wiki/File:Paris_Tuileries_Garden_Facepalm_statue.jpg118
![Page 119: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/119.jpg)
Single Responsibility Principle
Every class should have a single responsibility, and that responsibility
should be entirely encapsulatedby the class.
119
![Page 120: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/120.jpg)
ScheduleInstallationScheduleInstallation And
DoOneThingForAJAXRequests AndDoSomethingElseForHTMLRequests
120
![Page 121: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/121.jpg)
Responder
121
![Page 122: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/122.jpg)
122
InstallationsController
![Page 123: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/123.jpg)
123
InstallationsController
ScheduleInstallation???
![Page 124: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/124.jpg)
124
InstallationsController
Responder
???
ScheduleInstallation???
![Page 125: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/125.jpg)
class ScheduleInstallation def call
private
def cannot_schedule_while_credit_check_pendin def handle_exception(e) def scheduling_failed def scheduling_succeeded def do_post_success_cleanupend
class Responderend
class ScheduleInstallation def callend
class Responder def cannot_schedule_while_credit_check_pe def handle_exception(e) def scheduling_failed def scheduling_succeeded def do_post_success_cleanupend
125
![Page 126: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/126.jpg)
126
Dualism
![Page 127: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/127.jpg)
class Responder def cannot_schedule_while_credit_check_pending # ...6 lines... end
def cannot_schedule_while_credit_check_pending if request.xhr? # ...1 line... else # ...2 lines... end end
def handle_exception(e) if request.xhr? # ...7 lines... else # ...2 lines... end end
def scheduling_failed if request.xhr? # ...1 line... else # ...2 lines... end end
def scheduling_succeeded if request.xhr? # ...2 lines... else # ...5 lines... end end
def do_post_success_cleanup if request.xhr? # NOP else # ...2 lines... end end end
![Page 128: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/128.jpg)
if request.xhr? # do fooelse # do barend
![Page 129: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/129.jpg)
Replace ConditionalWith Polymorphism
129
![Page 130: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/130.jpg)
class Responder def cannot_schedule_while_credit_check_pending def handle_exception(e) def scheduling_failed def scheduling_succeeded def do_post_success_cleanupend
class AJAXResponder def cannot_schedule_while_credit_check_pending def handle_exception(e) def scheduling_failed def scheduling_succeeded def do_post_success_cleanupend
class HTMLResponder def cannot_schedule_while_credit_check_pending def handle_exception(e) def scheduling_failed def scheduling_succeeded def do_post_success_cleanupend
![Page 131: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/131.jpg)
class AJAXResponder def scheduling_failed if request.xhr? render :json => #... else flash[:error] = #... redirect_to #... end endend
class HTMLResponder def scheduling_failed if request.xhr? render :json => #... else flash[:error] = #... redirect_to #... end endend
class AJAXResponder def scheduling_failed render :json => #... endend
class HTMLResponder def scheduling_failed flash[:error] = #... redirect_to #... endend
![Page 132: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/132.jpg)
132
InstallationsController
Responder
???
ScheduleInstallation???
![Page 133: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/133.jpg)
class InstallationsController < ActionController::Base
def schedule responder = if request.xhr? AJAXResponder.new(self) else HTMLResponder.new(self) end ScheduleInstallation.new(responder).call endend
![Page 134: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/134.jpg)
LESSONS LEARNED
134
![Page 135: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/135.jpg)
Refactoring is Math
135
![Page 136: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/136.jpg)
Fast CharacterizationTests Rock
136
![Page 137: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/137.jpg)
Embrace Duplicationif request.xhr?
137
0
2
4
6
8
10
![Page 138: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/138.jpg)
Embrace Evil Hacks
138
![Page 139: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/139.jpg)
Perspective MattersSuperficial design flaws
can concealfundamental design flaws
139
![Page 140: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/140.jpg)
http://gomakemeasandwich.wordpress.com/2011/10/26/a-yeaf-of-gmmas-where-do-we-go-from-here/
Where Do We Go From Here?
140
![Page 141: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/141.jpg)
141
![Page 142: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/142.jpg)
142
![Page 143: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/143.jpg)
143
![Page 145: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/145.jpg)
Practice!• Play with automated refactorings in an IDE
• Do them manually in the editor (wax on, wax off)
145
![Page 146: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/146.jpg)
Practice!• Commit early, commit often:
‘git reset --hard’ is your friend!
• Use throwaway branches
• Write fast characterization tests
146
![Page 147: Fluent Refactoring (Lone Star Ruby Conf 2013)](https://reader034.vdocuments.net/reader034/viewer/2022042814/554f9928b4c90586258b4711/html5/thumbnails/147.jpg)
Fluent Refactoringgithub.com/geeksam/fluent-refactoring
Twitter, Github: @geeksam
147