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

Escaping The Tar Pit at NYC.rb

Escaping The Tar Pit at NYC.rb

Nobody wants to inherit a project that reeks but here we are: Stuck in the tar pit. How can we get out? Could we have avoided it in the first place?

In this talk you will learn how to use a few, great Ruby gems that will guide you out of that sticky tar you are in. On top of that, you will learn a repeatable way to gradually pay off technical debt.

Ernesto Tagwerker

May 13, 2020
Tweet

More Decks by Ernesto Tagwerker

Other Decks in Programming

Transcript

  1. “Large-system programming has over the past decade been such a

    tar pit, and many great and powerful beasts have thrashed violently in it.” Fred Brooks
  2. “The fiercer the struggle, the more entangling the tar, and

    no beast is so strong or so skillful but that they ultimately sink.” Fred Brooks
  3. Tar Pit Symptoms > Projects running over budget > Taking

    forever to ship small changes > Sacrificing quality, increasing tech debt
  4. “THAT’D BE GREAT” BOSS: “IF YOU COULD COME IN ON

    THIS GREAT, LEGACY PROJECT AND MAINTAIN IT FROM NOW ON…”
  5. “THAT’D BE GREAT” CLIENT: “IF YOU COULD COME IN ON

    THIS GREAT, LEGACY PROJECT AND MAINTAIN IT FROM NOW ON…”
  6. “BECAUSE I NEED IT BY END OF DAY TODAY” CLIENT:

    “HOW LONG IS IT GOING TO TAKE?”
  7. “The degree to which a system, component, or process meets

    implicit and explicit requirements.” IEEE
  8. ISO 9126-1 Software Quality Model ✅ Reliability ✅ Usability ✅

    Efficiency ✅ Maintainability ✅ Portability
  9. ISO 9126-1 Software Quality Model ✅ Reliability ✅ Usability ✅

    Efficiency ➡ Maintainability ✅ Portability
  10. Code Coverage # spec/spec_helper.rb if ENV["COVERAGE"] == "true" require 'simplecov'

    SimpleCov.start do add_group "Models", "models" add_filter "/spec/" track_files "**/*.rb" end end
  11. Code Quality n options (flog; flay; reek; churn; RubyCritic; MetricFu;

    attractor; rubocop; fukuzatsu; turbulence; …)
  12. Complexity class Default def yay # 10.8 = a =

    eval "1+1" # 1.2 + 6.0 + if a == 2 # 1.2 + 1.2 + puts "yay" # 1.2 end end end
  13. 100 0 1 100_000 No one understands these files but

    they work. So don’t change them. Complexity Churn
  14. 100 0 1 100_000 “[…], if the code never changes,

    it's not costing us money.” Sandi Metz Complexity Churn
  15. 100 0 1 100_000 Everybody understands these files but you

    need to change them often Complexity Churn
  16. 100 0 1 100_000 Complexity Churn “Sometimes a class becomes

    so complex that refactoring seems too difficult.” Michael Feathers
  17. Are you getting into a tar pit, is it a

    dumpster fire, or have you found a project which is easy to maintain?
  18. user.rb complexity: 10 smells: 10 smell points: 100 (10*10) shop.rb

    complexity: 10 smells: 10 smell points: 100 (10*10)
  19. user.rb complexity: 10 smells: 10 code_coverage: 0 skunk_score: 10,000 (10*10)*100

    shop.rb complexity: 10 smells: 10 code_coverage: 100 skunk_score: 100 (10*10)*1
  20. user.rb complexity: 10 smells: 10 code_coverage: 0 skunk_score: 10,000 (10*10)*100

    We should write some tests for user.rb shop.rb complexity: 10 smells: 10 code_coverage: 100 skunk_score: 100 (10*10)*1
  21. Skunk $ skunk ... SkunkScore Total: 13231.069999999996 Modules Analysed: 71

    SkunkScore Average: 186.3530985915493 Worst SkunkScore: 2401.75 (lib/rubycritic/source_control_systems/git.rb)
  22. Skunk $ skunk ... SkunkScore Total: 13231.069999999996 Modules Analysed: 71

    SkunkScore Average: 186.3530985915493 Worst SkunkScore: 2401.75 (lib/rubycritic/source_control_systems/git.rb)
  23. RubyCritic module RubyCritic class AnalysedModule def cost smells.map(&:cost).inject(0.0, :+) +

    # From Reek (complexity / COMPLEXITY_FACTOR) # From Flog end end end
  24. Skunk module RubyCritic class AnalysedModule def skunk_score return cost if

    perfect_coverage? cost * (PERFECT_COVERAGE - coverage.to_i) end end end
  25. Skunk module RubyCritic class AnalysedModule def skunk_score return cost if

    perfect_coverage? cost * (PERFECT_COVERAGE - coverage.to_i) # Penalty Factor = 100% - 20% => 80 end end end
  26. Skunk $ skunk -b master Base branch (master) average skunk

    score: 79.78 Feature branch (refactor/git) average skunk score: 71.79
  27. Skunk $ skunk -b master Base branch (master) average skunk

    score: 79.78 Feature branch (refactor/git) average skunk score: 71.79 10% better