I often get asked for recommendations. Here is a list of books and resources I vouch for because I’ve found them invaluable in my journey as a software engineer or have seen them greatly help others.
If you’ve never coded before, then my main recommendation is:
Learn Code The Hard Way course by Zed Shaw is one of those great starting places when you have never seen code before. It has plenty of good tips, tricks and exercises to get you started.
A few recommendations specifically for Go:
Go Training resources by Bill Kennedy is a nice introduction to programming in general and what is a good mental model for programming in Go. He covers a variety of topics and it is all free.
Web Development With Go course by Jon Calhoun is a comprehensive guide into writing a production ready web application.
The Go Programming Language book by Alan Donovan and Brian Kernighan.
After you have written your first if statements, loops and can manage a 1000 line program.
A Philosophy of Software Design by John Ousterhout is one of those books that helps you get started in moving the right direction for software development mastery. He guides you to find balance in the things you do using clear examples. His list of warning signs helps you notice when things have gone wrong.
The Practice of Programming by Brian Kernighan and Rob Pike is an elegant book which covers a variety of topics from comments to testing and performance.
The Pragmatic Programmer by Andrew Hunt and David Thomas is a step towards looking at the bigger picture of software craftsmanship, not just focusing on the coding.
Once you grasp basics you should continue learning by writing a bigger project – a few packages and around 10,000 lines of code. Otherwise, the following reading might be hard to relate to.
On the Criteria To Be Used in Decomposing Systems into Modules by David Parnas is a classic that will probably never age. It discusses main concerns when making software modular. It is a great introduction into software architecture.
Physics of Software by Carlo Pescio is a hidden gem that hones your intuition on how software evolves and how different pieces interact. Although these concepts may seem very abstract, I use them frequently.
Lean Architecture: for Agile Software Development by James Coplien and Gertrud Bjørnvig clearly reminds us to not start from technology, but rather from focusing on creating value and on people. In the long run it leads to software that adds more value and expresses ideas clearer.
Domain Driven Design by Eric Evans was interesting to me mainly with regards to how to design and figure out the domain part of the software and communicate it clearly.
Working Effectively with Legacy Code by Michael Feathers has sound advice on how to maintain software. I’ve learned so much from refactoring and making things clearer. Maybe even more than from writing things from scratch. Some day, all successful codebases become legacy, so learning how to manage them is essential.
Design Thinking by Dave West and Rebecca Rikner goes into fundamental perspectives, principles, concepts and practices that make design better and more insightful.
An Introduction to General Systems Thinking by Gerald Weinberg is an introduction on how to think about complex and chaotic problems where it is impossible to isolate the parts.
For performance and algorithms my favourites are:
The Algorithm Design Manual by Steven Skiena is my favorite algorithmics book. I especially recommend reading the War Stories where it makes clearer how people invent algorithms. It’s not a spark of insight, but rather a gradual improvement over days, months and years.
Latency Numbers Every Programmer Should Know is one of those tables that you should have roughly memorized for back-of-the-envelope calculations. In general, the skill of estimating is very useful in making smart decisions about performance.
Data Oriented Design by Richard Fabian offers a deep dive into using your computer clock cycles efficiently.
Algorithm Engineering goes in depth in all the different parts of designing algorithms (e.g. how to design, derive and test them properly).
As programmers we should read code more than we write it. Otherwise it’s easy to end up in our own bubble.
The Architecture of Open Source Application contains many different case-studies and interesting practical issues that people needed to solve.
Game Programming Gems series contains many very specific and interesting articles on different problems. It’s a great resource for building up your vocabulary about problems.
While programming you eventually end up working with other people for one reason or another.
ScrumPLOP is like a chest of treasures where each pattern is thoroughly thought out and analyses different problems a software team might have. Every pattern has years of experience to back it up. I would recommend to skip the Scrum Guide and go straight to the patterns.
Five Dysfunctions of a Team goes over major things that can go wrong in a team so you can detect it early and counteract.
re:Work by Google shares research insights into how to make work environment and communication better.
Even as a programmer you should have a good grasp on how to design usable things and what a human brain is capable of.
The Humane Interface by Jef Raskin is the introductory book on usability and cognetics. I gained a lot of insight into how to measure and understand usability.
The Design of Everyday Things by Don Norman explains human psychology and makes it clear that human interaction is to be expected and failing to take it into account is an error on the designer side.
Nielsen/Norman Group if you want to stay up to date with the latest news on usability research or you have a very specific topic that interests you. When I have a usability question then that’s the first place I search.
The Best Interface is No Interface reminds that the best solution often is not an app or an interaction, but rather the lack of it.
As programmers we spend most of our time building and maintaining solutions, however reflecting on why and what we are building is just as important.
Zen and the Art of Motorcycle Maintenance by Robert Pirsig is an exploration of what is “quality” and what matters in life.
The Nature of Order by Christopher Alexander is a formulation of principles that create good environments and life in the world. It’s a description on how to make life better using design.
Patterns of Software by Richard Gabriel contains many insightful essays on the nature of building software.
Somewhat more specialist subject is networking, but nevertheless, you will end up using networks one way or another:
Falsehoods programmers believe about networks and Fallacies of distributed computing are very short articles, but will make it clear why networking code is difficult, and therefore make you approach the field with greater reverence.
Network Programming with Go by Jan Newmarch goes over multiple layers of network programming with really nice explanations.
Why Do Computers Stop and What Can Be Done About It? by Jim Gray is a classic and a great introduction to dealing with the inevitable failure of systems.
Making reliable distributed systems in the presence of software errors by Joe Armstrong talks about building reliable systems that can survive in the harshest of conditions.
And now the miscellaneous:
Structure and Interpretation of Computer Programs by Gerald J. Sussman and Hal Abelson is a classic that teaches how to bend programming to your own needs.
NAND2Tetris course is an introduction to building a virtual computer from the basic elements (almost). It covers machine language, computer architecture, assemblers, high-level languages etc. All in a course form. For an addendum you can watch Ben Eater’s Building an 8-bit breadboard computer.
Awesome Falsehoods contains a series of articles by different authors exploring various topics in depth, usually things that people get wrong. Just learning about names is enough to take precautions in every other concern.