Book Review: Code that fits in your Head
The first book for our #speakingsoftwarebookbridge project was "Code That Fits in Your Head: Heuristics for Software Engineering" by Mark Seemann. Coming in at a hefty 400 pages; it’s no bedtime read! However, it is an invaluable book to have on your shelf - preferably always within arms’ reach of your computer…
Intro
This is a thick tome of rules-of-thumb for writing software. It wants you to think of that act of writing software as an art or craft - not a factory or a garden. The rules are presented almost in a building-block fashion, so that you could apply them piece-by-piece over time.
While it does indeed deliver some great practices, it also acknowledges that dogmatically following rules will only get you so far. Sometimes you just have to rely on your own knowledge, experience, and intuition (the "shifting sands of individual experience" as Mark calls it) in order to work out the best possible implementation.
In terms of implementations, the approach the book recommends when writing code can basically be summarized as: "Look after the pennies, and the pounds will look after themselves". We'll tap more into that in a minute!
Johnny?
When dealing with software, what ultimately slows down and stalls development is complexity. This just doesn't happen over night. It's months and years of rot, surprise, unintentional neglect, and patching that accumulates cruft and holes over time. It can happen to any team, regardless of competency or intention. Teams have to actively prevent code from rotting.
Mark's ultimate goal with this book is to help you manage complexity, by keeping a watchful eye on dependencies, responsibilities, separation of concerns, fostering stronger adherence to processes (via checklists), measuring complexity, and understanding how to compose and decompose 'units' of software.
While the practices mentioned here are applicable across any modern language, all examples in the book are in C#. The examples are quite concise and readable, so if you're not a .net developer you shouldn't be put off!
On a side note: I'd like to make this obligatory reading for all of my teams. Sorry Catalyst crew!
KISS - Keep it sustainable, stupid!
The book's title and theme - "Software that fits on your head" taps into Miller's law. That is that the average number of objects an average human can hold in short-term memory is 7 (±2). By writing software that takes this into account, and prioritizing the reader, you maximize their ability to understand what is happening in the code base. You write simpler code, enabling later contributors to continue to deliver in the most simplistic fashion possible.
The end-goal here is to make your software sustainable. Never again will your dev team by held hostage by an entrenched ogre, or a project shuttered due to a stilted SME walking away. All teammates are empowered to pitch in. Clients and end-users alike will be delighted that system stability is solid; thanks to clear, easy-to-understand implementations.
Building simple software in this manner can be accomplished by some easy steps:
Take 1 conclusive step in the right direction, and slowly repeat
When repeating, make critical decisions at every one of those steps
Use 'drivers' to inform what steps to take
Don't get married to your implementation.
Small changes are easier to rollback/modify than massive sweeping features/refactorings
If you consistently apply this approach, you are absolutely on your way to software success! A cautionary note though - don't sprint to the end goal; even if you know what it is supposed to look like. This type of thinking will definitely put off more Senior Developers, as they'll correctly see it slows them down.
The book strongly pushes you to "develop slower; deliver faster". It's a mature stand-point, and honestly it's refreshing. A lot of software books and training materials forget that the action of coding doesn't happen in a vacuum. Time, deadlines, competency, trade-offs, etc, are all part of "real-world" coding. Not every developer has endless time to implement features perfectly. Build in self-contained steps to avoid merge issues, long-running feature branches and merge-hell.
Change is to be small and constant.
Something that I liked about Mark's approach was about having drivers - basically clear motivations for changing or writing code. Some examples of drivers can be linters, static analysis tools, but also a coding methodology like DDD/BDD/TDD. The idea being that you interact with the driver(s), and they prompt you to modify the code. As long as you have (at least) 1 driver for writing code, that is what pushes the progress forward cm-by-cm, then m-by-m and soon km-by-km.
Teamwork
He also speaks of software being a team sport (which many curmudgeonly Seniors I've worked with love to deny!) and brings some real, usable tactics. For example:
Commit and integrate often. Maximum every 4 hours if possible! Nobody should sit on something for more than half a day.
2-week-sprint Developers may balk and wretch at this, but it's actually quite easy to hide incomplete implementations behind features-flags or the strangler fig pattern. Clients won’t see incomplete features, don’t worry!
Doing this allows the team visibility of the implementation as it progresses, and more allows testing of those features in the CI Pipeline while not compromising production. This keeps Production stable, but also keeps an eye on continuously inspecting quality as deliverables are being crafted. As features/refactoring meet maturity, you can safely test and enable them piecemeal. Upon success, the feature-flag code can be deleted and you have a clean code base.
During this process, I was never more then five minutes from being able to do a commit, and all commits left the system in a consistent state that could be integrated and deployed
Agility Inside
The maxim throughout is that you do not need to move from 1 absolute complete finalized state to another. You can safely inch forward, and keep Prod stable and continuously crawl towards finalized implementations step-by-step - maximizing you maneuverability as you go.
The slow, "stepped" approach lets you drop what you're doing to pivot to another angle or task as priorities change. You gain agility and maneuverability, without sacrificing system stability, or losing work.
Meaning
Some of my favorite quotes, that really give a flavor for the book's raison d'etre:
"Small improvements, continuously delivered, inch closer towards a useful system"
"I constantly have to remind developers to slow down"
"The more lines of code, the worse the code base."
"You have to actively prevent code from rotting. You pay attention by measuring various metrics [...] but ultimately you must use your own judgement."
"Designs APIs so that they make illegal states unrepresentable. If a state is invalid, it's best to design the API so that its impossible top express it in code. [...] A compiler error gives you faster feedback than a runtime exception."
"For any significant change, don't make it in-place; make it side-by-side."
"In software development, later is never."
Pros
A complete github example repo, with meaningful comments.
The final chapter is dedicated to walking through it!
Hierarchies of importance when implementing rules
Small meaningful code snippets, and not multi-page classes with 100s of lines
Acknowledges that technical terms are vague and can have multiple meanings.
API, Component, etc.. (I don't see this said enough in tech!)
Stresses the importance of teamwork and experience
Encouraging voice instead of a dogmatic tutelage. There's no ivory tower here!
Summary
It's not often I read books and wish I read them 10 years ago. This is one of those books. It IS a hefty tome, but there's nothing dry about it's content, and every chapter brings value hand-over-fist on every re-read. Every 6-12 months it’s worth another flick through, just to keep the principles fresh in your mind.
Definitely one that every developer should get a copy of; the earlier in their career - the better!