Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to f*ck up the refactoring

How to f*ck up the refactoring

Talk about refactoring antipatterns.
Ruby Meditation s.1, e.2, Kiev

Andrey Savchenko

April 06, 2013
Tweet

More Decks by Andrey Savchenko

Other Decks in Programming

Transcript

  1. Project 1 • Written by novice • Full of code

    duplication Saturday, April 6, 13
  2. Project 1 • Written by novice • Full of code

    duplication • Denormalized data structure Saturday, April 6, 13
  3. Project 2 • Written by more experienced developer • No

    code duplication Saturday, April 6, 13
  4. Project 2 • Written by more experienced developer • No

    code duplication • No data duplication Saturday, April 6, 13
  5. lib/extensions.rb ________ class Hash def to_ostruct # Convert text to

    ostruct end end module Wicked::Controller::Concerns::RenderRedirect def process_resource!(resource) # processing staff end end Saturday, April 6, 13
  6. How to prevent • Do not do refactor unless you

    know exactly what you do • Do not assign refactor tasks to the juniors • Learn design patterns Saturday, April 6, 13
  7. DRY does not mean “don’t type the same characters twice”

    ‟ David Chelimsky Saturday, April 6, 13
  8. Bad %(foo bar baz).each do |name| define_method(:"set_#{name}") do |val| val

    = val.to_s if name == "bar" name = :"#{name}_name" self.prev[name] = self.attributes[name] self.attributes[name] = val end end Saturday, April 6, 13
  9. Good def set_attribute(name, val) prev[name] = attributes[name] attributes[name] = val

    end def set_foo(val) set_attribute(:foo_name, val) end def set_bar(val) set_attribute(:bar_name, val.to_s) end def set_baz(val) set_attribute(:baz_name, val) end Saturday, April 6, 13
  10. tasks.do_the_task(:special, "foo") tasks.do_the_task(:ordinal, "bar") def do_the_task(type, val) if type ==

    :special val = convert_val_for_special(val) end if type == :ordinal && val.is_a?(String) self.is_string = true end self.type = type self.state = :done self.val = val save end Bad Saturday, April 6, 13
  11. Good def do_special_task(val) val = convert_val_for_special(val) persist_task(:special, val) end def

    do_ordinal_task(val) self.is_string = true if val.is_a?(String) persist_task(:ordinal, val) end def do_another_task persist_task(:another, val) end def persist_task(type, val) self.type = type self.state = :done self.val = val save end Saturday, April 6, 13
  12. How to prevent • Don’t afraid to type twice -

    afraid to implement twice • Avoid metaprogramming • Avoid metaprogramming Saturday, April 6, 13
  13. class PigLivery def filter(blood) # do important things end end

    class Pig def initialize @livery = PigLivery.new # ... end end Saturday, April 6, 13
  14. - class PigLivery + class PigHumanLivery class Human def initialize

    @livery = PigHumanLivery.new # ... end end def initialize if for_human? resize_a_bit end end Saturday, April 6, 13
  15. How to prevent • Use OOP superpower (subclassing instead conditions,

    etc.) • Follow the interface segregation principle Saturday, April 6, 13
  16. class GeneralContent # Attrs: title, body, coords, tags end class

    Page < GeneralContent # Uses: title, body, tags end class City < GeneralContent # Uses: title, body, coords end class Hotel < GeneralContent # Uses: title, coords, stars, tags end Saturday, April 6, 13
  17. How to prevent • Do not rebuild data structure while

    business requirements is not finalized • If you consciously do something like this — try to change your profession Saturday, April 6, 13