SlideShare uma empresa Scribd logo
1 de 167
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015
Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015
Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015Sergii Khomenko
 
Clearance: Simple, complete Ruby web app authentication.
Clearance: Simple, complete Ruby web app authentication.Clearance: Simple, complete Ruby web app authentication.
Clearance: Simple, complete Ruby web app authentication.Jason Morrison
 
Yes, browsers can do that! Hybrid and future web meetup at Jayway
Yes, browsers can do that! Hybrid and future web meetup at JaywayYes, browsers can do that! Hybrid and future web meetup at Jayway
Yes, browsers can do that! Hybrid and future web meetup at JaywayChristian Heilmann
 
Scalable vector ember
Scalable vector emberScalable vector ember
Scalable vector emberMatthew Beale
 
To Err Is Human
To Err Is HumanTo Err Is Human
To Err Is HumanAlex Liu
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of CodeJoe Morgan
 
Taking the pain out of signing users in
Taking the pain out of signing users inTaking the pain out of signing users in
Taking the pain out of signing users inFrancois Marier
 
Passwords and freedom: can we lose the former and retain the latter?
Passwords and freedom: can we lose the former and retain the latter?Passwords and freedom: can we lose the former and retain the latter?
Passwords and freedom: can we lose the former and retain the latter?Francois Marier
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wildJoe Morgan
 
TicketBEKA? Ticket booking
TicketBEKA? Ticket bookingTicketBEKA? Ticket booking
TicketBEKA? Ticket bookingLikhith Pujari
 
JavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New WorldJavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New WorldRobert Nyman
 
Persona: a federated and privacy-protecting login system for the whole Web
Persona: a federated and privacy-protecting login system for the whole WebPersona: a federated and privacy-protecting login system for the whole Web
Persona: a federated and privacy-protecting login system for the whole WebFrancois Marier
 
Vidéo approche en immobilier
Vidéo approche en immobilierVidéo approche en immobilier
Vidéo approche en immobilierhervepouliot
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In RailsLouie Zhao
 
Social media mashup website's
Social media mashup website'sSocial media mashup website's
Social media mashup website'sMathias Vissers
 
JQuery in Seaside
JQuery in SeasideJQuery in Seaside
JQuery in SeasideESUG
 

Mais procurados (20)

Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015
Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015
Helping Data Teams with Puppet / Puppet Camp London - Apr 13, 2015
 
Clearance: Simple, complete Ruby web app authentication.
Clearance: Simple, complete Ruby web app authentication.Clearance: Simple, complete Ruby web app authentication.
Clearance: Simple, complete Ruby web app authentication.
 
Ruby Robots
Ruby RobotsRuby Robots
Ruby Robots
 
Yes, browsers can do that! Hybrid and future web meetup at Jayway
Yes, browsers can do that! Hybrid and future web meetup at JaywayYes, browsers can do that! Hybrid and future web meetup at Jayway
Yes, browsers can do that! Hybrid and future web meetup at Jayway
 
Scalable vector ember
Scalable vector emberScalable vector ember
Scalable vector ember
 
To Err Is Human
To Err Is HumanTo Err Is Human
To Err Is Human
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of Code
 
Taking the pain out of signing users in
Taking the pain out of signing users inTaking the pain out of signing users in
Taking the pain out of signing users in
 
Passwords and freedom: can we lose the former and retain the latter?
Passwords and freedom: can we lose the former and retain the latter?Passwords and freedom: can we lose the former and retain the latter?
Passwords and freedom: can we lose the former and retain the latter?
 
ES6 patterns in the wild
ES6 patterns in the wildES6 patterns in the wild
ES6 patterns in the wild
 
TicketBEKA? Ticket booking
TicketBEKA? Ticket bookingTicketBEKA? Ticket booking
TicketBEKA? Ticket booking
 
JavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New WorldJavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New World
 
FuncUnit
FuncUnitFuncUnit
FuncUnit
 
Persona: a federated and privacy-protecting login system for the whole Web
Persona: a federated and privacy-protecting login system for the whole WebPersona: a federated and privacy-protecting login system for the whole Web
Persona: a federated and privacy-protecting login system for the whole Web
 
Vidéo approche en immobilier
Vidéo approche en immobilierVidéo approche en immobilier
Vidéo approche en immobilier
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
Social media mashup website's
Social media mashup website'sSocial media mashup website's
Social media mashup website's
 
jQuery quick tuts
jQuery quick tutsjQuery quick tuts
jQuery quick tuts
 
Php
PhpPhp
Php
 
JQuery in Seaside
JQuery in SeasideJQuery in Seaside
JQuery in Seaside
 

Destaque

Fluent Refactoring (Lone Star Ruby Conf 2013)
Fluent Refactoring (Lone Star Ruby Conf 2013)Fluent Refactoring (Lone Star Ruby Conf 2013)
Fluent Refactoring (Lone Star Ruby Conf 2013)Sam Livingston-Gray
 
Cucumbers Have Layers - RubyConf 2015
Cucumbers Have Layers - RubyConf 2015Cucumbers Have Layers - RubyConf 2015
Cucumbers Have Layers - RubyConf 2015Sam Livingston-Gray
 
Gruppo di famiglia in un interno facebook
Gruppo di famiglia in un interno facebookGruppo di famiglia in un interno facebook
Gruppo di famiglia in un interno facebookyuliy davidov
 
Scikit-Learn para MLLib: Machine Learning em Larga Escala
Scikit-Learn para MLLib: Machine Learning em Larga EscalaScikit-Learn para MLLib: Machine Learning em Larga Escala
Scikit-Learn para MLLib: Machine Learning em Larga EscalaGuilherme Peixoto
 
Analysis of the use of sound in previous
Analysis of the use of sound in previousAnalysis of the use of sound in previous
Analysis of the use of sound in previousEzgi Cicek
 
COMO PINTO ACRILICO
COMO PINTO ACRILICOCOMO PINTO ACRILICO
COMO PINTO ACRILICOveris1963
 
From the Big Bang to Ecommerce, a journey in making sense of Big Data
From the Big Bang to Ecommerce, a journey in making sense of Big DataFrom the Big Bang to Ecommerce, a journey in making sense of Big Data
From the Big Bang to Ecommerce, a journey in making sense of Big DataPatrick Deglon
 
DEFINICIÓN SOBRE EL AMOR
DEFINICIÓN SOBRE EL AMORDEFINICIÓN SOBRE EL AMOR
DEFINICIÓN SOBRE EL AMORAlquimista Aula
 
1. prepare usb installer
1.  prepare usb installer1.  prepare usb installer
1. prepare usb installerkris harden
 
Training & workshop lesson plan medea ocotber 21st 2014
Training & workshop lesson plan  medea ocotber 21st 2014 Training & workshop lesson plan  medea ocotber 21st 2014
Training & workshop lesson plan medea ocotber 21st 2014 Mr Bounab Samir
 
Bahasa Mandarin Dasar
Bahasa Mandarin DasarBahasa Mandarin Dasar
Bahasa Mandarin DasarDevy Riani
 

Destaque (19)

Fluent Refactoring (Lone Star Ruby Conf 2013)
Fluent Refactoring (Lone Star Ruby Conf 2013)Fluent Refactoring (Lone Star Ruby Conf 2013)
Fluent Refactoring (Lone Star Ruby Conf 2013)
 
Cucumbers Have Layers - RubyConf 2015
Cucumbers Have Layers - RubyConf 2015Cucumbers Have Layers - RubyConf 2015
Cucumbers Have Layers - RubyConf 2015
 
Tratado de Neuilly
Tratado de NeuillyTratado de Neuilly
Tratado de Neuilly
 
Gruppo di famiglia in un interno facebook
Gruppo di famiglia in un interno facebookGruppo di famiglia in un interno facebook
Gruppo di famiglia in un interno facebook
 
HRM Management Institute
HRM Management InstituteHRM Management Institute
HRM Management Institute
 
Scikit-Learn para MLLib: Machine Learning em Larga Escala
Scikit-Learn para MLLib: Machine Learning em Larga EscalaScikit-Learn para MLLib: Machine Learning em Larga Escala
Scikit-Learn para MLLib: Machine Learning em Larga Escala
 
JOMC slide deck
JOMC slide deckJOMC slide deck
JOMC slide deck
 
Intake 37 ef1
Intake 37 ef1Intake 37 ef1
Intake 37 ef1
 
Analysis of the use of sound in previous
Analysis of the use of sound in previousAnalysis of the use of sound in previous
Analysis of the use of sound in previous
 
COMO PINTO ACRILICO
COMO PINTO ACRILICOCOMO PINTO ACRILICO
COMO PINTO ACRILICO
 
Information Mapping (1)
Information Mapping (1)Information Mapping (1)
Information Mapping (1)
 
From the Big Bang to Ecommerce, a journey in making sense of Big Data
From the Big Bang to Ecommerce, a journey in making sense of Big DataFrom the Big Bang to Ecommerce, a journey in making sense of Big Data
From the Big Bang to Ecommerce, a journey in making sense of Big Data
 
Dilasa
DilasaDilasa
Dilasa
 
DEFINICIÓN SOBRE EL AMOR
DEFINICIÓN SOBRE EL AMORDEFINICIÓN SOBRE EL AMOR
DEFINICIÓN SOBRE EL AMOR
 
Affiches de la famille
Affiches de la familleAffiches de la famille
Affiches de la famille
 
1. prepare usb installer
1.  prepare usb installer1.  prepare usb installer
1. prepare usb installer
 
Training & workshop lesson plan medea ocotber 21st 2014
Training & workshop lesson plan  medea ocotber 21st 2014 Training & workshop lesson plan  medea ocotber 21st 2014
Training & workshop lesson plan medea ocotber 21st 2014
 
Bmw museum
Bmw museumBmw museum
Bmw museum
 
Bahasa Mandarin Dasar
Bahasa Mandarin DasarBahasa Mandarin Dasar
Bahasa Mandarin Dasar
 

Semelhante a Fluent Refactoring (Cascadia Ruby Conf 2013)

Slides changes symfony23
Slides changes symfony23Slides changes symfony23
Slides changes symfony23Javier López
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeWim Godden
 
GCRC 2014 - The Dark Side of Ruby
GCRC 2014 - The Dark Side of RubyGCRC 2014 - The Dark Side of Ruby
GCRC 2014 - The Dark Side of RubyGautam Rege
 
Ten Groovy Little JavaScript Tips
Ten Groovy Little JavaScript TipsTen Groovy Little JavaScript Tips
Ten Groovy Little JavaScript TipsTroy Miles
 
Ruby is Awesome
Ruby is AwesomeRuby is Awesome
Ruby is AwesomeAstrails
 
Drools and BRMS 6.0 (Dublin Aug 2013)
Drools and BRMS 6.0 (Dublin Aug 2013)Drools and BRMS 6.0 (Dublin Aug 2013)
Drools and BRMS 6.0 (Dublin Aug 2013)Mark Proctor
 
Puppet Camp London 2015 - Helping Data Teams with Puppet
Puppet Camp London 2015 - Helping Data Teams with PuppetPuppet Camp London 2015 - Helping Data Teams with Puppet
Puppet Camp London 2015 - Helping Data Teams with PuppetPuppet
 
Dtrace и немного магии
Dtrace и немного магииDtrace и немного магии
Dtrace и немного магииDan Kruchinin
 
Esoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in RubyEsoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in Rubymametter
 
Teaching Programming Online
Teaching Programming OnlineTeaching Programming Online
Teaching Programming OnlinePamela Fox
 
Beware: Sharp Tools
Beware: Sharp ToolsBeware: Sharp Tools
Beware: Sharp Toolschrismdp
 
Grow your own tools - VilniusRB
Grow your own tools - VilniusRBGrow your own tools - VilniusRB
Grow your own tools - VilniusRBRemigijus Jodelis
 
Intro to Clojure's core.async
Intro to Clojure's core.asyncIntro to Clojure's core.async
Intro to Clojure's core.asyncLeonardo Borges
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineAndy McKay
 
What Makes a Good Chef Cookbook? (May 2014 Edition)
What Makes a Good Chef Cookbook? (May 2014 Edition)What Makes a Good Chef Cookbook? (May 2014 Edition)
What Makes a Good Chef Cookbook? (May 2014 Edition)Julian Dunn
 
D3.js capita selecta
D3.js capita selectaD3.js capita selecta
D3.js capita selectaJoris Klerkx
 
An Introduction To jQuery
An Introduction To jQueryAn Introduction To jQuery
An Introduction To jQueryAndy Gibson
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeWim Godden
 

Semelhante a Fluent Refactoring (Cascadia Ruby Conf 2013) (20)

Slides changes symfony23
Slides changes symfony23Slides changes symfony23
Slides changes symfony23
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
 
GCRC 2014 - The Dark Side of Ruby
GCRC 2014 - The Dark Side of RubyGCRC 2014 - The Dark Side of Ruby
GCRC 2014 - The Dark Side of Ruby
 
Ten Groovy Little JavaScript Tips
Ten Groovy Little JavaScript TipsTen Groovy Little JavaScript Tips
Ten Groovy Little JavaScript Tips
 
Ruby is Awesome
Ruby is AwesomeRuby is Awesome
Ruby is Awesome
 
Drools and BRMS 6.0 (Dublin Aug 2013)
Drools and BRMS 6.0 (Dublin Aug 2013)Drools and BRMS 6.0 (Dublin Aug 2013)
Drools and BRMS 6.0 (Dublin Aug 2013)
 
Puppet Camp London 2015 - Helping Data Teams with Puppet
Puppet Camp London 2015 - Helping Data Teams with PuppetPuppet Camp London 2015 - Helping Data Teams with Puppet
Puppet Camp London 2015 - Helping Data Teams with Puppet
 
Czzawk
CzzawkCzzawk
Czzawk
 
Dtrace и немного магии
Dtrace и немного магииDtrace и немного магии
Dtrace и немного магии
 
Esoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in RubyEsoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in Ruby
 
Teaching Programming Online
Teaching Programming OnlineTeaching Programming Online
Teaching Programming Online
 
Beware: Sharp Tools
Beware: Sharp ToolsBeware: Sharp Tools
Beware: Sharp Tools
 
Grow your own tools - VilniusRB
Grow your own tools - VilniusRBGrow your own tools - VilniusRB
Grow your own tools - VilniusRB
 
Couchdb
CouchdbCouchdb
Couchdb
 
Intro to Clojure's core.async
Intro to Clojure's core.asyncIntro to Clojure's core.async
Intro to Clojure's core.async
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
 
What Makes a Good Chef Cookbook? (May 2014 Edition)
What Makes a Good Chef Cookbook? (May 2014 Edition)What Makes a Good Chef Cookbook? (May 2014 Edition)
What Makes a Good Chef Cookbook? (May 2014 Edition)
 
D3.js capita selecta
D3.js capita selectaD3.js capita selecta
D3.js capita selecta
 
An Introduction To jQuery
An Introduction To jQueryAn Introduction To jQuery
An Introduction To jQuery
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
 

Último

Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 

Último (20)

Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 

Fluent Refactoring (Cascadia Ruby Conf 2013)

  • 1. 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
  • 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
  • 9. Algebra Isn’t all of Math 9 Tuesday, October 22, 13
  • 15. Math is a Language 15 Tuesday, October 22, 13
  • 16. Math is a Language Algebra is [one of] its Grammar[s] 15 Tuesday, October 22, 13
  • 19. Can I get a definition? 17 http://www.kickasslabs.com/2012/04/28/rails-conf-2012-images/100_0304/ Tuesday, October 22, 13
  • 21. 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
  • 23. 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
  • 24. Re·fac·tor·ing (noun) A technique for restructuring code without changing behavior 20 Tuesday, October 22, 13
  • 25. Tell a clearer story 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
  • 29. Re·fac·tor·ing (noun) A language that describes ways to make your code suck less. 23 Tuesday, October 22, 13
  • 31. Flu·en·cy (noun) What you can say when you’re not thinking about how to say it 24 Tuesday, October 22, 13
  • 32. 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
  • 35. 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
  • 36. 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
  • 37. 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
  • 38. 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
  • 39. 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
  • 40. 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
  • 41. 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
  • 44. Production Rails Code Used with: • Permission 36 Tuesday, October 22, 13
  • 45. Production Rails Code Used with: • Permission • Obfuscation 36 Tuesday, October 22, 13
  • 46. Production Rails Code Used with: • Permission • Obfuscation • Respect 36 Tuesday, October 22, 13
  • 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
  • 59. Ship it! 41 Tuesday, October 22, 13 http://shipitsquirrel.github.io/
  • 64. Make the Job Smaller 44 Tuesday, October 22, 13
  • 65. Replace Method with Method Object See also: Katrina Owen, “Therapeutic Refactoring” 45 Tuesday, October 22, 13
  • 66. class InstallationsController < ActionController::Base def schedule # LOTS OF CODE end end 46 Tuesday, October 22, 13
  • 67. class InstallationsController < ActionController::Base def schedule # LOTS OF CODE end end class ScheduleInstallation def call end end 47 Tuesday, October 22, 13
  • 68. class InstallationsController < ActionController::Base def schedule end end class ScheduleInstallation def call # LOTS OF CODE end end 47 Tuesday, October 22, 13
  • 69. 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
  • 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
  • 77. if request.xhr? # ...20 lines... else # ...22 lines... end 55 Tuesday, October 22, 13
  • 78. if request.xml_http_request? # ...20 lines... else # ...22 lines... end 56 Tuesday, October 22, 13
  • 79. if request.xml_http_request? begin #... end else # ...22 lines... 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
  • 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 in Dr. 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 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
  • 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 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
  • 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 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
  • 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 if request.xhr? render :json => #... return end else flash[:error] = #... redirect_to #... end return end 74 Tuesday, October 22, 13
  • 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. Under The Rug 80 Tuesday, October 22, 13
  • 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 if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 124. class ScheduleInstallation def scheduling_failed if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 125. class ScheduleInstallation def scheduling_failed if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 126. class ScheduleInstallation def scheduling_failed if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 127. class ScheduleInstallation def scheduling_failed if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 128. class ScheduleInstallation def scheduling_failed if request.xhr? render :json => {:errors#... else flash[:error] = #... redirect_to #... end end end Tuesday, October 22, 13
  • 129. Single Responsibility Principle (SRP for short) 83 Tuesday, October 22, 13
  • 141. 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
  • 143. if request.xhr? # do this else # do that end Tuesday, October 22, 13
  • 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 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
  • 147. 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
  • 148. 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
  • 149. 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
  • 150. 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
  • 151. 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
  • 152. 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
  • 153. 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
  • 154. 99 Tuesday, October 22, 13 http://www.poodr.info/
  • 160. Throw Your Work Away 105 Tuesday, October 22, 13
  • 161. Speed Up Your Tests! 106 Tuesday, October 22, 13
  • 162. Speed Up Your Tests! See also: Katrina Owen, “Therapeutic Refactoring” (srsly) 106 Tuesday, October 22, 13
  • 163. I work at LivingSocial. We’re hiring. 107 Tuesday, October 22, 13
  • 164. I work at LivingSocial. We’re hiring. (Who isn’t?) 107 Tuesday, October 22, 13
  • 165. 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