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

How to work with
 Legacy (Rails) Code

How to work with
 Legacy (Rails) Code

Why does software become “legacy”?

Many of us have tried to discover ways to prevent code from becoming legacy.

We tried and had good intentions.
We've written books on principles, best practices and design patterns that can help programmers keep their systems clean.
But even the most disciplined will create a mess from time to time.

This talk will cover the main problems, that lead to legacy code and provide some guidance, tools and patterns, 
which can help you to work with legacy code and how to avoid it the next time.

DonSchado

May 24, 2016
Tweet

More Decks by DonSchado

Other Decks in Programming

Transcript

  1. Railslove
    We love to build the web.
    How to work with

    Legacy (Rails) Code
    Marco Schaden

    @donschado
    [email protected]
    24.05.2016

    View Slide

  2. Legacy (Rails) Code 24.05.2016
    The following is a summary of our own practical experiences
    enriched with opinions and knowledge of various esteemed experts
    and super heroes such as
    Kent Beck
    Martin Fowler
    Uncle Bob Martin
    Michael C. Feathers
    Katrina Owen
    Sandi Metz
    Corey Haines
    Jay Fields
    and other respected people
    Disclaimer

    View Slide

  3. Legacy (Rails) Code 24.05.2016
    Disclaimer
    The slides are primarily made with Ruby/JS web developers in mind, but apply in most principles to any language.

    We will see almost no code, but discuss a lot of best practices.
    You'll understand that I'm not able to show any client code.
    But I don't need to show you crappy code so that we can have fun about it,
    everybody wrote crappy code…
    You will have a lot of homework after this talk :)

    View Slide

  4. Legacy (Rails) Code 24.05.2016
    Disclaimer
    If you don’t understand something, don’t hesitate to ask.
    Slides are available online: https://speakerdeck.com/donschado

    View Slide

  5. Legacy (Rails) Code 24.05.2016
    Why does software become “legacy”?

    View Slide

  6. Legacy (Rails) Code 24.05.2016
    Is it the customers fault

    by changing the requirements
    all the time?

    View Slide

  7. Legacy Code 21.10.2016
    Why couldn't the customer just be happy, with what they first said they need…

    View Slide

  8. google: IT+Project+Tree
    How the customer 

    explained it
    How the Project Leader 

    understood it
    How the Analyst designed it 
 How the Programmer 

    wrote it
    How the Business
    Consultant described it
    How the project was 

    documented
    What Operations

    deployed
    How the customer was
    billed
    How it was supported What the customer really
    needed

    View Slide

  9. Legacy Code 21.10.2016
    Random developer: 

    “It was not designed to do this, we need to start from scratch..."

    View Slide

  10. Legacy Code 21.10.2016
    Surprise: Requirements Change

    View Slide

  11. Legacy Code 21.10.2016
    Surprise: Requirements Change, all the time!

    View Slide

  12. Legacy Code 21.10.2016
    Surprise: Requirements Change, all the time!
    Software that cannot tolerate this, is simply poor designed.

    View Slide

  13. Hi, I’m Marco
    @donschado
    [email protected]
    Software Developer

    Master of Computer Science

    View Slide

  14. T
    We’re an agile team 

    and develop products for the web.
    Web applications are more than our
    daily business. We support our
    customers in close cooperation from
    the initial idea through to the launch -
    and beyond.

    View Slide

  15. Legacy (Rails) Code 24.05.2016

    View Slide

  16. Legacy (Rails) Code 24.05.2016
    https://www.railslove.com/jobs

    View Slide

  17. Legacy (Rails) Code 24.05.2016
    Rails…?

    View Slide

  18. Legacy (Rails) Code 24.05.2016
    I know this is old, but when you remember web development in 2005, the demo is still awesome.

    View Slide

  19. Legacy (Rails) Code 24.05.2016
    Ruby
    A PROGRAMMER’S BEST FRIEND
    TL;DR Ruby
    Yukihiro Matsumoto
    (Matz)
    https://www.ruby-lang.org
    Ruby is designed to be human-oriented.
    It reduces the burden of programming
    and tries to push jobs back to machines.
    You can accomplish more tasks with less
    work, in smaller yet readable code.
    First appeared 1995
    21 years ago
    Multi-paradigm: 

    Object-oriented
    imperative
    functional
    reflective
    dynamically typed

    View Slide

  20. Legacy (Rails) Code 24.05.2016
    David Heinemeier Hansson
    (DHH)
    Rails is an attempt to
    mold the beauty and
    productiveness of Ruby
    into a framework for
    web applications.
    • convention over configuration
    • don't repeat yourself (DRY)
    • model - view - controller
    architecture (MVC)
    TL;DR Rails
    https://www.rubyonrails.org

    View Slide

  21. Legacy Code 21.10.2016

    View Slide

  22. This stuff is so 2005, you better use…
    ELIXIR
    PHOENIX
    GO
    EMBER
    ANGULAR
    GRUNT
    GULP
    ELM
    DOCKER
    REACT
    WEBPACK
    BROWSERIFY
    REDUX
    FLUX
    RUST
    BACKBONE MARIONETTE
    NODE
    ES2016
    SASS
    LESS
    COFFEESCRIPT
    POLYMER
    KNOCKOUT
    METEOR
    HANDLEBARS
    EXPRESS
    BOWER
    TRAILBLAZER
    CLOJURE
    MICROSERVICES
    TYPESCRIPT

    View Slide

  23. Legacy Code 21.10.2016
    the hype is a lie

    View Slide

  24. Legacy Code 21.10.2016
    http://www.gartner.com/technology/research/methodologies/hype-cycle.jsp

    View Slide

  25. Legacy Code 21.10.2016
    New technology doesn’t save you
    from legacy

    View Slide

  26. Legacy (Rails) Code 24.05.2016
    If you have lot of free time and are curios about new technology,
    it’s an amazing time to be a developer.
    The hype is a lie
    If you have a real job and maintaining a product, 

    then this doesn’t benefit you unless you rewrite your project every three months, 

    in the hottest tech available.
    Worse, even if you manage to resist the temptation to do that, 

    people will keep raving about their new toys and making you feel retarded.

    View Slide

  27. Legacy (Rails) Code 24.05.2016
    Mountain West Ruby 2016 - Surviving the Framework Hype Cycle by Brandon Hays
    https://www.youtube.com/watch?v=9zc4DSTRGeM

    View Slide

  28. Legacy (Rails) Code 24.05.2016

    def legacy_code
    legacy code VS technical debt
    class You < LegacyCode::Base
    Change
    Dependencies
    Testing
    Refactoring
    Bugs
    Rewrite vs Refactoring
    Tools

    View Slide

  29. Legacy Code 21.10.2016
    Legacy is not exclusively a bad thing

    View Slide

  30. Legacy Code 21.10.2016
    Most of us see legacy as…

    View Slide

  31. Legacy (Rails) Code 24.05.2016
    Some
    may see it
    differently:
    #vintage #oldtimer #classic

    View Slide

  32. Legacy Code 21.10.2016
    many “legacy” systems have reliably served 

    the needs of their businesses
    generating value (usually it’s the main system and the source of income…)
    people and processes depend on it
    just because code is old 

    doesn’t mean it has to be thrown away
    Some people in our industry call it legacy while the
    codebase is less than 2 years old?!
    #vintage #oldtimer #classic

    View Slide

  33. Legacy (Rails) Code 24.05.2016
    def legacy_code

    View Slide

  34. Legacy Code 21.10.2016
    slang for complex, difficult to change code
    code with many dependencies
    mostly somebody else's code
    “old” code with deprecated syntax/features or style
    highly coupled code / “spaghetti" / ball of mud
    code you’re afraid to touch
    code without tests
    def legacy_code

    View Slide

  35. Legacy (Rails) Code 24.05.2016
    The Michael C. Feathers definition:
    “code without tests”
    no matter how well written it is, 

    without tests you don't know 

    if a change makes it better or worse
    def legacy_code

    View Slide

  36. Why does software become “legacy”?

    View Slide

  37. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt

    View Slide

  38. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    *sometimes required to move projects forward

    View Slide

  39. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    *sometimes required to move projects forward
    referring to the eventual
    consequences of any
    system design

    View Slide

  40. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    accumulating interest
    *sometimes required to move projects forward
    referring to the eventual
    consequences of any
    system design

    View Slide

  41. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    accumulating interest
    *sometimes required to move projects forward
    referring to the eventual
    consequences of any
    system design
    the result
    of unpaid debt

    View Slide

  42. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    accumulating interest
    *sometimes required to move projects forward
    referring to the eventual
    consequences of any
    system design
    code smells
    • metaprogramming madness
    • long parameter list
    • shotgun surgery
    • duplicated code
    • feature envy
    • large class
    • long method
    • case statements
    • complex conditionals
    the result
    of unpaid debt

    View Slide

  43. Legacy (Rails) Code 24.05.2016
    legacy code vs technical debt
    accumulating interest
    code smells
    refactoring
    • metaprogramming madness
    • long parameter list
    • shotgun surgery
    • duplicated code
    • feature envy
    • large class
    • long method
    • case statements
    • complex conditionals
    *sometimes required to move projects forward
    referring to the eventual
    consequences of any
    system design
    the result
    of unpaid debt

    View Slide

  44. Legacy (Rails) Code 24.05.2016
    So you've inherited some “legacy”…
    What do you look at first?

    View Slide

  45. Legacy (Rails) Code 24.05.2016
    Who wrote that crap?

    git blame all the files

    View Slide

  46. Legacy (Rails) Code 24.05.2016
    What does crappy code say
    about the developer who wrote it?

    View Slide

  47. Legacy (Rails) Code 24.05.2016
    What does crappy code say
    about the developer who wrote it?
    not skilled enough
    bad person
    drunk

    View Slide

  48. Legacy (Rails) Code 24.05.2016
    What does crappy code say
    about the developer who wrote it?
    not skilled enough
    bad person
    drunk
    changing requirements
    tough deadline
    had a bad day

    View Slide

  49. Legacy (Rails) Code 24.05.2016
    What does crappy code say
    about the developer who wrote it?
    not skilled enough
    bad person
    drunk
    changing requirements
    tough deadline
    had a bad day
    it's easy and funny to criticise
    but you might miss the context,
    at the time the code was written

    View Slide

  50. Only blame the developers?

    View Slide

  51. Legacy Code 21.10.2016
    missing (product) strategy (no design thinking)
    unnecessary / tough deadlines
    unfinished requirements
    conceptually poor features
    needless complexity
    high fluctuation and poor on-boarding
    not enough training / further education
    doing agile wrong (yeah, we’re doing scrum/kanban we’re so agile!)
    The influence of management* on legacy:
    Even a development process that encourages code reviews and pairing

    can yield bad technical decisions which effect the whole architecture:

    View Slide

  52. Legacy Code 21.10.2016
    You might miss the context,
    at the time the code was written

    View Slide

  53. Legacy (Rails) Code 24.05.2016
    Uncle Bob:
    “every 5 years, double new programmers,
    with less than 5 years experience”
    http://blog.cleancoder.com/uncle-bob/2014/06/20/MyLawn.html

    View Slide

  54. Legacy (Rails) Code 24.05.2016
    Doesn't matter, now YOU need to

    View Slide

  55. Legacy (Rails) Code 24.05.2016
    Doesn't matter, now YOU need to

    View Slide

  56. Legacy (Rails) Code 24.05.2016
    Doesn't matter, now YOU need to

    View Slide

  57. Legacy (Rails) Code 24.05.2016
    Doesn't matter, now YOU need to

    View Slide

  58. Legacy Code 21.10.2016
    change

    View Slide

  59. Legacy (Rails) Code 24.05.2016
    changing legacy code
    is a big deal

    View Slide

  60. Legacy (Rails) Code 24.05.2016
    In legacy code, it is particularly hard to come up with estimates that are
    meaningful.
    even the simplest code changes take a long time to implement
    it seems like no amount of time will be enough to understand everything
    you need to do to make a change
    Expensive

    View Slide

  61. Legacy (Rails) Code 24.05.2016
    How much change can you afford if changes are risky?
    What changes do we have to make?
    How will we know that we've done them correctly and haven't broken
    anything?
    Risk
    Often we don't know how much of the existing behaviour is at risk 

    when we make our changes.

    View Slide

  62. Legacy (Rails) Code 24.05.2016

    View Slide

  63. Legacy (Rails) Code 24.05.2016
    1. Identify change points
    2. Find test points
    3. Break dependencies
    4. Write tests
    5. Make your changes and refactor
    Algorithm:
    Michael C. Feathers

    View Slide

  64. Legacy (Rails) Code 24.05.2016
    1. Identify change points
    2. Find test points
    3. Break dependencies
    4. Write tests
    5. Make your changes and refactor
    Algorithm:
    debugger, inspect, puts, tap, raise, console.log, …
    most obvious impediment to testing
    this can be hard for side effects

    sometime requires creative and ugly technics
    Always leave the campground cleaner than you found it
    Michael C. Feathers

    View Slide

  65. Legacy (Rails) Code 24.05.2016
    1. Identify change points
    2. Find test points
    3. Break dependencies
    4. Write tests
    5. Make your changes and refactor
    Algorithm:
    debugger, inspect, puts, tap, raise…
    most obvious impediment to testing
    this can be hard for side effects

    sometime requires creative and ugly technics
    Always leave the campground cleaner than you found it
    Michael C. Feathers

    View Slide

  66. Legacy (Rails) Code 24.05.2016
    Dependencies
    They will try to kill you

    View Slide

  67. Legacy (Rails) Code 24.05.2016
    http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm

    View Slide

  68. Legacy (Rails) Code 24.05.2016
    Whenever we bring up on our screens a nasty batch of tangled legacy code,
    we are experiencing the results of poor dependency management.
    Poor dependency management leads to code that is
    hard to change, fragile, and non-reusable.


    When classes depend directly on things that are hard to use in a test,
    they are hard to modify and hard to work with.
    Uncle Bob:

    View Slide

  69. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    depend on abstraction instead of implementation
    don't call 3rd Party APIs directly
    in Ruby you can do this implicit as a 'protocoll' 

    (we don't care for the type of the dependency)

    View Slide

  70. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    depend on abstraction instead of implementation
    don't call 3rd Party APIs directly
    in Ruby you can do this implicit as a 'protocoll' 

    (we don't care for the type of the dependency)
    A B
    before
    In UML the arrow points to a dependency

    View Slide

  71. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    depend on abstraction instead of implementation
    don't call 3rd Party APIs directly
    in Ruby you can do this implicit as a 'protocoll' 

    (we don't care for the type of the dependency)
    A B
    before
    A B
    after
    I
    Interface! Ohai Java!
    In UML the arrow points to a dependency

    View Slide

  72. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    Summary: DIP is primarily about reversing the conventional direction of
    dependencies from higher level components to lower level components such
    that lower level components are dependent upon the “interfaces” owned by
    the higher level components.

    View Slide

  73. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    Summary: DIP is primarily about reversing the conventional direction of
    dependencies from higher level components to lower level components such
    that lower level components are dependent upon the “interfaces” owned by
    the higher level components.

    View Slide

  74. Legacy (Rails) Code 24.05.2016
    Dependency Inversion Principle
    Summary: DIP is primarily about reversing the conventional direction of
    dependencies from higher level components to lower level components such
    that lower level components are dependent upon the “interfaces” owned by
    the higher level components.

    View Slide

  75. Legacy (Rails) Code 24.05.2016
    Dependency Injection
    class Car
    def start
    Engine.new.start
    end
    end
    before

    View Slide

  76. Legacy (Rails) Code 24.05.2016
    Dependency Injection
    class Car
    def start
    Engine.new.start
    end
    end
    class Car
    attr_reader :engine
    def initialize(engine = Engine.new)
    @engine = engine
    end
    def start
    engine.start
    end
    end
    before after (constructor injection)
    Car.new(V8Engine.new).start

    View Slide

  77. Legacy (Rails) Code 24.05.2016
    Dependency Injection
    class Car
    def start
    Engine.new.start
    end
    end
    before after (setter injection)
    class Car
    attr_writer :engine
    def initialize
    end
    def start
    engine.start
    end
    def engine
    @engine ||= Engine.new
    end
    end

    View Slide

  78. Legacy (Rails) Code 24.05.2016
    RubyConf 2009 - SOLID Ruby by: Jim Weirich
    https://www.youtube.com/watch?v=dKRbsE061u4
    GORUCO 2009 - SOLID Object-Oriented Design by Sandi Metz
    https://www.youtube.com/watch?v=v-2yFMzxqwU

    View Slide

  79. Legacy (Rails) Code 24.05.2016
    https://cleancoders.com/videos

    View Slide

  80. Legacy (Rails) Code 24.05.2016
    Testing
    To survive Legacy Code you need to maximise safety

    View Slide

  81. Legacy (Rails) Code 24.05.2016
    2 unit tests. 0 integration tests.

    View Slide

  82. Legacy (Rails) Code 24.05.2016
    unit test integration test

    View Slide

  83. Legacy (Rails) Code 24.05.2016
    unit test integration test
    aka acceptance, end to end , …

    View Slide

  84. Legacy (Rails) Code 24.05.2016
    unit test integration test
    hard to localize the bug when they fail
    very useful in bigger refactorings
    many people

    prefer these

    View Slide

  85. Legacy (Rails) Code 24.05.2016
    unit test integration test
    hard to localize the bug when they fail
    fast feedback very useful in bigger refactorings
    hard to work with

    when lots of little tests fail all the time
    many people

    prefer these
    many people

    do these wrong

    View Slide

  86. Legacy (Rails) Code 24.05.2016
    unit test integration test
    hard to localize the bug when they fail
    fast feedback very useful in bigger refactorings
    hard to work with

    when lots of little tests fail all the time
    many people

    prefer these
    many people

    do these wrong
    Use high level tests only to make sure the overall system works 

    and drive the behaviour down to the unit level.

    View Slide

  87. Legacy (Rails) Code 24.05.2016
    How to
    unit test
    In theory, writing a test 

    for a piece of functionality shouldn’t be too bad.
    We instantiate a class, 

    call its methods and check the results.
    What could go wrong?
    GOALS
    • comprehensive
    • stable
    • fast
    • few

    View Slide

  88. Legacy (Rails) Code 24.05.2016
    The method might not be accessible to the test. 

    It could be private or have some other accessibility problem.
    It might be hard to call the method because it is hard to
    construct the parameters we need to call it.
    We might need to sense through some other object that the
    method uses.
    The method might have (bad) side effects
    modifying a database
    send notification
    launching a cruise missile …
    How to
    unit test
    GOALS
    • comprehensive
    • stable
    • fast
    • few

    View Slide

  89. Legacy (Rails) Code 24.05.2016
    Rails Conf 2013 The Magic Tricks of Testing by Sandi Metz https://www.youtube.com/watch?v=URSWYvyc42M

    View Slide

  90. Legacy (Rails) Code 24.05.2016
    Legacy Code
    is special
    Testing legacy code requires creative
    and (sometimes) ugly technics
    Break all rules if it saves $$$ during development

    View Slide

  91. Legacy (Rails) Code 24.05.2016
    Rule of thumb for nearly every legacy system:
    What the system does is more important than what it is supposed to do.

    View Slide

  92. Legacy (Rails) Code 24.05.2016
    The tests that we need when we want to preserve behaviour are called
    characterization tests.

    View Slide

  93. Legacy (Rails) Code 24.05.2016
    Golden Master Testing
    wow, such fancy, very noble

    View Slide

  94. Legacy (Rails) Code 24.05.2016
    def:
    Golden Master Testing refers to capturing the result of “a process”,

    and then comparing future runs against the saved golden master version
    to discover unexpected changes.
    So you expect, that what it does now, is correct.

    View Slide

  95. Legacy (Rails) Code 24.05.2016
    Golden Master Testing
    wow such dirt, very temporary

    View Slide

  96. Legacy (Rails) Code 24.05.2016
    1. Use a piece of untested 

    undocumented code
    2. Write an assertion 

    that you know will fail
    3. Let the failure tell you 

    what the behaviour is
    4. Change the test so that it 

    expects the behaviour that
    the code produces
    5. Reason about the code 

    and exercise every branch
    Golden Master Testing:
    6. Repeat until 

    the code is covered

    View Slide

  97. Legacy (Rails) Code 24.05.2016
    <<<
    The idea is:
    you get some output and save the result (snapshot)
    and every time you run the test again you compare:


    * the same: great the test pass, because everything works as before
    * different: the test fails and the human has to check the output again
    >>>

    View Slide

  98. Legacy (Rails) Code 24.05.2016
    This seems to be fundamentally wrong
    Are our tests really testing anything at all?
    What if you just characterized a bug?

    View Slide

  99. Legacy (Rails) Code 24.05.2016
    We are trying to put in a mechanism to find bugs later.
    Protection for changing things => confidence to refactor

    View Slide

  100. Legacy (Rails) Code 24.05.2016
    We are trying to put in a mechanism to find bugs later.
    Protection for changing things => confidence to refactor
    A characterization test is not a test you want to keep around.
    • You use the test to get coverage,
    • you refactor,
    • cleanup / write new specs
    • and then you throw it away!

    View Slide

  101. Legacy (Rails) Code 24.05.2016
    Highly coupled tests will cost you more money than they save you
    Add a comment to the tests if you keep them # delete me if I fail
    They will fail when you need them most to pass
    while fixing a critical bug
    making an unrelated change
    you need to go in production NOW
    manually checking the output has high error potential
    Anti Pattern, if you keep them

    View Slide

  102. Legacy (Rails) Code 24.05.2016
    But what about the DOM?
    Legacy JavaScript code usually couples UI and business logic

    View Slide

  103. Legacy (Rails) Code 24.05.2016
    Get out of managing the DOM, as fast as you can.
    • test user interaction with an automated browser engine
    • the DOM represents the state of your application
    • using #ids or .classes to manipulate the DOM is dead
    • be careful testing markup, because it will change
    • use data, rel or role attributes in your tests and to describe behaviour
    • refactor heavy jQuery code to JavaScript objects
    • clear separation between UI and business logic

    View Slide

  104. Legacy (Rails) Code 24.05.2016
    RailsConf 2014 - Bring Fun Back to JS: Step-by-Step Refactoring Toward Ember by Brandon Hays

    https://www.youtube.com/watch?v=VMmaKj8hCR4

    View Slide

  105. Legacy (Rails) Code 24.05.2016
    Tools

    View Slide

  106. Legacy Code 21.10.2016
    Test coverage analysis
    Lines of Code (no code is better than no code)
    Cyclomatic Complexity
    ABC Score for Code Smells
    Churn
    Afferent / Efferent Coupling
    Mutation Coverage
    Metrics:
    Usually language agnostic and a helpful tool, but metrics should never be a goal:

    View Slide

  107. Legacy (Rails) Code 24.05.2016
    SimpleCov
    https://github.com/colszowka/simplecov

    View Slide

  108. Legacy (Rails) Code 24.05.2016
    https://github.com/kytrinyx/approvals
    Golden Master Testing

    View Slide

  109. Legacy (Rails) Code 24.05.2016
    https://github.com/bblimke/webmock
    WebMock

    View Slide

  110. Legacy (Rails) Code 24.05.2016
    https://github.com/vcr/vcr
    VCR

    View Slide

  111. Legacy (Rails) Code 24.05.2016
    https://github.com/jnicklas/capybara
    Capybara

    View Slide

  112. Legacy (Rails) Code 24.05.2016
    https://github.com/mattheworiordan/capybara-screenshot
    capybara-screenshot
    • powerful in
    combination with a
    debugger like
    • https://github.com/pry/pry

    View Slide

  113. Legacy (Rails) Code 24.05.2016
    https://github.com/teampoltergeist/poltergeist
    Poltergeist
    • trigger(“click”) is your friend
    • unit testing jQuery spaghetti is really hard
    • jasmine-rails gem

    View Slide

  114. Legacy (Rails) Code 24.05.2016
    https://github.com/douglascrockford/JSLint
    JSLint
    • IDE/Editor integrations

    View Slide

  115. Legacy (Rails) Code 24.05.2016
    https://github.com/es-analysis/plato
    plato

    View Slide

  116. Legacy (Rails) Code 24.05.2016
    https://github.com/es-analysis/plato
    plato

    View Slide

  117. Legacy (Rails) Code 24.05.2016
    https://github.com/jasmine/jasmine
    Jasmine

    View Slide

  118. Legacy (Rails) Code 24.05.2016
    https://github.com/troessner/reek
    reek

    View Slide

  119. Legacy (Rails) Code 24.05.2016
    https://github.com/seattlerb/flog
    flog

    View Slide

  120. Legacy (Rails) Code 24.05.2016
    https://github.com/mbj/mutant
    mutant
    https://speakerdeck.com/donschado/mutation-testing-with-the-mutant-gem

    View Slide

  121. Legacy (Rails) Code 24.05.2016
    https://github.com/CoralineAda/society
    Afferent/Efferent Coupling
    • identify risky hotspots

    View Slide

  122. Legacy (Rails) Code 24.05.2016
    https://relishapp.com/rspec/rspec-mocks/v/3-4/docs/basics/
    Mock / Stub / Fake Object

    View Slide

  123. Legacy (Rails) Code 24.05.2016
    Ruby & Black Magic
    Everything is allowed to get to first coverage
    instance_variable_get(:@foo)
    send private / protected methods
    reopen class and monkey patch attr_accessor
    capture algorithm in a lambda and use it as assertion for new refactored code
    import complete staging database dump into your test env

    View Slide

  124. Legacy (Rails) Code 24.05.2016
    Everything allowed?
    don’t forget to fix it!
    we can use reflection and special permissions to access
    private variables at runtime
    It is very helpful when we want to break dependencies
    But unless we deal with the root causes, that make these
    cheats necessary, we are just delaying the bill

    View Slide

  125. Legacy (Rails) Code 24.05.2016

    View Slide

  126. Legacy (Rails) Code 24.05.2016
    Bugs

    View Slide

  127. Legacy (Rails) Code 24.05.2016
    When you work on legacy code, you will find bugs throughout the entire process.
    All code has bugs, usually in direct proportion to how little it is understood.
    Examine the possibility that someone is depending on that behaviour.
    Often it takes a bit of analysis to figure out how to fix a bug without causing ripple effects.
    fixing bugs could be dangerous...
    What should you do when you find a bug?

    View Slide

  128. Legacy (Rails) Code 24.05.2016
    Refactoring

    View Slide

  129. Legacy (Rails) Code 24.05.2016

    View Slide

  130. Legacy (Rails) Code 24.05.2016
    the list of refactoring technics is just the beginning
    composing methods (extract method, replace method with object)
    moving features (move method, extract class)
    organizing data (replace hash with object, replace type code with polymorphism)
    simplifying conditional (decompose, recompose, null objects)
    making method calls simpler (separate query from modifier, replace constructor with factory)
    dealing with generalization (template method, extract module, inheritance)
    learn when to start, when to stop
    when you have “refactoring tickets” you're doing it wrong (it’s part of your work!)
    not having the time for refactoring (because of deadlines?) is usually a sign that
    you need to do some refactoring
    Refactoring: pay your bills!

    View Slide

  131. Legacy (Rails) Code 24.05.2016
    You are likely to see new possibilities,
    REFACTOR ALL THE CODE to pursue truth and beauty...

    View Slide

  132. Legacy (Rails) Code 24.05.2016
    DON’T.

    View Slide

  133. Legacy (Rails) Code 24.05.2016
    A big refactoring is a recipe for disaster.
    As ugly as the mess looks now, focus on the real problems.
    When you need to add a new feature:
    add some specs to get confidence
    clean up
    add new code
    refactoring hat, feature hat
    Don't mix an unfinished refactoring with other new tasks.
    Your goal is to leave the code computing exactly the same, like you found it.
    Always leave the campground cleaner than you found it.
    Discipline

    View Slide

  134. Legacy (Rails) Code 24.05.2016
    Rewrite vs Refactoring

    View Slide

  135. Legacy (Rails) Code 24.05.2016
    When is it easier to start from scratch, instead of refactoring a big mess?

    View Slide

  136. Legacy (Rails) Code 24.05.2016
    if it doesn't work at all (code has to work mostly correctly, before you refactor)
    if it is full of bugs and you cannot stabilize it
    there are big changing requirements, the current app can't support
    When is it easier to start from scratch, instead of refactoring a big mess?
    # depends…
    +
    +
    +

    View Slide

  137. Legacy Code 21.10.2016
    Compromise!
    Refactor one large piece into components.

    Favour piece by piece rewrite over big bang rewrite and rebuild incrementally.

    View Slide

  138. Legacy Code 21.10.2016
    Compromise!
    Refactor one large piece into components.

    Favour piece by piece rewrite over big bang rewrite and rebuild incrementally.
    • focus on the important parts
    • recover knowledge which got lost in complex code
    • preserve investment which went into the code already (time, bugfixes, requirements…)

    View Slide

  139. Legacy Code 21.10.2016
    Compromise!
    Refactor one large piece into components.

    Favour piece by piece rewrite over big bang rewrite and rebuild incrementally.
    What's the cost of debt?
    Which parts are less critical?
    Think of extra costs for maintenance and extension caused by overly complex code.
    • focus on the important parts
    • recover knowledge which got lost in complex code
    • preserve investment which went into the code already (time, bugfixes, requirements…)

    View Slide

  140. Legacy Code 21.10.2016
    TL;DR
    technical debt is the main reason for legacy code

    treat your legacy and former developers with respect

    the business always wins* (changing requirements)

    keep your code well tested

    break dependencies and decouple business logic

    maintenance == refactoring (pay your debt!)


    View Slide

  141. Legacy (Rails) Code 24.05.2016
    Refactoring - Ruby Edition
    http://www.amazon.com/Refactoring-Ruby-Addison-Wesley-Professional/dp/0321984137
    TL;DR: http://ghendry.net/refactor.html
    Patterns of Enterprise Application Architecture
    http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/
    Working Effectively with Legacy Code
    http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052

    Golden Master Testing: Refactor Complicated Views Katrina Owen: July 09, 2014
    http://www.sitepoint.com/golden-master-testing-refactor-complicated-views/
    Rails Conf 2013 The Magic Tricks of Testing by Sandi Metz
    https://www.youtube.com/watch?v=URSWYvyc42M
    GORUCO 2009 - SOLID Object-Oriented Design by Sandi Metz
    https://www.youtube.com/watch?v=v-2yFMzxqwU
    Rocky Mountain Ruby 2012 - Go Ahead, Make a Mess by Sandi Metz
    https://www.youtube.com/watch?v=f5I1iyso29U

    RailsConf 2014 - Step-by-Step Refactoring Toward Ember by Brandon Hays

    https://www.youtube.com/watch?v=VMmaKj8hCR4
    Katrina Owen - 467 tests, 0 failures, 0 confidence - Railsberry 2013
    https://vimeo.com/68730418
    BathRuby 2015 - Here Be Dragons, Katrina Owen
    https://www.youtube.com/watch?v=QAUHYzC9kFM
    Cascadia Ruby Conf 2012 Therapeutic Refactoring by Katrina Owen
    https://www.youtube.com/watch?v=J4dlF0kcThQ
    RailsConf 2015 - Getting a Handle on Legacy Code
    https://www.youtube.com/watch?v=lsFFjFp7mEE
    MountainWest RubyConf 2015 - Data-Driven Refactoring
    https://www.youtube.com/watch?v=AcdliNixNhs
    Baruco 2013: Design Patterns And The Proper Cultivation Thereof, Corey Haines
    https://www.youtube.com/watch?v=vqN3TQgsXzI
    Rocky Mountain Ruby 2013 SOLID and TDD, Sitting in a by Mike Nicholaides
    https://www.youtube.com/watch?v=FidRcixHQos
    RubyConf 2009 - SOLID Ruby by: Jim Weirich
    https://www.youtube.com/watch?v=dKRbsE061u4
    content[:source]

    View Slide

  142. Legacy (Rails) Code 24.05.2016
    Have some
    #legacy
    #vintage 

    #oldtimer 

    #classic

    App we can help you with?

    View Slide

  143. Railslove
    We love to build the web.
    KTHXBYE
    Questions?
    Marco Schaden

    @donschado
    [email protected]
    24.05.2016

    View Slide