Dennis Doomen discusses key principles for maintainable code, including isolation, testability, being diagnosable, traceability, readability, and discoverability. The goal is code that can be changed confidently by any developer on a team without fear and has a low cognitive load for readers to understand. Dennis Doomen is focused on continuously improving code through these principles.
Lessons learned from two decades of professional software development
1. Dennis Doomen | @ddoomen | Aviva Solutions | The Continuous Improver
2.
3.
4.
5.
6.
7.
8. Isolation
(can I do this without affecting anything else)
Testability
(is it doing what it is supposed to do)
Diagnosable
(why and when did this happen)
Traceability
(why did we do this)
Readability of code
(what does it try do and how)
Discoverability
(where is this done)
9.
10.
11.
12.
13.
14.
15.
16.
17.
18. "Code that can be changed by any developer
in the team without fear and with
confidence"
"Has a low cognitive load. The energy needed
by your brain to read and comprehend the
code"
Understand the context of when a tool, practice or principle applies and when not. Don't reject it because of misuse (e.g. IoC, OR/M, DRY, TDD).
Design patterns are communication tools, not goals on itself
Gut feelings are really Design Heuristics
Heuristics are ideas or experiences that give progress, but no guarantee
Monolith can't be avoided, unless you overengineer.
A long-living monolith is a testament for success.
There's too much knowledge hidden in that old code.
The new system may never catch up the old one
It'll cost too much capacity to maintain old and new
Instead, rebuild pieces bit by bit in the same code-base
Don't hide the magic
Avoid inheritance
Control dependencies
Explicit ownership of each repository
Adopt Github
Contribution through pull requests
Standardize read-me explaining code of conduct for contributions
Captures important decisions and changes
What was the problem, what were the options, what was chosen en why and what does it mean for other devs
Technology is almost never a solution to a problem (except for OWIN, Git, .NET Core). Unless you rebuild a piece
Be consistent within a boundary, don't bother outside (allow different patterns for different solutions)
Architectural seams
Understand the layers of testing
Test the boundary, not the internals
Clear cause and effect
Show what's important. Hide what's not.
Avoid DRY
Makes it easier to rebuild pieces
Avoids too much coupling
Consider DIP
No common/foundation/shared stuff
Be consistent within a boundary, don't bother outside (allow different patterns for different solutions)
Reads like a book
Acknowledges the Magic Number of Seven
Code explains the what and how..
…so doesn't obscure the algorithms
Aligns code with the boundaries
Don't use static mutable state
May seem convenient, but they hurt you
Build local as you build remote
Treat your build process as first-class citizens
PSake, Cake or Nuke
Clear Source Control History
Track the why of a changeset/commit, not just the what
Separate refactoings from functional changes
Don't squash unrelated changes
You are not the only audience
Logging statements
Exceptions
Configuration surface
You are not the only audience
Logging statements
Exceptions
Configuration surface
You are not the only audience
Logging statements
Exceptions
Configuration surface
After 1.0, be responsible
Choose a release strategy
Apply SemVer
Avoid breaking changes
Document your code
Understand the audience and accuracy of your documentation
Technical Debt is inevitable. Plan for it. (e.g. 20% per release)
Keep refactoring -> code rot => boy scout rule
Natural Cause of Refactoring
Work with somebody that has radical/out-of-the-box ideas and then find a middle ground
Don't take anything at face value (especially speakers at conferences and events)