My journey in the world of software has been quite brief.
I joined the industry roughly three years ago, as a not-yet-graduated mathematician converted to ML practioner. It took me another two years to find myself in a position where building software was my main occupation.
I owe loads to many awesome individuals I have met and worked with along this short walk of life.
I owe loads as well to many others who I will probably never meet - the authors of the books I fed upon along the way.
First-hand experience is extremely powerful, nonetheless time is finite.
Books gave me a chance to tap into the compressed mastery of other practiotioners, a mastery built over thousands and thousands of hours of work. If you could only absorb 10% of that knowledge by reading it would still be a bargain.
As I find myself moving from the mentee to the mentor seat in some of my professional relationships, I do happen to share more and more often lists of titles that I found useful on my own journey.
Publishing this list as a public blog post will likely increase its reach and prove useful to many others.
- Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems by Martin Kleppmann
This book is dense.
It’s packed with foundational material and it manages to combine a first-principles approach with a focus on the impact of those decisions on the engineering choices behind real-world large-scale distributed systems.
I do go back to it from time to time, to re-read a chapter, re-study a set of concepts.
I just love it.
- Cloud Native Patterns: Designing change-tolerant software by Cornelia Davis
I never believed the digital native narrative, but it’s indeed true that as a software engineer I am Cloud native. All the systems I have been working with have always been designed, hosted and operated in the Cloud since day 0.
Cornelia Davis did a very good job at putting together a primer on the patterns and techniques that you should have in your toolbox when designing increasingly-complex Cloud native applications.
I recommend it often as a first read on real-world distributed systems.
The book on DDD, also known as The Big Blue Book.
It’s long but it covers an insane amount of material: if you are in the business of writing enterprise software, it’s a must-read.
Translating the rules and the mental model of a complex business domain into sofware is indeed the core of the challenge when writing enterprise software.
The techniques and the terminology introduced by Evans will pay dividends as the complexity of the domain you are tackling and the organisation you are working in increases. Different people have suggested me a shorter introduction to the subject, Domain-Driven Design Distilled by Vaughn Vernon, but I haven’t read it first hand.
- Domain Modeling Made Functional by Scott Wlaschin
I discovered this book looking up the author from a talk of his - I loved the talk and I loved the book.
It’s on its own a good introduction to DDD as well as to the broader topic of type-driven development.
In a nutshell, we can leverage the type system to represent the constraints of our domain, making incorrect state difficult or impossible to represent.
The book presents the idea in the context of functional programming, but it’s indeed viable even with non-strictly-functional programming languages as long as they have a rich typesystem (e.g. Rust).
If you find the idea interesting, the author’s website is a gold mine.
If you want a blog-sized introduction to the topic, check Parse, don’t validate by Alexis King.
- Test Driven Development: by Example by Kent Beck
There is a general appreciation in our industry around Test Driven Development. Nonetheless, I haven’t met many practioners who actually run it by the book, for all sorts of reasons.
Before taking a stance on the matter I wanted to see it done religiously. Short on neighbours, I turned to the author himself: Kent Beck is the creator of XP (Xtreme Programming), one the main voices of TDD as well as one of the authours of the Agile manifesto.
The book is nothing more nothing less than a long pair programming session with him, as he works his way using TDD through a problem (i.e. writing a testing framework - there is a meta element at play here).
You are an observer - as a reader you don’t get to play ping-pong with him; yet, it’s worth reading to actually see what TDD looks and feels like.
- Working Effectively with Legacy Code by Michael Feathers
I have come to appreciate that software is more often read than written. As it often goes, the author has generally moved on (either in another area of the business or somewhere else entirely). Yet the system keeps running in production, hopefully producing value, and it needs to be maintained.
As it happens, not all of its behaviour is covered by automated tests - it’s legacy code. And most engineers will spend most of their careers working on such code (that includes code they wrote themselves six or twelve months earlier). I spent a fair share of my short software career doing so already.
Feathers put together a series of useful techniques to tame the beast - documenting existing behaviour using tests in order to make it possible to evolve the system itself to satisfy new requirements.
Extremely useful as a reference when working on gnarly legacy beasts.
- xUnit Test Patterns: Refactoring Test Code by Gerard Meszaros
As you approach a new project armed with the two books above, you will try to stick to a disciplined testing approach.
I sure did when given the chance to start a greenfield service.
After a while, our test coverage started to decrease: new code was less thoroughly tested than the code we wrote at the very beginning of the project. Did we do it on purpose?
No - if you asked, the whole team would have probably re-stated their faith in the importance of testing. Nonetheless, it was happening.
The truth was that our tests had started to slow us a down - it was getting cumbersome to write and maintain them as the codebase evolved. As a result, we were writing less and less tests, without acknowledging it.
If we kept at it without changing direction, we would have probably joined the faction of those who see tests as a hindrance more than an asset. Instead, I found this book and a significant refactor of our test suite brought us back to our previous development speed without compromising on our testing practices.
The book is a bit dated, but it’s a useful reference for a bunch of important techniques to keep the development tax of your comprehensive test suite under control. It was indeed instrumental for ours.
I don’t suggest to read it cover to cover - it’s quite repetitive and way too long.
- The Soul of A New Machine by Tracy Kidder
A novel - what is it doing here?
Well, it takes quite the effort to digest the material I linked so far. Why bother? What is it that makes it worthwhile to go through all these hurdles? (Tech money aside, perfectly legit motivation)
The Soul of A New Machine resonates.
With the part of me that loved reading about Wiles’ proof of the Fermat’s Last Theorem.
With that part of me that is fascinated by people losing themselves in the quest to solve problems that are bigger than them, almost all-consuming.
On that note, I can’t avoid recommending Bryan Cantrill’s review of the The Soul of A New Machine with almost the same fervor of my recommendation for the book itself.
Software development lifecycle
- Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation by Jez Humble and David Farley
A deep-dive into the world of CD, Continuous Delivery.
The book is 10 years old, but it has withstood the test of time: technologies might have changed, but the principles and the challenges highlighted here are still relevant when designing (and automating) the release pipelines of contemporary systems.
- Accelerate: The Science of Lean Software and Devops by Nicole Fosgren, Jez Humble and Gene Kim
Why should you go through all the trouble of implementing what the previous book details?
Accelerate doesn’t necessarily introduce a set of revolutionary metholodogies in software delivery, but it provides solid datapoints and robust research proving that some of those methodologies (Lean, DevOps, etc.) have indeed a measurable impact on the business performance of an organisation.
The four key metrics are extremely useful to measure the health of an engineering team.
The yearly State of DevOps report complements Accelerate and provides updates on the state of the industry.
There is more to software than code.
Code is often the easy bit - people are the tough nut to crack.
Core skills and leadership are often neglected when describing the minimal toolset needed by a software engineer to be effective.
While competency is key, it’s being capable to work with others that makes it or breaks it.
The jury is out on the existence of 10x engineers, but I am sure of the existence of 10x (and 0.1x!) teams.
It goes beyond the individuals - it’s a mix of practices, processes, vision, values.
You can freestyle it as a team of 5 or 6, but it will soon spiral out of control when the organisation grows.
These three books are the one I found the most interesting among the many I touched in the “management” section - they are principled, clear-written and insightful. They deserve a spot in an engineering curriculum as much as the fundamentals of testing and domain design.
Turn The Ship Around!, in particular, is a written account of the wonders of decentralised decision-making and high mutual-trust in an environment used to a strict Command/Control management-style (the US Navy!).
Empowering every single individual to channel their best version of themselves should be the goal of every (engineering) organisation.