Jake Zimmerman
Getty D. Ritter
November 19, 2024
This dependency is 10 years out of date!
We need to change how we talk to the database!
…
Have one team drive the refactor:
concentrates expertise
most problems will be repeat problems
incentivizes automation
fewer engineer-hours overall
more likely to finish
no need to wait for each team to plan and prioritize
Leverage over the codebase
Way to ratchet incremental progress
To
you need to
and to
refactor a large, stubborn codebase
have a point of leverage
pick good ratchets.
Improving developer satisfaction with Sorbet
Making a Ruby monolith more modular
Lessons learned from ratchets ratcheted
“hard to understand”
“waiting for tests is slow”
“only breaks in production”
“don’t trust the docs”
“too much low-quality code”
(sentiment from company-wide survey)
“hard to understand”
“waiting for tests is slow”
“only breaks in production”
“don’t trust the docs”
“too much low-quality code”
→ IDE aids
understanding
→ all code type checks in
seconds
→ type checker catches bugs in
CI
→ runtime makes types
trustworthy
→ bad code is hard to
type
(sentiment from company-wide survey)
Timeline
Tools that you can use to bootstrap something:
# typed
comments# typed
comment at the top of each
file
# typed:
false
# typed:
true
# typed:
strict
→ just syntax and constants
→ inference in methods
→ every method needs a signature
typed:
false
→
true
Alternatives to # typed:
comment:
by folder → too broad
(not local enough, not incremental enough)
by coverage percent → too granular
(noisy, hard to action)
Developer satisfaction improved because
we
by
and
refactored a large, stubborn codebase
having a point of leverage (Sorbet)
picking good ratchets (# typed:
)
Improving developer satisfaction with Sorbet
Making a Ruby monolith more modular
Lessons learned from ratchets ratcheted
Tangled code is…
A drag on both developer velocity and runtime performance
The essential principle is that any element of a layer depends only on other elements in the same layer or on elements of the layer ’beneath’ it. Communication upward must pass through some indirect mechanism.
—Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software
strict_dependencies
'false'
'layered'
'layered'
'layered_dag'
'layered_dag'
'dag'
'dag'
strict_dependencies
strict_dependencies
'false'
strict_dependencies
'layered'
strict_dependencies
'layered_dag'
strict_dependencies
'dag'
Developer velocity and production latency are improving because
we
by
and
are modularizing a large, stubborn codebase
having a point of leverage (packages and
layering)
picking good ratchets
(strict_dependencies
)
false
→ true
→ strict
false
→
layered
→ layered_dag
→ dag
Improving developer satisfaction with Sorbet
Making a Ruby monolith more modular
Lessons learned from ratchets ratcheted
In theory, there is no difference between theory and practice. In practice, there is.
— Walter J. Savitch, relaying a quote overheard at a computer science conference
Important to have:
class MyPackage < PackageSpec
sorbet min_typed_level: 'strict', test_min_typed_level: 'true'
# ...
end
gen-packages
, for
automatically fixing up imports and exports
One team can
by
and
refactor a large, stubborn codebase
having a point of leverage
picking good ratchets
… and don’t forget to be patient—it’s hard work!