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. How to f*ck up
    the refactoring
    The ultimate guide
    Saturday, April 6, 13

    View full-size slide

  2. Situation
    Saturday, April 6, 13

    View full-size slide

  3. •2 developers
    Saturday, April 6, 13

    View full-size slide

  4. •2 developers
    •2 projects
    Saturday, April 6, 13

    View full-size slide

  5. •2 developers
    •2 projects
    •Near the same stage
    Saturday, April 6, 13

    View full-size slide

  6. Project 1
    • Written by novice
    Saturday, April 6, 13

    View full-size slide

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

    View full-size slide

  8. Project 1
    • Written by novice
    • Full of code duplication
    • Denormalized data structure
    Saturday, April 6, 13

    View full-size slide

  9. Project 1
    Still maintainable

    Saturday, April 6, 13

    View full-size slide

  10. Project 2
    • Written by more experienced developer
    Saturday, April 6, 13

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  13. Project 2
    Maintainable through rewrite

    Saturday, April 6, 13

    View full-size slide

  14. Saturday, April 6, 13

    View full-size slide

  15. @ptico
    }
    Github
    Twitter
    LinkedIn
    Andrey Savchenko
    Aejis
    Saturday, April 6, 13

    View full-size slide

  16. Refactoring
    anti-patterns
    Saturday, April 6, 13

    View full-size slide

  17. “IDD”
    Intuition Driven Development
    Saturday, April 6, 13

    View full-size slide

  18. 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

    View full-size slide

  19. app/controllers/application_controller.rb
    module AjaxActions
    def users_list
    render :json => @users
    end
    end
    Saturday, April 6, 13

    View full-size slide

  20. lib/model_helper.rb
    module ModelHelpers
    def as_json(*)
    super(:include => :logs)
    end
    end
    Saturday, April 6, 13

    View full-size slide

  21. 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

    View full-size slide

  22. “DRY Madness”
    Saturday, April 6, 13

    View full-size slide

  23. DRY does not mean “don’t type the
    same characters twice”

    David Chelimsky
    Saturday, April 6, 13

    View full-size slide

  24. 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

    View full-size slide

  25. 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

    View full-size slide

  26. 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

    View full-size slide

  27. 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

    View full-size slide

  28. How to prevent
    • Don’t afraid to type twice - afraid to
    implement twice
    • Avoid metaprogramming
    • Avoid metaprogramming
    Saturday, April 6, 13

    View full-size slide

  29. “Frankenstein”
    Saturday, April 6, 13

    View full-size slide

  30. class PigLivery
    def filter(blood)
    # do important things
    end
    end
    class Pig
    def initialize
    @livery = PigLivery.new
    # ...
    end
    end
    Saturday, April 6, 13

    View full-size slide

  31. - 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

    View full-size slide

  32. class FrankensteinMonster
    def initialize
    @livery = PigHumanLivery.new
    @eyes = CatDogEyes.new
    @jaw = MonkeyJaw.new
    # ...
    end
    end
    Saturday, April 6, 13

    View full-size slide

  33. How to prevent
    • Use OOP superpower (subclassing instead
    conditions, etc.)
    • Follow the interface segregation principle
    Saturday, April 6, 13

    View full-size slide

  34. “General content”
    Saturday, April 6, 13

    View full-size slide

  35. 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

    View full-size slide

  36. 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

    View full-size slide

  37. Common tips
    Saturday, April 6, 13

    View full-size slide

  38. Don’t refactor on early
    stages
    Saturday, April 6, 13

    View full-size slide

  39. You have enought time

    Saturday, April 6, 13

    View full-size slide

  40. Learn design patterns
    and principles
    Saturday, April 6, 13

    View full-size slide

  41. SOLID
    GRASP
    YAGNI
    Saturday, April 6, 13

    View full-size slide

  42. Use common sense
    Saturday, April 6, 13

    View full-size slide

  43. Saturday, April 6, 13

    View full-size slide

  44. Questions?
    Attributions:
    Linecons by Sergey Shmidt
    http://www.flickr.com/photos/amyn-design/8548659957/
    http://www.flickr.com/photos/greenflames09/100781977/
    Andrey Savchenko
    Aejis
    @ptico
    Saturday, April 6, 13

    View full-size slide