Escaping The Tar Pit at Solidus Conf 2019

Escaping The Tar Pit at Solidus Conf 2019

Presentation about avoiding and escaping the tar pit.

Introduction to the `skunk` gem. Talks a little bit about `flog`; `rubycritic`; `simplecov`; `reek`; and other tools you can use to get metrics related to the codebase.

F77032adcbe77d2777bb0e0c30873159?s=128

Ernesto Tagwerker

October 21, 2019
Tweet

Transcript

  1. 8.

    “No scene from prehistory is quite so vivid as that

    of the mortal struggles of great beasts in the tar pits. […] 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
  2. 9.

    “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
  3. 10.
  4. 11.
  5. 14.

    Tar Pit Symptoms > Projects running over budget > Taking

    forever to ship small changes > Sacrificing quality, increasing tech debt
  6. 16.

    “THAT’D BE GREAT” BOSS: “IF YOU COULD COME IN ON

    THIS GREAT, LEGACY PROJECT AND MAINTAIN IT FROM NOW ON…”
  7. 17.

    “THAT’D BE GREAT” CLIENT: “IF YOU COULD COME IN ON

    THIS GREAT, LEGACY PROJECT AND MAINTAIN IT FROM NOW ON…”
  8. 18.

    “BECAUSE I NEED IT BY END OF DAY TODAY” CLIENT:

    “HOW LONG IS IT GOING TO TAKE?”
  9. 23.
  10. 33.

    “The degree to which a system, component, or process meets

    implicit and explicit requirements.” IEEE
  11. 36.

    ISO 9126-1 Software Quality Model ✅ Reliability ✅ Usability ✅

    Efficiency ✅ Maintainability ✅ Portability
  12. 37.

    ISO 9126-1 Software Quality Model ✅ Reliability ✅ Usability ✅

    Efficiency ➡ Maintainability ✅ Portability
  13. 43.

    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
  14. 48.

    Code Quality n options (flog; flay; reek; churn; RubyCritic; MetricFu;

    attractor; rubocop; fukuzatsu; turbulence; …)
  15. 50.
  16. 51.
  17. 57.

    Complexity class Foo def yay # 11.2 = a =

    eval "1+1" # 1.2 + 6.0 + if a == 2 then # 1.2 + 1.2 + 0.4 + puts "yay" # 1.2 end end end
  18. 63.
  19. 70.

    100% 0% 1 100_000 “No one understands these files but

    they work. So don’t change them.” Complexity Churn
  20. 71.

    100% 0% 1 100_000 “[…], if the code never changes,

    it's not costing us money.” Sandi Metz Complexity Churn
  21. 73.

    100% 0% 1 100_000 “Everybody understands these files but you

    need to change them often because of reasons…” Complexity Churn
  22. 75.

    100% 0% 1 100_000 Complexity Churn “Here be dragons. These

    modules are complex and change a lot…” '
  23. 76.

    100% 0% 1 100_000 Complexity Churn “Sometimes a class becomes

    so complex that refactoring seems too difficult.” Michael Feathers
  24. 78.

    Are you getting into a tar pit, is it a

    dumpster fire, or have you found a project which is easy to maintain?
  25. 80.
  26. 93.

    foo.rb churn: 10 complexity: 10 smells: 10 smell: 1,000 (10*10*10)

    bar.rb churn: 10 complexity: 10 smells: 10 smell: 1,000 (10*10*10)
  27. 97.

    foo.rb churn: 10 complexity: 10 smells: 10 code_coverage: 0 stink_score:

    100,000 (10*10*10)*100 bar.rb churn: 10 complexity: 10 smells: 10 code_coverage: 100 stink_score: 1,000 (10*10*10)*1
  28. 102.
  29. 103.
  30. 104.

    Skunk $ skunk ... StinkScore Total: 13220.859999999997 Modules Analysed: 71

    StinkScore Average: 0.1862092957746 Worst StinkScore: 2401.75 (lib/rubycritic/source_control_systems/git.rb)
  31. 105.

    RubyCritic module RubyCritic class AnalysedModule def cost smells.map(&:cost).inject(0.0, :+) +

    # From Reek (complexity / COMPLEXITY_FACTOR) # From Flog end end end
  32. 106.

    Skunk module RubyCritic class AnalysedModule def stink_score return churn_times_cost if

    perfect_coverage? (churn_times_cost * (PERFECT_COVERAGE - coverage.to_i)) end def churn_times_cost safe_churn = churn > 0 ? churn : 1 safe_churn * cost end end end
  33. 107.

    Skunk module RubyCritic class AnalysedModule def stink_score return churn_times_cost if

    perfect_coverage? (churn_times_cost * (PERFECT_COVERAGE - coverage.to_i)) end def churn_times_cost safe_churn = churn > 0 ? churn : 1 safe_churn * cost end end end
  34. 115.
  35. 117.

    100% 0% 1 100_000 Complexity Churn “Here be dragons. These

    modules are complex and change a lot…” '
  36. 126.
  37. 130.
  38. 136.