Refactoring
.... porque apenas fazer
funcionar não é o suficiente.

                   @caike
                   caikesouza.com
www.envylabs.com
Orlando Coding Dojo




http://orlandodojo.org
Refatorar é...
realizar mudanças internas em um
programa funcional com o objetivo torná-lo
mais fácil de ser compreendido e mais
barato de ser modificado - sem que haja
mudanças no comportamento externo;
Limpar a casa sem
 mudar a fachada
Métodos
 Ágeis
eXtreme
Programming
Scrum ?
Testes
(Anti-)Patterns
Software
Craftsmanship
"Any fool can write code that
   a computer can understand.
Good programmers write code that
    humans can understand"

          (Martin Fowler)
Benefícios
Design
Responder
a mudanças
Entregas
Constantes
Waterfall




Jan   Feb   Mar    Apr     May     Jun           Jul

             Cost of Maintenance         Extreme Programming Explained: Embrace Change
                                                     Addison Wesley, 2000
XP




Jan   Feb   Mar    Apr     May     Jun           Jul

             Cost of Maintenance         Extreme Programming Explained: Embrace Change
                                                     Addison Wesley, 2000
Quando ?
novas features
TDD
Red
 Green
Refactor
bugs
TDD
Red
 Green
Refactor
Code Reviews
om
         c o
        e çã
   il izReviews
Code ra
  t e
 U d
  m   o
“The great thing about programming is
 pretty much everyone's code is shit.
Writing software is hard, so it's no problem
      finding dogs in someone's stuff”

                 (Zed Shaw)
Débito Técnico
exemplos.rb
managers = []

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

employees.each do |e|
  managers << e if e.is_manager?
end
Replace Loop with
 Closure Method
managers = []

employees.each do |e|
  managers << e if e.is_manager?
end
managers = employees.
  select { |e| e.is_manager? }
class Movie
  def initialize(stars)
    @stars = stars
  end

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

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

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

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

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

  def recommended?
    rating = (@stars > 5) ? 8 : 1
    rating >= 8
  end
end
Replace Temp
With Query
class Movie
  def initialize(stars)
    @stars = stars
  end

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

  def recommended?
    rating >= 8
  end

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

  def recommended?
    rating() >= 8
  end

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

  def recommended?
    rating >= 8
  end

  def rating
    (@stars > 5) ? 8 : 1
  end
end
OMG OMG OMG OMG OMG
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
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
Inline Method
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
class Movie
  def initialize...end
  def recommended?
    rating >= 8
  end

  def rating
    @stars > 5 ? 8 : 1
  end




end
user.posts.paginate(:page => params[:page],
    :per_page => params[:per_page] || 15)
user.posts.paginate(:page => params[:page],
    :per_page => params[:per_page] || 15)
Replace Magic Number
with Symbolic Constant
user.posts.paginate(:page => params[:page],
    :per_page => params[:per_page] || 15)
CONTACTS_PER_PAGE = 15

user.posts.paginate(:page => params[:page],
    :per_page => params[:per_page] ||
CONTACTS_PER_PAGE)
mock = mock('user')
expectation = mock.expects(:find)
expectation.with("1")
expectation.returns([])
mock = mock('user')
expectation = mock.expects(:find)
expectation.with("1")
expectation.returns([])
Replace Temp
 With Chain
mock = mock('user')
expectation = mock.expects(:find)
expectation.with("1")
expectation.returns([])
mock = mock('user')
mock.expects(:find).with("1").
      returns([])
Command
  vs.
 Query
def expects
  ...
  self
end

def with
  ...
  self
end

def returns
  ...
  self
end
def charge(amount, card_number)
  begin
    conn = CC_Charger_Server.connect(...)
    conn.send_charge(amount, card_number)
  rescue IOError => e
    Logger.log "Error: #{e}"
    return nil
  ensure
    conn.close
  end
end
def charge(amount, card_number)
  begin
    conn = CC_Charger_Server.connect(...)
    conn.send_charge(amount, card_number)
  rescue IOError => e
    Logger.log "Error: #{e}"
    return nil
  ensure
    conn.close
  end
end
Extract Surrounding
      Method
def charge(amount, ccnumber)
  begin
    conn = CC_Charger_Server.connect(...)
    conn.send_charge(amount, card_number)
  rescue IOError => e
    Logger.log "Error: #{e}"
    return nil
  ensure
    conn.close
  end
end
def charge(amount, card_number)
  connect do |conn|
    conn.send_charge(amount, card_number)
  end
end
def connect
  begin
    conn = CC_Charger_Server.connect(...)
    yield conn
  rescue IOError => e
    Logger.log "Error: #{e}"
    return nil
  ensure
    conn.close
  end
end
def body_fat_percentage(name,
  age, height, weight, metric_system)
  ...
end
body_fat_percentage("fred", 30, 1.82, 90, 1)
body_fat_percentage("joe", 32, 6, 220, 2)
body_fat_percentage("fred", 30, 1.82, 90, 1)
body_fat_percentage("joe", 32, 6, 220, 2)
Introduce Named Parameter
body_fat_percentage("fred", 30, 1.82, 90, 1)
body_fat_percentage("joe", 32, 6, 220, 2)
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)
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 })
def   body_fat_percentage(name, params={})
  #   params[:age]
  #   params[:height]
  #   params[:weight]
  #   params[:metric_system]
end
class MountainBike
  def price
    ...
  end
end

MountainBike.new(:type => :rigid, ...)
MountainBike.new(:type => :front_suspension, ...)
MountainBike.new(:type => :full_suspension, ...)
def price
  if @type == :rigid
      (1 + @comission) * @base_price
  end
  if @type == :font_suspension
    (1 + @comission) * @base_price +
    @front_suspension_price
  end
  if @type == :full_suspension
    (1 + @comission) * @base_price+
    @front_suspension_price +
    @rear_suspension_price
  end




end
def price
  if @type == :rigid
      (1 + @comission) * @base_price
  end
  if @type == :font_suspension
    (1 + @comission) * @base_price +
    @front_suspension_price
  end
  if @type == :full_suspension
    (1 + @comission) * @base_price+
    @front_suspension_price +
    @rear_suspension_price
  end
  if @type == :ultra_suspension
      ...
  end
end
FECHADAS
para modificações

   ABERTAS
 para extensões
Replace Conditional
With Polymorphism
class MountainBike
  def price
    ...
  end
end
module MountainBike
  def price
    ...
  end
end
class RigidMountainBike
  include MountainBike
end

class FrontSuspensionMountainBike
  include MountainBike
end

class FullSuspensionMountainBike
  include MountainBike
end
RigidMountainBike.new(:type => :rigid, ...)

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

FullSuspensionMountainBike.new(:type =>
 :full_suspension, ...)
class RigidMountainBike
  include MountainBike

  def price
    (1 + @comission) * @base_price
  end
end
def price
  if @type == :rigid
    raise "should not be called"
  end
  if @type == :font_suspension
    (1 + @comission) * @base_price +
    @front_suspension_price
  end
  if @type == :full_suspension
    (1 + @comission) * @base_price+
    @front_suspension_price +
    @rear_suspension_price
  end
end
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
  end
end
def price
  if @type == :rigid
    raise "should not be called"
  end
  if @type == :font_suspension
    raise "should not be called"
  end
  if @type == :full_suspension
    raise "should not be called"
  end
end
def price
  if @type == :rigid
    raise "should not be called"
  end
  if @type == :font_suspension
    raise "should not be called"
  end
  if @type == :full_suspension
    raise "should not be called"
  end
end
class RigidMountainBike
  include MountainBike
end

class FrontSuspensionMountainBike
  include MountainBike
end

class FullSuspensionMountainBike
  include MountainBike
end
Já posso ser um
  Programador
   RockStar ?
NÃO
“I’m not a great programmer.
 I’m just a good programmer
     with great habits”

          (Kent Beck)
"People are non-linear,
first-order components in
 software development"
      (Alistair Cockburn)
Refactoring
.... porque apenas fazer
funcionar não é o suficiente.
      http://www.flickr.com/photos/eurleif/255241547/
      http://www.flickr.com/photos/dhammza/91435718/
      http://www.flickr.com/photos/krash0387
      http://www.flickr.com/photos/benfrantzdale/208672143/
      http://www.flickr.com/photos/improveit/1574023621/      @caike
      http://www.flickr.com/photos/aaroncoyle/972403508
      http://www.flickr.com/photos/talios/3726484920
      http://www.flickr.com/photos/moow/3412079622
                                                             caikesouza.com
      http://www.flickr.com/photos/highwayoflife/2699887178/

Refactoring