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

Avatar for Andrey Savchenko

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