Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

How to f*ck_up_the_refactoring - Andrii Savchenko

49 views

Published on

Ruby Meditation #2
April 6, 2013
Kyiv

Published in: Technology
  • Be the first to comment

  • Be the first to like this

How to f*ck_up_the_refactoring - Andrii Savchenko

  1. 1. How to f*ck up the refactoring The ultimate guide Saturday, April 6, 13
  2. 2. Situation Saturday, April 6, 13
  3. 3. •2 developers Saturday, April 6, 13
  4. 4. •2 developers •2 projects Saturday, April 6, 13
  5. 5. •2 developers •2 projects •Near the same stage Saturday, April 6, 13
  6. 6. Project1 • Written by novice Saturday, April 6, 13
  7. 7. Project1 • Written by novice • Full of code duplication Saturday, April 6, 13
  8. 8. Project1 • Written by novice • Full of code duplication • Denormalized data structure Saturday, April 6, 13
  9. 9. Project1 Still maintainable Saturday, April 6, 13
  10. 10. Project2 • Written by more experienced developer Saturday, April 6, 13
  11. 11. Project2 • Written by more experienced developer • No code duplication Saturday, April 6, 13
  12. 12. Project2 • Written by more experienced developer • No code duplication • No data duplication Saturday, April 6, 13
  13. 13. Project2 Maintainable through rewrite Saturday, April 6, 13
  14. 14. Saturday, April 6, 13
  15. 15. @ptico }Github Twitter LinkedIn Andrey Savchenko Aejis Saturday, April 6, 13
  16. 16. Refactoring anti-patterns Saturday, April 6, 13
  17. 17. “IDD” Intuition Driven Development Saturday, April 6, 13
  18. 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
  19. 19. app/controllers/application_controller.rb module AjaxActions def users_list render :json => @users end end Saturday, April 6, 13
  20. 20. lib/model_helper.rb module ModelHelpers def as_json(*) super(:include => :logs) end end Saturday, April 6, 13
  21. 21. Howtoprevent • 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
  22. 22. “DRY Madness” Saturday, April 6, 13
  23. 23. DRY does not mean “don’t type the same characters twice”‟David Chelimsky Saturday, April 6, 13
  24. 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
  25. 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
  26. 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
  27. 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
  28. 28. Howtoprevent • Don’t afraid to type twice - afraid to implement twice • Avoid metaprogramming • Avoid metaprogramming Saturday, April 6, 13
  29. 29. “Frankenstein” Saturday, April 6, 13
  30. 30. class PigLivery def filter(blood) # do important things end end class Pig def initialize @livery = PigLivery.new # ... end end Saturday, April 6, 13
  31. 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
  32. 32. class FrankensteinMonster def initialize @livery = PigHumanLivery.new @eyes = CatDogEyes.new @jaw = MonkeyJaw.new # ... end end Saturday, April 6, 13
  33. 33. Howtoprevent • Use OOP superpower (subclassing instead conditions, etc.) • Follow the interface segregation principle Saturday, April 6, 13
  34. 34. “General content” Saturday, April 6, 13
  35. 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
  36. 36. Howtoprevent • 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
  37. 37. Common tips Saturday, April 6, 13
  38. 38. Don’trefactor onearly stages Saturday, April 6, 13
  39. 39. You have enought time  Saturday, April 6, 13
  40. 40. Learndesign patterns andprinciples Saturday, April 6, 13
  41. 41. SOLID GRASP YAGNI Saturday, April 6, 13
  42. 42. Usecommonsense Saturday, April 6, 13
  43. 43. Saturday, April 6, 13
  44. 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

×