Refactoring

113
Refactoring { :from => :mess, :to => :clean_code, :through => :patterns } Orlando Ruby User Group January 2010 @caike http://caikesouza.com Friday, January 15, 2010

description

Talk at the Orlando Ruby User Group on January 2010 about Refactoring.

Transcript of Refactoring

Page 1: Refactoring

Refactoring{ :from => :mess, :to => :clean_code, :through => :patterns }

Orlando Ruby User GroupJanuary 2010

@caikehttp://caikesouza.com

Friday, January 15, 2010

Page 2: Refactoring

Agile

Friday, January 15, 2010

Page 3: Refactoring

Testing

Friday, January 15, 2010

Page 4: Refactoring

Patterns

Friday, January 15, 2010

Page 5: Refactoring

Professionalism

Friday, January 15, 2010

Page 6: Refactoring

Software Craftsmanship

Friday, January 15, 2010

Page 7: Refactoring

?Friday, January 15, 2010

Page 8: Refactoring

http://www.flickr.com/photos/eurleif/255241547/

Friday, January 15, 2010

Page 9: Refactoring

"Any fool can write code that a computer can understand.

Good programmers write code that humans can understand"

(Martin Fowler)

Friday, January 15, 2010

Page 10: Refactoring

“Free software only matters to those who can read”

(Robert M. Lefkowitz)

Friday, January 15, 2010

Page 11: Refactoring

Friday, January 15, 2010

Page 12: Refactoring

http://www.flickr.com/photos/dhammza/91435718/

Friday, January 15, 2010

Page 13: Refactoring

Given messy code that worksWhen I refactor

Then it should be easier to understandAnd still work!

Friday, January 15, 2010

Page 14: Refactoring

Cleaning up the house

Friday, January 15, 2010

Page 15: Refactoring

http://www.flickr.com/photos/improveit/1574023621/

http://www.flickr.com/photos/benfrantzdale/208672143/

Friday, January 15, 2010

Page 16: Refactoring

wiki, Fit, JUnit

eXtreme Programming

http://www.flickr.com/photos/improveit/1574023621/

http://www.flickr.com/photos/benfrantzdale/208672143/

Friday, January 15, 2010

Page 17: Refactoring

Friday, January 15, 2010

Page 18: Refactoring

http://www.flickr.com/photos/adewale_oshineye/2933030620

Friday, January 15, 2010

Page 19: Refactoring

Some reasons...

Friday, January 15, 2010

Page 20: Refactoring

Design++

Friday, January 15, 2010

Page 21: Refactoring

Money++

Friday, January 15, 2010

Page 22: Refactoring

Money++Respond to changes

Friday, January 15, 2010

Page 23: Refactoring

Money++Respond to changes

Release with confidence

Friday, January 15, 2010

Page 24: Refactoring

Effort--

Friday, January 15, 2010

Page 25: Refactoring

Jan Feb Mar Apr May Jun Jul

Cost of Maintenance

Waterfall

Extreme Programming Explained: Embrace ChangeAddison Wesley, 2000

Friday, January 15, 2010

Page 26: Refactoring

Jan Feb Mar Apr May Jun Jul

Cost of Maintenance Extreme Programming Explained: Embrace ChangeAddison Wesley, 2000

XP

Friday, January 15, 2010

Page 27: Refactoring

http://www.flickr.com/photos/x180/503574487/

code LESSsleep MORE

Friday, January 15, 2010

Page 28: Refactoring

http://www.flickr.com/photos/rockinrob/1485573200/

Friday, January 15, 2010

Page 29: Refactoring

When ?

Friday, January 15, 2010

Page 30: Refactoring

When you add a function

Friday, January 15, 2010

Page 31: Refactoring

When you fix a bug

Friday, January 15, 2010

Page 32: Refactoring

Code Reviews

Friday, January 15, 2010

Page 33: Refactoring

http://www.flickr.com/photos/highwayoflife/2699887178/

Friday, January 15, 2010

Page 34: Refactoring

Code Smells

Friday, January 15, 2010

Page 35: Refactoring

Code Smells

Duplicated Code

Friday, January 15, 2010

Page 36: Refactoring

Long Method

Duplicated Code

Code Smells

Friday, January 15, 2010

Page 37: Refactoring

Duplicated Code

Long Method

Large ClassCode Smells

Friday, January 15, 2010

Page 38: Refactoring

Duplicated Code

Long Method

Divergent ChangeLarge ClassCode Smells

Friday, January 15, 2010

Page 39: Refactoring

Duplicated Code

Long Method

Divergent ChangeLarge Class

Long ParameterList

Code Smells

Friday, January 15, 2010

Page 40: Refactoring

Test Driven Development

Friday, January 15, 2010

Page 41: Refactoring

RedGreen

Refactor

Friday, January 15, 2010

Page 42: Refactoring

What if I Don’t ?

Friday, January 15, 2010

Page 43: Refactoring

Debt Metaphor

Friday, January 15, 2010

Page 44: Refactoring

http://www.flickr.com/photos/benfrantzdale/208672143/

Friday, January 15, 2010

Page 45: Refactoring

http://www.flickr.com/photos/didmyself/3050138294/

Friday, January 15, 2010

Page 46: Refactoring

Get ready for code!

Friday, January 15, 2010

Page 47: Refactoring

managers = []

employees.each do |e| managers << e if e.is_manager?end

Saturday, January 16, 2010

Page 48: Refactoring

managers = []

employees.each do |e| managers << e if e.is_manager?end

Saturday, January 16, 2010

Page 49: Refactoring

Replace Loop withClosure Method

Saturday, January 16, 2010

Page 50: Refactoring

managers = []

employees.each do |e| managers << e if e.is_manager?end

Saturday, January 16, 2010

Page 51: Refactoring

managers = employees. select { |e| e.is_manager? }

Saturday, January 16, 2010

Page 52: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? ((@stars > 5) ? 8 : 1) >= 8 endend

Saturday, January 16, 2010

Page 53: Refactoring

http://www.flickr.com/photos/anirudhkoul/3804552280/

Saturday, January 16, 2010

Page 54: Refactoring

http://www.bartcop.com/marilyn-monroe001.jpg

Saturday, January 16, 2010

Page 55: Refactoring

http://thetorchonline.com/wp-content/uploads/2009/04/deathstar.jpg

Saturday, January 16, 2010

Page 56: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? ((@stars > 5) ? 8 : 1) >= 8 endend

Saturday, January 16, 2010

Page 57: Refactoring

Introduce ExplainingVariable

Saturday, January 16, 2010

Page 58: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? ((@stars > 5) ? 8 : 1) >= 8 endend

Saturday, January 16, 2010

Page 59: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? rating = (@stars > 5) ? 8 : 1 rating >= 8 endend

Saturday, January 16, 2010

Page 60: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? rating = (@stars > 5) ? 8 : 1 rating >= 8 endend

Saturday, January 16, 2010

Page 61: Refactoring

Replace TempWith Query

Saturday, January 16, 2010

Page 62: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? rating = (@stars > 5) ? 8 : 1 rating >= 8 endend

Saturday, January 16, 2010

Page 63: Refactoring

class Movie def initialize(stars) @stars = stars end def recommended? rating >= 8 end

def rating (@stars > 5) ? 8 : 1 end end

Saturday, January 16, 2010

Page 64: Refactoring

OMG,This is sooooo cooooool!

Saturday, January 16, 2010

Page 65: Refactoring

class Movie

def recommended? rating >= 8 end

def rating (@stars > 5) ? 8 : 1 end end

Saturday, January 16, 2010

Page 66: Refactoring

class Movie

def recommended? rating >= 8 end

def rating more_than_five_stars? ? 8 : 1 end

def more_than_five_stars? @stars > 5 end end

Saturday, January 16, 2010

Page 67: Refactoring

Inline Method

Saturday, January 16, 2010

Page 68: Refactoring

class Movie def initialize...end def recommended? rating >= 8 end

def rating more_than_five_stars? ? 8 : 1 end

def more_than_five_stars? @stars > 5 end end

Saturday, January 16, 2010

Page 69: Refactoring

class Movie def initialize...end def recommended? rating >= 8 end

def rating @stars > 5 ? 8 : 1 end

endSaturday, January 16, 2010

Page 70: Refactoring

mock = mock('user')expectation = mock.expects(:find)expectation.with("1")expectation.returns([])

Saturday, January 16, 2010

Page 71: Refactoring

mock = mock('user')expectation = mock.expects(:find)expectation.with("1")expectation.returns([])

Saturday, January 16, 2010

Page 72: Refactoring

Replace TempWith Chain

Saturday, January 16, 2010

Page 73: Refactoring

mock = mock('user')expectation = mock.expects(:find)expectation.with("1")expectation.returns([])

Saturday, January 16, 2010

Page 74: Refactoring

mock = mock('user')mock.expects(:find).with("1"). returns([])

Saturday, January 16, 2010

Page 75: Refactoring

def expects ... selfend

def with ... selfend

def returns ... selfend

Saturday, January 16, 2010

Page 76: Refactoring

def charge(amount, ccnumber) begin conn = CC_Charger_Server.connect(...) conn.send(amount, ccnumber) rescue IOError => e Logger.log "Error: #{e}" return nil ensure conn.close endend

Saturday, January 16, 2010

Page 77: Refactoring

def charge(amount, ccnumber) begin conn = CC_Charger_Server.connect(...) conn.send(amount, ccnumber) rescue IOError => e Logger.log "Error: #{e}" return nil ensure conn.close endend

Saturday, January 16, 2010

Page 78: Refactoring

Extract SurroundingMethod

Saturday, January 16, 2010

Page 79: Refactoring

def charge(amount, ccnumber) begin conn = CC_Charger_Server.connect(...) conn.send(amount, ccnumber) rescue IOError => e Logger.log "Error: #{e}" return nil ensure conn.close endend

Saturday, January 16, 2010

Page 80: Refactoring

def charge(amount, ccnumber) connect do |conn| conn.send(amount, ccnumber) endend

Saturday, January 16, 2010

Page 81: Refactoring

def connect begin conn = CC_Charger_Server.connect(...) yield conn rescue IOError => e Logger.log "Error: #{e}" return nil ensure conn.close endend

Saturday, January 16, 2010

Page 82: Refactoring

def body_fat_percentage(name, age, height, weight, metric_system) ...end

Saturday, January 16, 2010

Page 83: Refactoring

body_fat_percentage("fred", 30, 1.82, 90, 1)body_fat_percentage("joe", 32, 6, 220, 2)

Saturday, January 16, 2010

Page 84: Refactoring

body_fat_percentage("fred", 30, 1.82, 90, 1)body_fat_percentage("joe", 32, 6, 220, 2)

Saturday, January 16, 2010

Page 85: Refactoring

Introduce Named Parameter

Saturday, January 16, 2010

Page 86: Refactoring

def body_fat_percentage(name, age, height, weight, metric_system) ...end

Saturday, January 16, 2010

Page 87: Refactoring

def body_fat_percentage(name, params={}) # params[:age] # params[:height] # params[:weight] # params[:metric_system]end

Saturday, January 16, 2010

Page 88: Refactoring

body_fat_percentage("fred", 30, 1.82, 90, 1)body_fat_percentage("joe", 32, 6, 220, 2)

Saturday, January 16, 2010

Page 89: Refactoring

body_fat_percentage("fred", :age => 30, :height => 1.82, :weight => 90, MetricSystem::METERS_KG)

body_fat_percentage("joe", :age => 32, :height => 6, :weight => 220, MetricSystem::FEET_LB)

Saturday, January 16, 2010

Page 90: Refactoring

user.posts.paginate(:page => params[:page], :per_page => params[:per_page] || 15)

Saturday, January 16, 2010

Page 91: Refactoring

user.posts.paginate(:page => params[:page], :per_page => params[:per_page] || 15)

Saturday, January 16, 2010

Page 92: Refactoring

Replace Magic Number with Symbolic Constant

Saturday, January 16, 2010

Page 93: Refactoring

user.posts.paginate(:page => params[:page], :per_page => params[:per_page] || 15)

Saturday, January 16, 2010

Page 94: Refactoring

CONTACTS_PER_PAGE = 15

user.posts.paginate(:page => params[:page], :per_page => params[:per_page] || CONTACTS_PER_PAGE)

Saturday, January 16, 2010

Page 95: Refactoring

class MountainBike def price ... endend

MountainBike.new(:type => :rigid, ...)MountainBike.new(:type => :front_suspension, ...)MountainBike.new(:type => :full_suspension, ...)

Saturday, January 16, 2010

Page 96: Refactoring

def price if @type_code == :rigid (1 + @comission) * @base_price end if @type_code == :font_suspension (1 + @comission) * @base_price + @front_suspension_price end if @type_code == :full_suspension (1 + @comission) * @base_price+ @front_suspension_price + @rear_suspension_price

end

endSaturday, January 16, 2010

Page 97: Refactoring

def price if @type_code == :rigid (1 + @comission) * @base_price end

if @type_code == :font_suspension (1 + @comission) * @base_price + @front_suspension_priceend if @type_code == :full_suspension (1 + @comission) * @base_price+

@front_suspension_price + @rear_suspension_price

end if @type_code == :ultra_suspension ... end end

Saturday, January 16, 2010

Page 98: Refactoring

Saturday, January 16, 2010

Page 99: Refactoring

Replace ConditionalWith Polymorphism

Saturday, January 16, 2010

Page 100: Refactoring

class MountainBike def price ... endend

Saturday, January 16, 2010

Page 101: Refactoring

module MountainBike def price ... endend

Saturday, January 16, 2010

Page 102: Refactoring

class RigidMountainBike include MountainBikeend

class FrontSuspensionMountainBike include MountainBikeend

class FullSuspensionMountainBike include MountainBikeend

Saturday, January 16, 2010

Page 103: Refactoring

RigidMountainBike.new(:type => :rigid, ...)

FrontSuspensionMountainBike.new(:type => :front_suspension, ...)

FullSuspensionMountainBike.new(:type => :full_suspension, ...)

Saturday, January 16, 2010

Page 104: Refactoring

class RigidMountainBike include MountainBike

def price (1 + @comission) * @base_price endend

Saturday, January 16, 2010

Page 105: Refactoring

def price if @type_code == :rigid raise "should not be called" end if @type_code == :font_suspension (1 + @comission) * @base_price + @front_suspension_price end if @type_code == :full_suspension (1 + @comission) * @base_price+ @front_suspension_price + @rear_suspension_price

end end

Saturday, January 16, 2010

Page 106: Refactoring

class FrontSuspensionMountainBike include MountainBike def price (1 + @comission) * @base_price + @front_suspension_price end end

class FullSuspensionMountainBike include MountainBike def price (1 + @comission) * @base_price + @front_suspension_price + @rear_suspension_price endend

Saturday, January 16, 2010

Page 107: Refactoring

def price if @type_code == :rigid raise "should not be called" end if @type_code == :font_suspension raise "should not be called" end if @type_code == :full_suspension raise "should not be called" end end

Saturday, January 16, 2010

Page 108: Refactoring

def price if @type_code == :rigid raise "should not be called" end if @type_code == :font_suspension raise "should not be called" end if @type_code == :full_suspension raise "should not be called" end end

Saturday, January 16, 2010

Page 109: Refactoring

class RigidMountainBike include MountainBikeend

class FrontSuspensionMountainBike include MountainBikeend

class FullSuspensionMountainBike include MountainBikeend

Saturday, January 16, 2010

Page 110: Refactoring

Only the beginning...Saturday, January 16, 2010

Page 111: Refactoring

http://www.flickr.com/photos/el_ser_lomo/3267627038/

Coding Dojo

http://orlandodojo.wordpress.com/http://groups.google.com/group/orlando-dojo/

Saturday, January 16, 2010

Page 112: Refactoring

Saturday, January 16, 2010

Page 113: Refactoring

Thank you!@caike

http://caikesouza.com

Saturday, January 16, 2010