The next book is one that's been lying on my desk a while now. Almost 2 years actually. It's the anniversary edition of The Pragmatic Programmer, yet another "must read".
This updated classic goes through a lot of material in its roughly 300 pages. It discusses "softer" topics such as craftsmanship and agency, taking pride in, and responsibility for, your own work. It also discusses "not-so-soft" topics such as Concurrency and the Actor pattern. The more technical chapters are, understandably, not very in-depth, as there are standalone books on these already. For a junior developer to use this book as an introduction to the field is very helpful, and possibly a little daunting. But it is a complicated field, and it's constantly being made more complicated by the steady stream of humans involving themselves with software development. Software runs the world, and it's seeping into every nook and cranny of every business on the planet. This makes taking a stand for quality more important, and more difficult than ever before.
I'd be doing the book a disservice if I tried to summarize it, so I think I'll have to make do with listing my favorite tips and my own description of why I like them.
Tip 5: Don't live with broken windows
The Broken Windows Theory is well known. A single less-than-ideal piece of code, a single manual procedure or a single flaky test can cause everything to fall apart. If there is a single broken window left alone for too long, soon another will be broken. And then another. I've seen this happen, and back then I began saying; "optimize for copy-paste".
Tip 22: Program close to the problem domain
Just as you want to program in a higher level language rather than assembly, you want to program close to your domain, rather than in terms in SQL statements and socket connections. Compare a Bézier curve to a list of coordinates. Dijkstra's quote is quite fitting: "The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise."
Tip 59: Use Actors for concurrency without shared state
Actors are amazing, I love them and everyone should use them all the time.
Tip 68: Build End-to-End, Not Top-Down or Bottom-Up
This relates a lot to tip 20, about tracer bullets. This is the MVP-way of software development. Involve every piece, just to see that it actually works. Develop your design-level abstractions as you go along. Refactor, rename and improve continuously, but start with a threading the needle with a thin red thread that goes through the entire system. So you don't find out later that you can't actually connect to the database.
Tip 75: No-one knowns exactly what they want
Software developers are problem solvers. We think about edge cases and bridge the gap between natural language and computerized instructions. It's in this gap that crazy things happens, and we need to look for feedback at every step, and from multiple different angles to make sure that what we're doing is the right thing. We should not blindly implement whatever requirement or user story that's put in front of us. We cannot know everything every time. This is also why we should always strive to understand the bigger picture and story behind what's been written down, or retold to us.
Tip 86: Organize fully functional teams
My ideal team consists of a group of people where everyone can do everything. As in, front end, backend, database, troubleshooting, document, test. Of course you can have specialties, and favorite areas - but if push comes to shove, can just about anyone pick up that urgent bug request? Or do we need to wait until Brent comes back from vacation? A team should consist of everyone who is needed, from idea to evaluation, not just monkeys waiting for bananas, then throwing peels over the wall.