$30 off During Our Annual Pro Sale. View Details »

A Brewer's Guide to Filtering out Complexity and Churn (RubyConf Mini 2022 Edition)

A Brewer's Guide to Filtering out Complexity and Churn (RubyConf Mini 2022 Edition)

RubyConf Mini 2022 presentation by Alan Ridlehoover & Fito von Zastrow

Mechanical coffee machines are amazing! You drop in a coin, listen for the clink, make a selection, and the machine springs to life, hissing, clicking, and whirring. Then the complex mechanical ballet ends, splashing that glorious, aromatic liquid into the cup. Ah! C’est magnifique!

There’s just one problem. Our customers also want soup! And, our machine is not extensible. So, we have a choice: we can add to the complexity of our machine by jamming in a new dispenser with each new request; or, we can pause to make our machine more extensible before development slows to a halt.

Here's the video of the talk: https://youtu.be/RJRSosxtzbU

Alan Ridlehoover
PRO

November 18, 2022
Tweet

More Decks by Alan Ridlehoover

Other Decks in Programming

Transcript

  1. Alan Ridlehoover & Fito von Zastrow
    RubyConf Mini 2022
    The Coffee
    Machine Talk
    A Brewer’s Guide to Filtering out
    Complexity and Churn

    View Slide

  2. PRONOUNS

    he/him/his

    HOMETOWN

    Asunción

    RUBY EXPERIENCE

    12 years

    FAVORITE COFFEE

    Ghirardelli Dark
    Chocolate Mocha
    PRONOUNS

    he/him/his

    HOMETOWN

    Seattle

    RUBY EXPERIENCE

    12 years

    FAVORITE COFFEE

    New Orleans Cold
    Brew w/ Chicory

    View Slide

  3. View Slide

  4. 🤲

    View Slide

  5. View Slide

  6. View Slide

  7. 👍

    View Slide

  8. How did we get here?
    How complexity sneaks into a code base.

    View Slide

  9. ☕ Story: As a patron, I want coffee
    class CoffeeMachine


    def vend


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispose_of_grounds


    end


    end

    View Slide

  10. ☕ Story: As a patron, I want tea
    class CoffeeMachine


    def vend(drink: :coffee)


    if drink == :coffee


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispose_of_grounds


    elsif drink == :tea


    dispense_cup


    dispense_tea_bag


    heat_water


    dispense_water


    end


    end


    end

    View Slide

  11. ☕ Refactor: DRY up the code
    class CoffeeMachine


    def vend(drink: :coffee)


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispose_of_grounds if drink == :coffee


    end


    end


    View Slide

  12. ☕ Story: As a patron, I want sweetener
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispense_sweetener if options[:sweet]


    dispose_of_grounds if drink == :coffee


    end


    end

    View Slide

  13. ☕ Story: As a patron, I want cream
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_cream if options[:creamy]


    dispose_of_grounds if drink == :coffee


    end


    end


    View Slide

  14. ☕ Story: As a patron, I want cocoa
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end

    View Slide

  15. ☕ Story: As a patron, I want whipped cream
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    unless drink == :tea


    dispense_whipped_cream if options[:fluffy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end

    View Slide

  16. Do you smell that?
    How to recognize the problem before it
    becomes painful and frustrating.
    Rules by Sandi Metz Flog by Ryan Davis

    View Slide

  17. ☕ Measuring complexity with the flog gem
    Score of Means


    - - - - - - - - - - - - - - - - - - - - - - - - -


    0-10 Awesome


    11-20 Good enough


    21-40 Might need refactoring


    41-60 Possible to justify


    61-100 Danger


    100-200 Whoop, whoop, whoop


    200 + Someone please think of the children


    (note: these are scores for an individual method)


    What's a good
    fl
    og score? by Jake Scruggs

    View Slide

  18. ☕ Story: As a patron, I want coffee
    class CoffeeMachine


    def vend


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispose_of_grounds


    end


    end
    Churn

    1
    Complexity

    5.5
    10
    20
    30
    25
    15
    5
    0

    View Slide

  19. ☕ Story: As a patron, I want tea
    class CoffeeMachine


    def vend(drink: :coffee)


    if drink == :coffee


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispose_of_grounds


    elsif drink == :tea


    dispense_cup


    dispense_tea_bag


    heat_water


    dispense_water


    end


    end


    end
    Churn

    2
    Complexity

    14.6
    10
    20
    30
    25
    15
    5
    0

    View Slide

  20. ☕ Refactor: DRY up the code
    class CoffeeMachine


    def vend(drink: :coffee)


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispose_of_grounds if drink == :coffee


    end


    end


    Churn

    3
    Complexity

    10.9
    10
    20
    30
    25
    15
    5
    0

    View Slide

  21. ☕ Story: As a patron, I want sweetener
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispense_sweetener if options[:sweet]


    dispose_of_grounds if drink == :coffee


    end


    end
    Churn

    4
    Complexity

    13.5
    10
    20
    30
    25
    15
    5
    0

    View Slide

  22. ☕ Story: As a patron, I want cream
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    end


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_cream if options[:creamy]


    dispose_of_grounds if drink == :coffee


    end


    end


    Churn

    5
    Complexity

    16.0
    10
    20
    30
    25
    15
    5
    0

    View Slide

  23. ☕ Story: As a patron, I want cocoa
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end
    Churn

    6
    Complexity

    21.3
    10
    20
    30
    25
    15
    5
    0

    View Slide

  24. ☕ Story: As a patron, I want whipped cream
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    unless drink == :tea


    dispense_whipped_cream if options[:fluffy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end
    Churn

    7
    Complexity

    25.5
    10
    20
    30
    25
    15
    5
    0

    View Slide

  25. ☕ CoffeeMachine Pain Index over time
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    unless drink == :tea


    dispense_whipped_cream if options[:fluffy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end
    Churn

    7
    Complexity

    25.5
    10
    20
    30
    25
    15
    5
    0

    View Slide

  26. ☕ CoffeeMachine Pain Index over time
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    unless drink == :tea


    dispense_whipped_cream if options[:fluffy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end
    Churn

    7
    Complexity

    25.5
    10
    20
    30
    25
    15
    5
    0

    View Slide

  27. Can we turn it around?
    How to
    fi
    lter out complexity and churn.

    View Slide

  28. ☕ Refactor: Rehydrate to see missing abstractions
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    dispense_cup


    heat_water


    if drink == :coffee


    prepare_grounds


    elsif drink == :tea


    dispense_tea_bag


    elsif drink == :cocoa


    dispense_cocoa_mix


    end


    dispense_water


    unless drink == :cocoa


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    unless drink == :tea


    dispense_whipped_cream if options[:fluffy]


    end


    dispose_of_grounds if drink == :coffee


    end


    end

    View Slide

  29. ☕ Refactor: Rehydrate to see missing abstractions
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    if drink == :coffee


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    elsif drink == :tea


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    elsif drink == :cocoa


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end


    end

    View Slide

  30. ☕ Refactor: Extract polymorphic objects
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    if drink == :coffee


    Coffee.new(options: options).prepare


    elsif drink == :tea


    Tea.new(options: options).prepare


    elsif drink == :cocoa


    Cocoa.new(options: options).prepare


    end


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  31. ☕ Refactor: Extract polymorphic objects
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    if drink == :coffee


    Coffee.new(options: options).prepare


    elsif drink == :tea


    Tea.new(options: options).prepare


    elsif drink == :cocoa


    Cocoa.new(options: options).prepare


    end


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  32. ☕ Refactor: Extract factory class
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    BeverageFactory.build(drink, options).prepare


    end


    end


    class BeverageFactory


    def self.build(drink, options)


    if drink == :coffee


    Coffee.new(options: options)


    elsif drink == :tea


    Tea.new(options: options)


    elsif drink == :cocoa


    Cocoa.new(options: options)


    end


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  33. ☕ Refactor: Extract factory class
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    BeverageFactory.build(drink, options).prepare


    end


    end


    class BeverageFactory


    def self.build(drink, options)


    if drink == :coffee


    Coffee.new(options: options)


    elsif drink == :tea


    Tea.new(options: options)


    elsif drink == :cocoa


    Cocoa.new(options: options)


    else


    NullBeverage.new(options: options)


    end


    end


    end


    class NullBeverage


    def prepare


    # no-op


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  34. ☕ Refactor: Use convention to prevent churn
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    BeverageFactory.build(drink, options).prepare


    end


    end


    class BeverageFactory


    def self.build(drink, options)


    klass = drink.capitalize


    if Module.const_defined?(klass)


    Module.const_get(klass).new(options: options)


    else


    NullBeverage.new(options: options)


    end


    end


    end


    class NullBeverage


    def prepare


    # no-op


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  35. ☕ Complexity of the CoffeeMachine class over time
    Rehydrate
    Extract Classes
    Introduce Factory
    Whipped Cream
    Cocoa
    Cream
    Sweetener
    DRY
    Tea
    Co
    ff
    ee
    10
    20
    30
    25
    15
    5
    0
    40
    35

    View Slide

  36. ☕ Complexity of the CoffeeMachine class over time
    Rehydrate
    Extract Classes
    Introduce Factory
    Whipped Cream
    Cocoa
    Cream
    Sweetener
    DRY
    Tea
    Co
    ff
    ee
    10
    20
    30
    25
    15
    5
    0
    40
    35

    View Slide

  37. ☕ Complexity of the CoffeeMachine class over time
    Rehydrate
    Extract Classes
    Introduce Factory
    Whipped Cream
    Cocoa
    Cream
    Sweetener
    DRY
    Tea
    Co
    ff
    ee
    10
    20
    30
    25
    15
    5
    0
    40
    35

    View Slide

  38. ☕ Complexity of the CoffeeMachine class over time
    Rehydrate
    Extract Classes
    Introduce Factory
    Whipped Cream
    Cocoa
    Cream
    Sweetener
    DRY
    Tea
    Co
    ff
    ee
    10
    20
    30
    25
    15
    5
    0
    40
    35

    View Slide

  39. ☕ Complexity of the application
    Class Churn Complexity


    --------------------- ----- ----------


    CoffeeMachine#vend 10 3.9


    BeverageFactory#build 2 6.2


    Coffee#prepare 1 16.6


    Tea#prepare 1 11.8


    Cocoa#prepare 1 8.1


    NullBeverage#prepare 1 0.0

    View Slide

  40. How to add functionality without modifying existing
    fi
    les.
    Now, who wants ?

    View Slide

  41. ☕ Refactor: Use convention to prevent churn
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    BeverageFactory.build(drink, options).prepare


    end


    end


    class BeverageFactory


    def self.build(drink, options)


    klass = drink.capitalize


    if Module.const_defined?(klass)


    Module.const_get(klass).new(options: options)


    else


    NullBeverage.new(options: options)


    end


    end


    end


    class NullBeverage


    def prepare


    # no-op


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  42. ☕ Refactor: Use convention to prevent churn
    class CoffeeMachine


    def vend(drink: :coffee, options: {})


    BeverageFactory.build(drink, options).prepare


    end


    end


    class BeverageFactory


    def self.build(drink, options)


    klass = drink.capitalize


    if Module.const_defined?(klass)


    Module.const_get(klass).new(options: options)


    else


    NullBeverage.new(options: options)


    end


    end


    end


    class NullBeverage


    def prepare


    # no-op


    end


    end


    class Soup


    def prepare


    dispense_cup


    heat_water


    dispense_condensed_soup


    dispense_water


    dispense_croutons if options[:crunchy]


    dispense_hot_sauce if options[:spicy]


    end


    end
    class Coffee


    def prepare


    dispense_cup


    heat_water


    prepare_grounds


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    dispense_whipped_cream if options[:fluffy]


    dispose_of_grounds


    end


    end


    class Tea


    def prepare


    dispense_cup


    heat_water


    dispense_tea_bag


    dispense_water


    dispense_sweetener if options[:sweet]


    dispense_creamer if options[:creamy]


    end


    end


    class Cocoa


    def prepare


    dispense_cup


    heat_water


    dispense_cocoa_mix


    dispense_water


    dispense_whipped_cream if options[:fluffy]


    end


    end

    View Slide

  43. Yeah, but does it scale?
    How to apply this to a large, complicated code base.

    View Slide

  44. ☕ Plotting complexity vs. churn
    Churn
    Complexity
    Getting Empirical about Refactoring by Michael Feathers

    View Slide

  45. ☕ Plotting complexity vs. churn
    Pain Free
    Churn
    Complexity

    View Slide

  46. ☕ Plotting complexity vs. churn
    Pain Free
    Painful
    Churn
    Complexity

    View Slide

  47. Pain Free
    ☕ Plotting complexity vs. churn
    Painful
    Configuration?
    Churn
    Complexity

    View Slide

  48. ☕ Plotting complexity vs. churn
    Pain Free
    Painful
    Configuration?
    Omega Mess?
    Churn
    Complexity
    Go Ahead, Make a Mess by Sandi Metz

    View Slide

  49. ☕ Plotting complexity vs. churn
    Churn
    Complexity

    View Slide

  50. Conclusion
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  51. Take Aways
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  52. Take Aways
    A Brewer’s Guide to Filtering out Complexity and Churn
    Complexity will sneak into your code.
    • Happens one commit at a time
    • Conditionals and DRY are often the culprits

    View Slide

  53. Take Aways
    A Brewer’s Guide to Filtering out Complexity and Churn
    You can recognize complexity before it becomes painful.
    • Keep methods short
    • Watch complexity
    • Pay attention to how it feels
    Complexity will sneak into your code.
    • Happens one commit at a time
    • Conditionals and DRY are often the culprits

    View Slide

  54. Take Aways
    A Brewer’s Guide to Filtering out Complexity and Churn
    You can recognize complexity before it becomes painful.
    • Keep methods short
    • Watch complexity
    • Pay attention to how it feels
    And, you can back away from painful complexity.
    • Polymorphism and factories are your friends
    • Overly DRY code can hide abstractions and couple algorithms in dangerous ways
    Complexity will sneak into your code.
    • Happens one commit at a time
    • Conditionals and DRY are often the culprits

    View Slide

  55. Homework
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  56. Homework
    What is the average method complexity for your application?
    • Use the Flog gem to measure complexity
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  57. Homework
    What is the
    fi
    le with the most churn in your application?
    • Use the Churn gem to measure churn
    What is the average method complexity for your application?
    • Use the Flog gem to measure complexity
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  58. Homework
    What is the
    fi
    le with the most churn in your application?
    • Use the Churn gem to measure churn
    Which class in your application needs the most attention?
    • Use the Ruby Critic gem to plot complexity vs. churn
    • Look for the
    fi
    le with the highest complexity and churn
    What is the average method complexity for your application?
    • Use the Flog gem to measure complexity
    A Brewer’s Guide to Filtering out Complexity and Churn

    View Slide

  59. EMAIL

    fi
    [email protected]
    GITHUB

    @Fito

    TWITTER

    @
    fi
    to.vonzastrow
    EMAIL

    [email protected]

    GITHUB

    @aridlehoover

    TWITTER

    @aridlehoover

    BLOG

    the.codegardener.com
    GITHUB REPO

    https://github.com/
    fi
    rst-try-software/co
    ff
    ee
    Get in touch!
    SLACK CHANNEL

    #a-brewers-guide-to-
    fi
    ltering-out-complexity-and-churn

    View Slide

  60. Ruby Flog
    Ruby Flog
    VS Code extension that puts
    fl
    og scores in your status bar

    View Slide

  61. Thanks for coming!
    A Brewer’s Guide to Filtering out Complexity and Churn
    Sandi Metz
    • Practical Object Oriented Design in Ruby (book)

    • 99 Bottles of OOP (book) (sample on the topic of measuring complexity)

    • Rules: https://youtu.be/npOGOmkxuio

    • Go Ahead, Make a Mess: https://youtu.be/mpA2F1In41w

    Ryan Davis
    • Flog: https://github.com/seattlerb/
    fl
    og
    Jake Scruggs
    • https://jakescruggs.blogspot.com/2008/08/whats-good-
    fl
    og-score.html

    Michael Feathers
    • Working E
    ff
    ectively with Legacy Code (book)

    • https://www.agileconnection.com/article/getting-empirical-about-refactoring

    Alan Ridlehoover & Fito von Zastrow
    • Ruby Flog: https://marketplace.visualstudio.com/items?itemName=
    fi
    rst-try-software.ruby-
    fl
    og

    View Slide