Fluent Refactoring
Sam Livingston-Gray

THERE
WILL BE
CODE!
It may be
this small

puts (1..100).map { |i|
s = ''
fizz = (i % 3).zero?
buzz = (i % 5).zero?
s << 'Fizz' if fizz
s << 'Buzz' if buzz
s = i if s.empty?
s
}

1
Tuesday, October 22, 13
Math
m/

2
Tuesday, October 22, 13
3
http://2012books.lardbucket.org/books/elementary-algebra/section_06/5d10b670d78abac93a4572dc0c2afb0f.jpg
Tuesday, October 22, 13
4
Tuesday, October 22, 13

http://www.wikihow.com/Image:Solve-for-X-Step-12.jpg
5
Tuesday, October 22, 13

http://math.about.com/od/algebra/ss/birthday.htm
6
http://www.smosh.com/smosh-pit/photos/16-wonderfully-stupid-test-answers
Tuesday, October 22, 13
Algebra

7
Tuesday, October 22, 13
Algebra Isn’t Math

8
Tuesday, October 22, 13
Algebra Isn’t all of Math

9
Tuesday, October 22, 13
Algebra ⊂ Math
Algebra

Math
10
Tuesday, October 22, 13
11

http://upload.wikimedia.org/wikipedia/commons/thumb/0/08/NautilusCutawayLogarithmicSpiral.jpg/793px-NautilusCutawayLogarithmicSpiral.jpg
Tuesday, October 22, 13
12
http://upload.wikimedia.org/wikipedia/commons/a/a4/Mandelbrot_sequence_new.gif
Tuesday, October 22, 13
13
http://mathequalslove.blogspot.com/2012/12/hexaflexagon-love.html
Tuesday, October 22, 13
14
http://think-like-a-git.net/sections/graph-theory/seven-bridges-of-konigsberg.html
Tuesday, October 22, 13
Math is a Language

15
Tuesday, October 22, 13
Math is a Language
Algebra is
[one of]
its Grammar[s]

15
Tuesday, October 22, 13
Fluent Refactoring

16
Tuesday, October 22, 13
17
http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/
Tuesday, October 22, 13
Can I get a
definition?

17
http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/
Tuesday, October 22, 13
Re·fac·tor·ing (noun)

18
Tuesday, October 22, 13
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

18
Tuesday, October 22, 13
TL;DR

19
Tuesday, October 22, 13
TL;DR
"...a disciplined technique for
restructuring an existing body of
code, altering its internal structure
without changing its external
behavior."

19
Tuesday, October 22, 13
Re·fac·tor·ing (noun)
A technique
for restructuring code
without changing behavior

20
Tuesday, October 22, 13
Tell a clearer story
with fewer details

21
Tuesday, October 22, 13
Jargon

22
Tuesday, October 22, 13

http://www.tagxedo.com/app.html
Jargon

22
Tuesday, October 22, 13

http://www.tagxedo.com/app.html
Re·fac·tor·ing (noun)

23
Tuesday, October 22, 13
Re·fac·tor·ing (noun)
A language that
describes ways to
make your code
suck less.
23
Tuesday, October 22, 13
Flu·en·cy (noun)

24
Tuesday, October 22, 13
Flu·en·cy (noun)
What you can say when you’re
not thinking about how to say it

24
Tuesday, October 22, 13
Flu·en·cy (noun)
What you can say when you’re
woken up in the middle of the night
with a flashlight in your face

25
Tuesday, October 22, 13
Stress

26
http://dailyawesimity.files.wordpress.com/2013/01/cat-stress-relief-4.jpg
Tuesday, October 22, 13
Language Hunters

27
Tuesday, October 22, 13
Levels of Proficiency
Level 1
Level 2
Level 3
Level 4

28
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2
Level 3
Level 4

29
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2

Going to
the party

"Where is the party?"
"How do I get to the party?"

Level 3
Level 4

30
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2

Going to
the party

"Where is the party?"
"How do I get to the party?"

Level 3

Discussing
the party

"What happened at the party
last night?"

Level 4

31
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2

Going to
the party

"Where is the party?"
"How do I get to the party?"

Level 3

Discussing
the party

"What happened at the party
last night?"

Level 4

Charlie Rose

"Should parties be illegal?"

32
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2

Going to
the party

"Where is the party?"
"How do I get to the party?"

Level 3

Discussing
the party

"What happened at the party
last night?"

Level 4

Charlie Rose

"Should parties be illegal?"

33
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Levels of Proficiency
Level 1

Tarzan at
a party

“Beer!”
“Good party.”

Level 2

Going to
the party

"Where is the party?"
"How do I get to the party?"

34
Tuesday, October 22, 13

http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
Story Time

35
Tuesday, October 22, 13
Production Rails Code

36
Tuesday, October 22, 13
Production Rails Code
Used with:

• Permission

36
Tuesday, October 22, 13
Production Rails Code
Used with:

• Permission
• Obfuscation

36
Tuesday, October 22, 13
Production Rails Code
Used with:

• Permission
• Obfuscation
• Respect

36
Tuesday, October 22, 13
Respect

37
Tuesday, October 22, 13
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

Tuesday, October 22, 13

38
Observations

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

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

~50 lines in method

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

~50 lines in method

Longest line: 177 chars

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

~50 lines in method

Longest line: 177 chars
Indentation: 4-16 spaces

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

~50 lines in method

Longest line: 177 chars
Indentation: 4-16 spaces
Nested control
structures:

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~800 lines in file

~50 lines in method

Longest line: 177 chars
Indentation: 4-16 spaces
Nested control
structures:
audit_trail_for

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~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

# lots more stuff...
end

Tuesday, October 22, 13

39
Observations

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

~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

# lots more stuff...
end

Tuesday, October 22, 13

39
Complexity

40
http://scientopia.org/blogs/whitecoatunderground/2009/06/10/my-head-just-asploded-twice/
Tuesday, October 22, 13
Ship it!

41
Tuesday, October 22, 13

http://shipitsquirrel.github.io/
~800 lines

42
Tuesday, October 22, 13
~800 lines

42
http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html
Tuesday, October 22, 13
~800 lines

42
http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html
Tuesday, October 22, 13
~800 lines

43
http://hyperboleandahalf.blogspot.com/2010/06/this-is-why-ill-never-be-adult.html
Tuesday, October 22, 13
Make the Job Smaller

44
Tuesday, October 22, 13
Replace Method with
Method Object
See also:
Katrina Owen,
“Therapeutic Refactoring”

45
Tuesday, October 22, 13
class InstallationsController <
ActionController::Base
def schedule
# LOTS OF CODE
end
end

46
Tuesday, October 22, 13
class InstallationsController <
ActionController::Base
def schedule
# LOTS OF CODE
end
end
class ScheduleInstallation
def call
end
end

47
Tuesday, October 22, 13
class InstallationsController <
ActionController::Base
def schedule
end
end
class ScheduleInstallation
def call
# LOTS OF CODE
end
end

47
Tuesday, October 22, 13
class InstallationsController <
ActionController::Base
def schedule
ScheduleInstallation.new.call
end
end
class ScheduleInstallation
def call
# LOTS OF CODE
end
end

47
Tuesday, October 22, 13
NoMethodError
LOL WUT?

48
Tuesday, October 22, 13
class
def
#
#
#
#
end
end

ScheduleInstallation
call
LOTS OF CODE
... params ...
... render ...
... redirect_to ...

49
Tuesday, October 22, 13
class ScheduleInstallation
def initialize(controller)
@controller = controller
end
def
#
#
#
#
end
end

call
LOTS OF CODE
... params ...
... render ...
... redirect_to ...

50
Tuesday, October 22, 13
class ScheduleInstallation
def initialize(controller)
@controller = controller
end
def
#
#
#
#
end
end

call
LOTS OF CODE
... @controller.params ...
... @controller.render ...
... @controller.redirect_to ...

51
Tuesday, October 22, 13
class ScheduleInstallation
def initialize(controller)
@controller = controller
end
extend Forwardable
def_delegators :@controller,
:params, :render, :redirect_to
def
#
#
#
#
end
end

call
LOTS OF CODE
... params ...
... render ...
... redirect_to ...

52
Tuesday, October 22, 13
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)
end
end

53
Tuesday, October 22, 13
Code Archaeology

54
http://anthro.ucsc.edu/undergraduate/sub-fields/anthro-archeaology.html
Tuesday, October 22, 13
if request.xhr?
# ...20 lines...
else
# ...22 lines...
end

55
Tuesday, October 22, 13
if request.xml_http_request?
# ...20 lines...
else
# ...22 lines...
end

56
Tuesday, October 22, 13
if request.xml_http_request?
begin
#...
end
else
# ...22 lines...
end

57
Tuesday, October 22, 13
if request.xml_http_request?
begin
if @installation.pending_credit_check?
render :json => #...
return
end
#...
end
else
# ...22 lines...
end

58
Tuesday, October 22, 13
if request.xml_http_request?
begin
if @installation.pending_credit_check?
render :json => #...
return
end
#...
end
else
# ...22 lines...
end

58
Tuesday, October 22, 13
if request.xml_http_request?
begin
if @installation.pending_credit_check?
render :json => #...
return
end
#...
Guard Clause
end
-Smalltalk Best Practice Patterns
else
by Kent Beck
# ...22 lines...
end

58
Tuesday, October 22, 13
if request.xhr?
begin
if @installation.pending_credit_check?
render :json => #...
return
end
#...
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to installations_path(:city_id =>
end
begin
#...
end
end
59
Tuesday, October 22, 13
tion.city_id, :view => "calendar") and return

59
Tuesday, October 22, 13
if request.xhr?
begin
if @installation.pending_credit_check?
render :json => #...
return
end
#...
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to installations_path(:city_id =>
return
end
begin
#...
end
60
Tuesday, October 22, 13
if request.xhr?
if request.xhr?
begin
if @installation.pend
if @installation.pending_credit_check? #..
render :json =>
render :json => #... return
return
end
end
begin
#...
#...
end
end
else
else
if @installation.pending_credit_check?
if @installation.pend
flash[:error] = #...
flash[:error] = #..
redirect_to installations_path(:city_id =>
redirect_to install
return
return
end
end
begin
begin
#...
#...
end
end
60
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
begin
#...
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to installations_path(:city_id =>
return
end
begin
#...
end
61
Tuesday, October 22, 13
if request.xhr?
if request.xhr?
if @installation.pending_credit_check?
if @installation.pend
render :json => #...
render :json => #..
return
return
end
end
begin
else
#...
if @installation.pend
end
flash[:error] = #..
else
redirect_to #...
if @installation.pending_credit_check?
return
flash[:error] = #... end
redirect_to installations_path(:city_id =>
end
return
end
if request.xhr?
begin
begin
#...
#...
end
end
61
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

62
Tuesday, October 22, 13
emph·AS·is

63
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

64
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

64
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

64
Tuesday, October 22, 13
Flatten Nested
Conditionals
source:
Michael Feathers
in Dr. Dobbs

65
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

66
Tuesday, October 22, 13
if ajax
if nope
render :json => #...
return
end
else
if nope
flash[:error] = #...
redirect_to #...
return
end
end

67
Tuesday, October 22, 13
if ajax
if nope
render :json => #...
return
end
else
if nope
flash[:error] = #...
redirect_to #...
return
end
end

67
Tuesday, October 22, 13

ajax

nope

TRUE

TRUE

ajax

nope

FALSE

TRUE
if ajax
if nope
render :json => #...
return
end
else
if nope
flash[:error] = #...
redirect_to #...
return
end
end

68
Tuesday, October 22, 13
if ajax
if ajax
if nope
if nope
render :json => #...
render :json => #..
return
return
end
end
else
end
if nope
if not ajax
flash[:error] = #... if nope
redirect_to #...
flash[:error] = #..
return
redirect_to #...
end
return
end
end
end

68
Tuesday, October 22, 13
if ajax
if nope
render :json => #...
return
end
end
if not ajax
if nope
flash[:error] = #...
redirect_to #...
return
end
end

69
Tuesday, October 22, 13
if ajax
if ajax && nope
if nope
render :json => #...
render :json => #... return
return
end
end
if (not ajax) && nope
end
flash[:error] = #...
if not ajax
redirect_to #...
if nope
return
flash[:error] = #...end
redirect_to #...
return
end
end

69
Tuesday, October 22, 13
if ajax && nope
render :json => #...
return
end
if (not ajax) && nope
flash[:error] = #...
redirect_to #...
return
end

70
Tuesday, October 22, 13
if ajax && nope
render :json => #...
return
end
if (not ajax) && nope
flash[:error] = #...
redirect_to #...
return
end

70
Tuesday, October 22, 13
if ajax && nope
render :json => #...
return
end
if (not ajax) && nope
flash[:error] = #...
redirect_to #...
return
end

if nope
if ajax
render :json => #..
return
end
if not ajax
flash[:error] = #..
redirect_to #...
return
end
end

70
Tuesday, October 22, 13
if nope
if ajax
render :json => #...
return
end
if not ajax
flash[:error] = #...
redirect_to #...
return
end
end

71
Tuesday, October 22, 13
if nope
if nope
if ajax
if ajax
render :json => #...
render :json => #..
return
return
end
else
if not ajax
flash[:error] = #..
flash[:error] = #...
redirect_to #...
redirect_to #...
return
return
end
end
end
end

71
Tuesday, October 22, 13
if nope
if ajax
render :json => #...
return
else
flash[:error] = #...
redirect_to #...
return
end
end

72
Tuesday, October 22, 13
if nope
if nope
if ajax
if ajax
render :json => #...
render :json => #..
return
else
else
flash[:error] = #..
flash[:error] = #...
redirect_to #...
redirect_to #...
end
return
return
end
end
end

72
Tuesday, October 22, 13
if request.xhr?
if @installation.pending_credit_check?
render :json => #...
return
end
else
if @installation.pending_credit_check?
flash[:error] = #...
redirect_to #...
return
end
end

73
Tuesday, October 22, 13
if request.xhr?
if @installation.pendin
if @installation.pending_credit_check?
if request.xhr?
render :json => #...
render :json => #..
return
else
end
flash[:error] = #..
else
redirect_to #...
if @installation.pending_credit_check?
end
flash[:error] = #... return
redirect_to #...
end
return
end
end

73
Tuesday, October 22, 13
if @installation.pending_credit_check?
if request.xhr?
render :json => #...
else
flash[:error] = #...
redirect_to #...
end
return
end

74
Tuesday, October 22, 13
if @installation.pendin
if @installation.pending_credit_check?
cant_schedule_while_c
if request.xhr?
render :json => #... return
end
else
flash[:error] = #...
redirect_to #...
end
return
end

74
Tuesday, October 22, 13
if @installation.pending_credit_check?
cant_schedule_while_credit_check_pending
return
end
if request.xhr?
begin
#...
end
else
begin
#...
end
end

75
Tuesday, October 22, 13
“Hard Work” Montage

76
http://spectrumculture.com/2012/09/re-makere-model-the-karate-kid-1984-vs-the-karate-kid-2010.html/
Tuesday, October 22, 13
class InstallationsController < ActionController::Base
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
end

77
Tuesday, October 22, 13
class InstallationsController < ActionController::Base
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
end

class ScheduleInstallation
def call
if @installation.pending_c
cant_schedule_while_cred
return
end

77
Tuesday, October 22, 13

audit_trail_for(current_us
if schedule!
if @installation.sched
scheduling_succeeded
end
do_post_success_cleanu
else
scheduling_failed
end
end
rescue => e
handle_exception e
end
end
class ScheduleInstallation
def call
if @installation.pending_credit_check?
cant_schedule_while_credit_check_pending
return
end
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 => e
handle_exception e
end
end
78

Tuesday, October 22, 13
class ScheduleInstallation
def call
if @installation.pending_credit_check?
cant_schedule_while_credit_check_pending
return
end
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 => e
handle_exception e
end
end

request.xhr?

79

Tuesday, October 22, 13
class ScheduleInstallation
def call
if @installation.pending_credit_check?
cant_schedule_while_credit_check_pending
return
end
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 => e
handle_exception e
end
end

request.xhr?

79

Tuesday, October 22, 13
Under The Rug

80
Tuesday, October 22, 13
def cannot_schedule_while_#...
if request.xhr?
# ...1 line...
else
# ...2 lines...
end
end

def scheduling_failed
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 do_post_success_cleanup
if request.xhr?
# DO NOTHING
else
# ...1 line...
end
end

def scheduling_succeeded
if request.xhr?
# ...2 lines...
else
# ...5 lines...
end
end
81
Tuesday, October 22, 13
def cannot_schedule_while_#...
if request.xhr?
# ...1 line...
else
# ...2 lines...
end
end

def scheduling_failed
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 do_post_success_cleanup
if request.xhr?
# DO NOTHING
else
# ...1 line...
end
end

def scheduling_succeeded
if request.xhr?
# ...2 lines...
else
# ...5 lines...
end
end
81
Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class ScheduleInstallation
def scheduling_failed
if request.xhr?
render :json => {:errors#...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
Single Responsibility
Principle
(SRP for short)

83
Tuesday, October 22, 13
ScheduleInstallation

84
Tuesday, October 22, 13
ScheduleInstallation
ScheduleInstallationAnd
DoOneThingForAJAXRequestsAnd
DoSomethingElseForHTMLRequests

84
Tuesday, October 22, 13
ScheduleInstallation
ScheduleInstallation And

DoOneThingForAJAXRequests And
DoSomethingElseForHTMLRequests

85
Tuesday, October 22, 13
ScheduleInstallation
ScheduleInstallation And
DoOneThingForAJAXRequests And
DoSomethingElseForHTMLRequests

86
Tuesday, October 22, 13
Recap

87
Tuesday, October 22, 13
InstallationsController

88
Tuesday, October 22, 13
InstallationsController

ScheduleInstallation

88
Tuesday, October 22, 13
InstallationsController
???
ScheduleInstallation

88
Tuesday, October 22, 13
InstallationsController

Responder
???
ScheduleInstallation

89
Tuesday, October 22, 13
InstallationsController
???
Responder
???
ScheduleInstallation

89
Tuesday, October 22, 13
class ScheduleInstallation
def call
private
def
def
def
def
def
end

cannot_schedule_while_credit_check_pendin
handle_exception(e)
scheduling_failed
scheduling_succeeded
do_post_success_cleanup

class Responder
end

90
Tuesday, October 22, 13
class ScheduleInstallation
class ScheduleInstallat
def call
def call
end
private
class Responder
def cannot_schedule_while_credit_check_pendin
def cannot_schedule_w
def handle_exception(e) def handle_exception(
def scheduling_failed
def scheduling_failed
def scheduling_succeededdef scheduling_succee
def do_post_success_cleanup do_post_success_c
def
end
end
class Responder
end

90
Tuesday, October 22, 13
Responder

91
Tuesday, October 22, 13
if request.xhr?
# do this
else
# do that
end
Tuesday, October 22, 13
Replace Conditional
With Polymorphism

93
Tuesday, October 22, 13
class
def
def
def
def
def
end

Tuesday, October 22, 13

Responder
cannot_schedule_while_credit_check_pending
handle_exception(e)
scheduling_failed
scheduling_succeeded
do_post_success_cleanup
class
def
def
def
def
def
end

Responder
class AJAXResponder
cannot_schedule_while_credit_check_pending
def
handle_exception(e) cannot_schedule_while_cre
scheduling_failed
def handle_exception(e)
scheduling_succeeded def scheduling_failed
do_post_success_cleanup scheduling_succeede
def
def do_post_success_cle
end

class HTMLResponder
def
cannot_schedule_while_cre
def handle_exception(e)
def scheduling_failed
def scheduling_succeede
def do_post_success_cle
end
Tuesday, October 22, 13
class InstallationsController
< ActionController::Base
def schedule
responder = request.xhr?
?
AJAXResponder.new(self) :
HTMLResponder.new(self)
ScheduleInstallation.new(responder).call
end
end

Tuesday, October 22, 13
class InstallationsController
< ActionController::Base
def schedule
responder = request.xhr?
?
AJAXResponder.new(self) :
HTMLResponder.new(self)
ScheduleInstallation.new(responder).call
end
end

Tuesday, October 22, 13
class InstallationsController
< ActionController::Base
def schedule
responder = request.xhr?
?
AJAXResponder.new(self) :
HTMLResponder.new(self)
ScheduleInstallation.new(responder).call
end
end

Tuesday, October 22, 13
class AJAXResponder
def scheduling_failed
if request.xhr?
render :json => #...
else
flash[:error] = #...
redirect_to #...
end
end
end
class HTMLResponder
def scheduling_failed
if request.xhr?
render :json => #...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13
class AJAXResponder
def scheduling_failed
if request.xhr?
render :json => #...
else
flash[:error] = #...
redirect_to #...
end
end
end
class HTMLResponder
def scheduling_failed
if request.xhr?
render :json => #...
else
flash[:error] = #...
redirect_to #...
end
end
end

Tuesday, October 22, 13

class AJAXResponder
def scheduling_failed
render :json => #...
end
end
class HTMLResponder
def scheduling_failed
flash[:error] = #...
redirect_to #...
end
end
class InstallationsController
< ActionController::Base
def schedule
responder = request.xhr?
?
AJAXResponder.new(self) :
HTMLResponder.new(self)
ScheduleInstallation.new(responder).call
end
end

Tuesday, October 22, 13
Where Do We Go
From Here?

98
http://gomakemeasandwich.wordpress.com/2011/10/26/a-yeaf-of-gmmas-where-do-we-go-from-here/
Tuesday, October 22, 13
99
Tuesday, October 22, 13

http://www.poodr.info/
100
Tuesday, October 22, 13
101
Tuesday, October 22, 13
102
Tuesday, October 22, 13
103
Tuesday, October 22, 13
Commit Early,
Commit Often

104
Tuesday, October 22, 13
Throw Your Work Away

105
Tuesday, October 22, 13
Speed Up Your Tests!

106
Tuesday, October 22, 13
Speed Up Your Tests!
See also:
Katrina Owen,
“Therapeutic Refactoring”
(srsly)

106
Tuesday, October 22, 13
I work at LivingSocial.
We’re hiring.

107
Tuesday, October 22, 13
I work at LivingSocial.
We’re hiring.
(Who isn’t?)

107
Tuesday, October 22, 13
Thanks to:
Jim Shore and Diana Larsen
for “Agile Fluency”
Kirsten Comandich
Sandi Metz, Katrina Owen,
Sonia Connolly
PDX.rb
108
Tuesday, October 22, 13
github.com/geeksam
/fluent-refactoring

109
Tuesday, October 22, 13
github.com/geeksam
/fluent-refactoring
Sam Livingston-Gray
geeksam@gmail.com
Twitter, Github: @geeksam

110
Tuesday, October 22, 13

Fluent Refactoring (Cascadia Ruby Conf 2013)

  • 1.
    Fluent Refactoring Sam Livingston-Gray THERE WILLBE CODE! It may be this small puts (1..100).map { |i| s = '' fizz = (i % 3).zero? buzz = (i % 5).zero? s << 'Fizz' if fizz s << 'Buzz' if buzz s = i if s.empty? s } 1 Tuesday, October 22, 13
  • 2.
  • 3.
  • 4.
    4 Tuesday, October 22,13 http://www.wikihow.com/Image:Solve-for-X-Step-12.jpg
  • 5.
    5 Tuesday, October 22,13 http://math.about.com/od/algebra/ss/birthday.htm
  • 6.
  • 7.
  • 8.
  • 9.
    Algebra Isn’t allof Math 9 Tuesday, October 22, 13
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
    Math is aLanguage 15 Tuesday, October 22, 13
  • 16.
    Math is aLanguage Algebra is [one of] its Grammar[s] 15 Tuesday, October 22, 13
  • 17.
  • 18.
  • 19.
    Can I geta definition? 17 http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/ Tuesday, October 22, 13
  • 20.
  • 21.
    Re·fac·tor·ing (noun) "...a disciplinedtechnique for restructuring an existing body of code, altering its internal structure without changing its external behavior." -refactoring.com 18 Tuesday, October 22, 13
  • 22.
  • 23.
    TL;DR "...a disciplined techniquefor restructuring an existing body of code, altering its internal structure without changing its external behavior." 19 Tuesday, October 22, 13
  • 24.
    Re·fac·tor·ing (noun) A technique forrestructuring code without changing behavior 20 Tuesday, October 22, 13
  • 25.
    Tell a clearerstory with fewer details 21 Tuesday, October 22, 13
  • 26.
    Jargon 22 Tuesday, October 22,13 http://www.tagxedo.com/app.html
  • 27.
    Jargon 22 Tuesday, October 22,13 http://www.tagxedo.com/app.html
  • 28.
  • 29.
    Re·fac·tor·ing (noun) A languagethat describes ways to make your code suck less. 23 Tuesday, October 22, 13
  • 30.
  • 31.
    Flu·en·cy (noun) What youcan say when you’re not thinking about how to say it 24 Tuesday, October 22, 13
  • 32.
    Flu·en·cy (noun) What youcan say when you’re woken up in the middle of the night with a flashlight in your face 25 Tuesday, October 22, 13
  • 33.
  • 34.
  • 35.
    Levels of Proficiency Level1 Level 2 Level 3 Level 4 28 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 36.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Level 3 Level 4 29 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 37.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Going to the party "Where is the party?" "How do I get to the party?" Level 3 Level 4 30 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 38.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Going to the party "Where is the party?" "How do I get to the party?" Level 3 Discussing the party "What happened at the party last night?" Level 4 31 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 39.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Going to the party "Where is the party?" "How do I get to the party?" Level 3 Discussing the party "What happened at the party last night?" Level 4 Charlie Rose "Should parties be illegal?" 32 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 40.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Going to the party "Where is the party?" "How do I get to the party?" Level 3 Discussing the party "What happened at the party last night?" Level 4 Charlie Rose "Should parties be illegal?" 33 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 41.
    Levels of Proficiency Level1 Tarzan at a party “Beer!” “Good party.” Level 2 Going to the party "Where is the party?" "How do I get to the party?" 34 Tuesday, October 22, 13 http://www.jamesshore.com/Blog/Proficiencies-of-Planning.html
  • 42.
  • 43.
  • 44.
    Production Rails Code Usedwith: • Permission 36 Tuesday, October 22, 13
  • 45.
    Production Rails Code Usedwith: • Permission • Obfuscation 36 Tuesday, October 22, 13
  • 46.
    Production Rails Code Usedwith: • Permission • Obfuscation • Respect 36 Tuesday, October 22, 13
  • 47.
  • 48.
    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 Tuesday, October 22, 13 38
  • 49.
    Observations 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 Tuesday, October 22, 13 39
  • 50.
    Observations 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 ~800 lines in file # lots more stuff... end Tuesday, October 22, 13 39
  • 51.
    Observations 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 ~800 lines in file ~50 lines in method # lots more stuff... end Tuesday, October 22, 13 39
  • 52.
    Observations 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 ~800 lines in file ~50 lines in method Longest line: 177 chars # lots more stuff... end Tuesday, October 22, 13 39
  • 53.
    Observations 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 ~800 lines in file ~50 lines in method Longest line: 177 chars Indentation: 4-16 spaces # lots more stuff... end Tuesday, October 22, 13 39
  • 54.
    Observations 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 ~800 lines in file ~50 lines in method Longest line: 177 chars Indentation: 4-16 spaces Nested control structures: # lots more stuff... end Tuesday, October 22, 13 39
  • 55.
    Observations 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 ~800 lines in file ~50 lines in method Longest line: 177 chars Indentation: 4-16 spaces Nested control structures: audit_trail_for # lots more stuff... end Tuesday, October 22, 13 39
  • 56.
    Observations 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 ~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 # lots more stuff... end Tuesday, October 22, 13 39
  • 57.
    Observations 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 ~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 # lots more stuff... end Tuesday, October 22, 13 39
  • 58.
  • 59.
    Ship it! 41 Tuesday, October22, 13 http://shipitsquirrel.github.io/
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
    Make the JobSmaller 44 Tuesday, October 22, 13
  • 65.
    Replace Method with MethodObject See also: Katrina Owen, “Therapeutic Refactoring” 45 Tuesday, October 22, 13
  • 66.
    class InstallationsController < ActionController::Base defschedule # LOTS OF CODE end end 46 Tuesday, October 22, 13
  • 67.
    class InstallationsController < ActionController::Base defschedule # LOTS OF CODE end end class ScheduleInstallation def call end end 47 Tuesday, October 22, 13
  • 68.
    class InstallationsController < ActionController::Base defschedule end end class ScheduleInstallation def call # LOTS OF CODE end end 47 Tuesday, October 22, 13
  • 69.
    class InstallationsController < ActionController::Base defschedule ScheduleInstallation.new.call end end class ScheduleInstallation def call # LOTS OF CODE end end 47 Tuesday, October 22, 13
  • 70.
  • 71.
    class def # # # # end end ScheduleInstallation call LOTS OF CODE ...params ... ... render ... ... redirect_to ... 49 Tuesday, October 22, 13
  • 72.
    class ScheduleInstallation def initialize(controller) @controller= controller end def # # # # end end call LOTS OF CODE ... params ... ... render ... ... redirect_to ... 50 Tuesday, October 22, 13
  • 73.
    class ScheduleInstallation def initialize(controller) @controller= controller end def # # # # end end call LOTS OF CODE ... @controller.params ... ... @controller.render ... ... @controller.redirect_to ... 51 Tuesday, October 22, 13
  • 74.
    class ScheduleInstallation def initialize(controller) @controller= controller end extend Forwardable def_delegators :@controller, :params, :render, :redirect_to def # # # # end end call LOTS OF CODE ... params ... ... render ... ... redirect_to ... 52 Tuesday, October 22, 13
  • 75.
    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) end end 53 Tuesday, October 22, 13
  • 76.
  • 77.
    if request.xhr? # ...20lines... else # ...22 lines... end 55 Tuesday, October 22, 13
  • 78.
    if request.xml_http_request? # ...20lines... else # ...22 lines... end 56 Tuesday, October 22, 13
  • 79.
    if request.xml_http_request? begin #... end else # ...22lines... end 57 Tuesday, October 22, 13
  • 80.
    if request.xml_http_request? begin if @installation.pending_credit_check? render:json => #... return end #... end else # ...22 lines... end 58 Tuesday, October 22, 13
  • 81.
    if request.xml_http_request? begin if @installation.pending_credit_check? render:json => #... return end #... end else # ...22 lines... end 58 Tuesday, October 22, 13
  • 82.
    if request.xml_http_request? begin if @installation.pending_credit_check? render:json => #... return end #... Guard Clause end -Smalltalk Best Practice Patterns else by Kent Beck # ...22 lines... end 58 Tuesday, October 22, 13
  • 83.
    if request.xhr? begin if @installation.pending_credit_check? render:json => #... return end #... end else if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => end begin #... end end 59 Tuesday, October 22, 13
  • 84.
    tion.city_id, :view =>"calendar") and return 59 Tuesday, October 22, 13
  • 85.
    if request.xhr? begin if @installation.pending_credit_check? render:json => #... return end #... end else if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => return end begin #... end 60 Tuesday, October 22, 13
  • 86.
    if request.xhr? if request.xhr? begin if@installation.pend if @installation.pending_credit_check? #.. render :json => render :json => #... return return end end begin #... #... end end else else if @installation.pending_credit_check? if @installation.pend flash[:error] = #... flash[:error] = #.. redirect_to installations_path(:city_id => redirect_to install return return end end begin begin #... #... end end 60 Tuesday, October 22, 13
  • 87.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end begin #... end else if @installation.pending_credit_check? flash[:error] = #... redirect_to installations_path(:city_id => return end begin #... end 61 Tuesday, October 22, 13
  • 88.
    if request.xhr? if request.xhr? if@installation.pending_credit_check? if @installation.pend render :json => #... render :json => #.. return return end end begin else #... if @installation.pend end flash[:error] = #.. else redirect_to #... if @installation.pending_credit_check? return flash[:error] = #... end redirect_to installations_path(:city_id => end return end if request.xhr? begin begin #... #... end end 61 Tuesday, October 22, 13
  • 89.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 62 Tuesday, October 22, 13
  • 90.
  • 91.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 64 Tuesday, October 22, 13
  • 92.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 64 Tuesday, October 22, 13
  • 93.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 64 Tuesday, October 22, 13
  • 94.
    Flatten Nested Conditionals source: Michael Feathers inDr. Dobbs 65 Tuesday, October 22, 13
  • 95.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 66 Tuesday, October 22, 13
  • 96.
    if ajax if nope render:json => #... return end else if nope flash[:error] = #... redirect_to #... return end end 67 Tuesday, October 22, 13
  • 97.
    if ajax if nope render:json => #... return end else if nope flash[:error] = #... redirect_to #... return end end 67 Tuesday, October 22, 13 ajax nope TRUE TRUE ajax nope FALSE TRUE
  • 98.
    if ajax if nope render:json => #... return end else if nope flash[:error] = #... redirect_to #... return end end 68 Tuesday, October 22, 13
  • 99.
    if ajax if ajax ifnope if nope render :json => #... render :json => #.. return return end end else end if nope if not ajax flash[:error] = #... if nope redirect_to #... flash[:error] = #.. return redirect_to #... end return end end end 68 Tuesday, October 22, 13
  • 100.
    if ajax if nope render:json => #... return end end if not ajax if nope flash[:error] = #... redirect_to #... return end end 69 Tuesday, October 22, 13
  • 101.
    if ajax if ajax&& nope if nope render :json => #... render :json => #... return return end end if (not ajax) && nope end flash[:error] = #... if not ajax redirect_to #... if nope return flash[:error] = #...end redirect_to #... return end end 69 Tuesday, October 22, 13
  • 102.
    if ajax &&nope render :json => #... return end if (not ajax) && nope flash[:error] = #... redirect_to #... return end 70 Tuesday, October 22, 13
  • 103.
    if ajax &&nope render :json => #... return end if (not ajax) && nope flash[:error] = #... redirect_to #... return end 70 Tuesday, October 22, 13
  • 104.
    if ajax &&nope render :json => #... return end if (not ajax) && nope flash[:error] = #... redirect_to #... return end if nope if ajax render :json => #.. return end if not ajax flash[:error] = #.. redirect_to #... return end end 70 Tuesday, October 22, 13
  • 105.
    if nope if ajax render:json => #... return end if not ajax flash[:error] = #... redirect_to #... return end end 71 Tuesday, October 22, 13
  • 106.
    if nope if nope ifajax if ajax render :json => #... render :json => #.. return return end else if not ajax flash[:error] = #.. flash[:error] = #... redirect_to #... redirect_to #... return return end end end end 71 Tuesday, October 22, 13
  • 107.
    if nope if ajax render:json => #... return else flash[:error] = #... redirect_to #... return end end 72 Tuesday, October 22, 13
  • 108.
    if nope if nope ifajax if ajax render :json => #... render :json => #.. return else else flash[:error] = #.. flash[:error] = #... redirect_to #... redirect_to #... end return return end end end 72 Tuesday, October 22, 13
  • 109.
    if request.xhr? if @installation.pending_credit_check? render:json => #... return end else if @installation.pending_credit_check? flash[:error] = #... redirect_to #... return end end 73 Tuesday, October 22, 13
  • 110.
    if request.xhr? if @installation.pendin if@installation.pending_credit_check? if request.xhr? render :json => #... render :json => #.. return else end flash[:error] = #.. else redirect_to #... if @installation.pending_credit_check? end flash[:error] = #... return redirect_to #... end return end end 73 Tuesday, October 22, 13
  • 111.
    if @installation.pending_credit_check? if request.xhr? render:json => #... else flash[:error] = #... redirect_to #... end return end 74 Tuesday, October 22, 13
  • 112.
    if @installation.pendin if @installation.pending_credit_check? cant_schedule_while_c ifrequest.xhr? render :json => #... return end else flash[:error] = #... redirect_to #... end return end 74 Tuesday, October 22, 13
  • 113.
  • 114.
  • 115.
    class InstallationsController <ActionController::Base 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 end 77 Tuesday, October 22, 13
  • 116.
    class InstallationsController <ActionController::Base 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 end class ScheduleInstallation def call if @installation.pending_c cant_schedule_while_cred return end 77 Tuesday, October 22, 13 audit_trail_for(current_us if schedule! if @installation.sched scheduling_succeeded end do_post_success_cleanu else scheduling_failed end end rescue => e handle_exception e end end
  • 117.
    class ScheduleInstallation def call if@installation.pending_credit_check? cant_schedule_while_credit_check_pending return end 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 => e handle_exception e end end 78 Tuesday, October 22, 13
  • 118.
    class ScheduleInstallation def call if@installation.pending_credit_check? cant_schedule_while_credit_check_pending return end 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 => e handle_exception e end end request.xhr? 79 Tuesday, October 22, 13
  • 119.
    class ScheduleInstallation def call if@installation.pending_credit_check? cant_schedule_while_credit_check_pending return end 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 => e handle_exception e end end request.xhr? 79 Tuesday, October 22, 13
  • 120.
  • 121.
    def cannot_schedule_while_#... if request.xhr? #...1 line... else # ...2 lines... end end def scheduling_failed 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 do_post_success_cleanup if request.xhr? # DO NOTHING else # ...1 line... end end def scheduling_succeeded if request.xhr? # ...2 lines... else # ...5 lines... end end 81 Tuesday, October 22, 13
  • 122.
    def cannot_schedule_while_#... if request.xhr? #...1 line... else # ...2 lines... end end def scheduling_failed 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 do_post_success_cleanup if request.xhr? # DO NOTHING else # ...1 line... end end def scheduling_succeeded if request.xhr? # ...2 lines... else # ...5 lines... end end 81 Tuesday, October 22, 13
  • 123.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 124.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 125.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 126.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 127.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 128.
    class ScheduleInstallation def scheduling_failed ifrequest.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 129.
    Single Responsibility Principle (SRP forshort) 83 Tuesday, October 22, 13
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
    class ScheduleInstallation class ScheduleInstallat defcall def call end private class Responder def cannot_schedule_while_credit_check_pendin def cannot_schedule_w def handle_exception(e) def handle_exception( def scheduling_failed def scheduling_failed def scheduling_succeededdef scheduling_succee def do_post_success_cleanup do_post_success_c def end end class Responder end 90 Tuesday, October 22, 13
  • 142.
  • 143.
    if request.xhr? # dothis else # do that end Tuesday, October 22, 13
  • 144.
  • 145.
    class def def def def def end Tuesday, October 22,13 Responder cannot_schedule_while_credit_check_pending handle_exception(e) scheduling_failed scheduling_succeeded do_post_success_cleanup
  • 146.
    class def def def def def end Responder class AJAXResponder cannot_schedule_while_credit_check_pending def handle_exception(e) cannot_schedule_while_cre scheduling_failed defhandle_exception(e) scheduling_succeeded def scheduling_failed do_post_success_cleanup scheduling_succeede def def do_post_success_cle end class HTMLResponder def cannot_schedule_while_cre def handle_exception(e) def scheduling_failed def scheduling_succeede def do_post_success_cle end Tuesday, October 22, 13
  • 147.
    class InstallationsController < ActionController::Base defschedule responder = request.xhr? ? AJAXResponder.new(self) : HTMLResponder.new(self) ScheduleInstallation.new(responder).call end end Tuesday, October 22, 13
  • 148.
    class InstallationsController < ActionController::Base defschedule responder = request.xhr? ? AJAXResponder.new(self) : HTMLResponder.new(self) ScheduleInstallation.new(responder).call end end Tuesday, October 22, 13
  • 149.
    class InstallationsController < ActionController::Base defschedule responder = request.xhr? ? AJAXResponder.new(self) : HTMLResponder.new(self) ScheduleInstallation.new(responder).call end end Tuesday, October 22, 13
  • 150.
    class AJAXResponder def scheduling_failed ifrequest.xhr? render :json => #... else flash[:error] = #... redirect_to #... end end end class HTMLResponder def scheduling_failed if request.xhr? render :json => #... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 151.
    class AJAXResponder def scheduling_failed ifrequest.xhr? render :json => #... else flash[:error] = #... redirect_to #... end end end class HTMLResponder def scheduling_failed if request.xhr? render :json => #... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13 class AJAXResponder def scheduling_failed render :json => #... end end class HTMLResponder def scheduling_failed flash[:error] = #... redirect_to #... end end
  • 152.
    class InstallationsController < ActionController::Base defschedule responder = request.xhr? ? AJAXResponder.new(self) : HTMLResponder.new(self) ScheduleInstallation.new(responder).call end end Tuesday, October 22, 13
  • 153.
    Where Do WeGo From Here? 98 http://gomakemeasandwich.wordpress.com/2011/10/26/a-yeaf-of-gmmas-where-do-we-go-from-here/ Tuesday, October 22, 13
  • 154.
    99 Tuesday, October 22,13 http://www.poodr.info/
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
    Throw Your WorkAway 105 Tuesday, October 22, 13
  • 161.
    Speed Up YourTests! 106 Tuesday, October 22, 13
  • 162.
    Speed Up YourTests! See also: Katrina Owen, “Therapeutic Refactoring” (srsly) 106 Tuesday, October 22, 13
  • 163.
    I work atLivingSocial. We’re hiring. 107 Tuesday, October 22, 13
  • 164.
    I work atLivingSocial. We’re hiring. (Who isn’t?) 107 Tuesday, October 22, 13
  • 165.
    Thanks to: Jim Shoreand Diana Larsen for “Agile Fluency” Kirsten Comandich Sandi Metz, Katrina Owen, Sonia Connolly PDX.rb 108 Tuesday, October 22, 13
  • 166.
  • 167.