refactoring workshop (rails pacific 2014)

34
REFACTORING WORKSHOP Bruce Li @ Rails Pacific 2014 Please clone this repo https://github.com/ascendbruce/refactoring-workshop run bundle install and Check your ruby version

Upload: bruce-li

Post on 28-Nov-2014

769 views

Category:

Software


2 download

DESCRIPTION

Refactoring Workshop (Rails Pacific 2014)

TRANSCRIPT

Page 1: Refactoring Workshop (Rails Pacific 2014)

REFACTORING WORKSHOPBruce Li @ Rails Pacific 2014

Please clone this repo https://github.com/ascendbruce/refactoring-workshop run bundle install and Check your ruby version

Page 2: Refactoring Workshop (Rails Pacific 2014)

ABOUT ME

• Li, Po-Chun a.k.a. Bruce Li

• Work at Techbang

• http://ascendbruce.logdown.com/

• @BruceToyRoom, @techbangtech

Page 3: Refactoring Workshop (Rails Pacific 2014)

REFACTORING

• Reduce maintenance cost

• Technical debt is not about technology. It’s about people

• programmer happiness is very important

is important

Page 4: Refactoring Workshop (Rails Pacific 2014)

TEST COVERAGE

• Confident in changes

• Code School, TeaLeaf are good start

• SimpleCov and CodeClimate can make you happier while repairing test cases

is important

Page 5: Refactoring Workshop (Rails Pacific 2014)

PRY

• gem "pry-rails"gem "pry-byebug" # or pry-debugger for ruby 1.9

• binding.pry # to entering debug mode

• Commands: next, step, break, continue, exit

• It’s all you need at first

is useful

Page 6: Refactoring Workshop (Rails Pacific 2014)

COMMENTS IN CODE

• Ideally, code should describe itself.

• Out-dated comments are worser than none. It’s actively misleading.

• Comments is helpful for providing additional information or link to issue tracking history.

is bad (in some cases)

Page 7: Refactoring Workshop (Rails Pacific 2014)

1. INTENTION REVEALING METHOD

• Add comments if code need it.

• Transform comments into methods.

• Comments are now code. Code describes itself.

Page 8: Refactoring Workshop (Rails Pacific 2014)
Page 9: Refactoring Workshop (Rails Pacific 2014)
Page 10: Refactoring Workshop (Rails Pacific 2014)
Page 11: Refactoring Workshop (Rails Pacific 2014)

user_is_admitted?

Page 12: Refactoring Workshop (Rails Pacific 2014)

user_is_admitted?

Page 13: Refactoring Workshop (Rails Pacific 2014)

user_is_admitted?

set_marketing_flash

Page 14: Refactoring Workshop (Rails Pacific 2014)

user_is_admitted?

set_marketing_flash

Page 15: Refactoring Workshop (Rails Pacific 2014)

2. MOVE MODEL LOGIC INTO THE MODEL

• Move the logic, which belongs to model, into the model

• instance variable should change to self in model

Page 16: Refactoring Workshop (Rails Pacific 2014)

class ProjectsController def new # @#$^$%&#%&*#$%& @project = Project.new !! # &*%^&@#$! end end

class Project !!!!end

@project.do_ooxx @project.xxoo = "xxoo"

def do_something !!end

Page 17: Refactoring Workshop (Rails Pacific 2014)

@project.do_something

class ProjectsController def new # @#$^$%&#%&*#$%& @project = Project.new !! # &*%^&@#$! end end

class Project !!!!end

@project.do_ooxx @project.xxoo = "xxoo"

def do_something !!end

Page 18: Refactoring Workshop (Rails Pacific 2014)

@project.do_something

class ProjectsController def new # @#$^$%&#%&*#$%& @project = Project.new !! # &*%^&@#$! end end

class Project !!!!end

@project.do_ooxx @project.xxoo = "xxoo"

def do_something !!end

Page 19: Refactoring Workshop (Rails Pacific 2014)

do_ooxx self.xxoo = "xxoo"

@project.do_something

class ProjectsController def new # @#$^$%&#%&*#$%& @project = Project.new !! # &*%^&@#$! end end

class Project !!!!end

def do_something !!end

Page 20: Refactoring Workshop (Rails Pacific 2014)

3. REPLACE METHOD WITH METHOD OBJECT

• Create a class with same initialization arguments as BIG method

• Copy & Paste the method's body in the new class, with no arguments

• Replace original method with a call to the new class

• Apply "Intention Revealing Method" to the class

Page 21: Refactoring Workshop (Rails Pacific 2014)

class OriginMethods def a_fat_method !!!! end end

# $%@ + ($@# / ^%) # && ^ %& * #%%^ # wtf # and 100 lines...

Page 22: Refactoring Workshop (Rails Pacific 2014)

class OriginMethods def a_fat_method !!!! end end

class NewMethodsdef perform

endend

# $%@ + ($@# / ^%) # && ^ %& * #%%^ # wtf # and 100 lines...

Page 23: Refactoring Workshop (Rails Pacific 2014)

class OriginMethods def a_fat_method !!!! end end

class NewMethods def perform !!!! end end

# $%@ + ($@# / ^%) # && ^ %& * #%%^ # wtf # and 100 lines...

Page 24: Refactoring Workshop (Rails Pacific 2014)

class OriginMethods def a_fat_method !!!! end end

class NewMethods def perform !!!! end end

# $%@ + ($@# / ^%) # && ^ %& * #%%^ # wtf # and 100 lines...

NewMethods.new.perform

Page 25: Refactoring Workshop (Rails Pacific 2014)

class NewMethods !!!! def perform File.open(??????????) # ... end end !class OriginMethods def a_fat_method(file_name) NewMethods.new.perform end end

?

Page 26: Refactoring Workshop (Rails Pacific 2014)

class NewMethods !!!! def perform File.open( ) # ... end end !class OriginMethods def a_fat_method(file_name) NewMethods.new end end

Page 27: Refactoring Workshop (Rails Pacific 2014)

class NewMethods !!!! def perform File.open( ) # ... end end !class OriginMethods def a_fat_method(file_name) NewMethods.new end end

(file_name).perform

Page 28: Refactoring Workshop (Rails Pacific 2014)

class NewMethods !!!! def perform File.open( ) # ... end end !class OriginMethods def a_fat_method(file_name) NewMethods.new end end

def initialize(file_name)@file_name = file_name

end

(file_name).perform

Page 29: Refactoring Workshop (Rails Pacific 2014)

class NewMethods !!!! def perform File.open( ) # ... end end !class OriginMethods def a_fat_method(file_name) NewMethods.new end end

@file_name

def initialize(file_name)@file_name = file_name

end

(file_name).perform

Page 30: Refactoring Workshop (Rails Pacific 2014)

4. SERVICE OBJECT

• If we add new functionality to an object and:

• It couples to a new dependency

• It loses cohesion

• Testing gets harder and slower

Page 31: Refactoring Workshop (Rails Pacific 2014)

4. SERVICE OBJECT

• If it's a domain concept, it's an Object. If it's only an algorithm (no state) we call it a Service.

• Delegate to the Service Object

Page 32: Refactoring Workshop (Rails Pacific 2014)

5. FORM OBJECT

• accepts_nested_attributes_for is hard to track

• Making very different forms for the same object is a pain. The model is messed up

Page 33: Refactoring Workshop (Rails Pacific 2014)

5. FORM OBJECT• include ActiveModel::Model

• Set attr_reader for related models

• Set attr_accessor for accepted fields

• Add validators (ActiveModel::Model will take care of validation and errors)

• Define persisted? method (false for create, true for update form)

• Add initialize, save, update etc… if needed