Code that fits in your Head #1
Starting strong on our first #speakingsoftwarebookbridge book pick, I'd like to relay some of my initial impressions and insights.
Our first pick is "Code That Fits in Your Head: Heuristics for Software Engineering" by Mark Seemann, and it's a fantastic read!
As per the title: this book is about software heuristics: there's no "1 true way" or hard-rules talk, which is VERY refreshing. Many software tomes go too deep into their preferred way dogmatically, and it can be off-putting. The heuristics here are a set of strategies that you can opt into, and mix'n'match to help keep your project on a good path.
It's interesting how Mark tries to dispel the traditional thinking about writing software. It's not a building a skyscraper, or a growing a garden, or like brain; it's intangible. It's a craft; an art even. You'll need to use your own eyes, experience and judgement; not just cling to the same old patterns and rules.
The first heuristic we come across is Checklists. Pilots use them. Surgeons use them. Why not Software Engineers, right? Mark gives an example specifically around starting a new code base:
Use Git
Automate the build
Turn on all error messages
You get your CI/CD Pipeline, Version control and quality checks together at the start of a project. This allows you to start off on the right foot. These can be VERY hard to shoehorn in correctly later!
Funnily enough, I had put together a checklist on my team for our Pull Requests:
Does the code adhere to our naming conventions and coding guidelines?
Is the code put in the correct place? e.g. Separation of concerns
Does the code adhere to SOLID principles, and 'fit' with the patterns and structure of the rest of the code base?
Are there new, or updated, unit/integration tests?
Are any assumptions made that bite us later? E.g. never expecting more than X Elements in a collection/view, etc.
Going back to Mark's example in regards to turning on all error messages: you should treat all Warnings as Errors. When it comes to tools like Linters, Static Analysis, Compiler warnings - use as many as possible. Set them up as strict as you can, and fix all issues at the very start of the project. It's very easy to then continue the trend! 2-3 issues to be fixed today are much easier then turning all of this on later, and being both build-blocked and overwhelmed by 1000s of errors.
If you do decide to do this later in a project's life-cycle, it's not the end of the world though. You can configure which rules are active, and apply them, piecemeal:
Turn on one additional rule
Solve all offences
Commit & Push (kicking off the automated build)
On successful automated build: Rinse and Repeat, until all possible rules are active.
Whether activating from the start or half-way, this result of all of this is that it automates a subjective (human) synchronous quality-gate by turning it into an automated (machine) asynchronous quality-gate. It frees up Developers to think about bigger problems that require more craft and creativity. They can turn towards solving the business requirements instead of doing shallow work.
As an aside, in all my years; I've never seen project with these tools active and implemented that was either unstable or buggy.
Software Development as a craft is more than checklists or automation! It's also more than writing code. In reality, you'll spend way more time reading code then you ever will writing - by several magnitudes. That maybe hints that: when you write code, you should optimize for readability.
Martin Fowler says it succinctly:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
The challenge when writing good code (for humans) is that you need to understand the limits of the human mind. 7 things (+/- 2) is the rule of what we can fit in our head (Miller's law). That means you should be writing smaller, self-contained functions, using less dependencies, less variables, and writing simpler code. If we don't pay attention, we can easily write software that exceeds what we can reasonably mentally handle. In this way, code that could be an asset becomes a liability.
A battle against complexity is a battle for maintainability, ease-of-understanding, and application stability. It's always a worthy fight!
Loving what I'm reading so far! Spoiler, it's not my first read-through, but I'm always picking up new nuggets of wisdom as I revise.
What about you? How is your reading going; on target to finish by Feb 29th? Let us know about your progress and what you've learned so far!
Originally posted here.