An Ordered and Curated Reading List for Software Craftsmanship Growth
- Must I read the books in order?
This list is the order I wished I had read these books when I started reading programming books.
- It’s a lot of books on the list.
There are many great programming books to read. I have tried to maximize learning per page in this list. It will take years to read them all, so don’t stress it and take your time. Remember, It’s not a competition.
- I’m a beginner, will this be suitable for me?
Before starting this list, I recommend that you have endured a codebase for more than one year and are proficient in one programming language.
It’s a programming book about how to excel as a software craftsman. You’ll learn indispensable advice that I wished I knew when I started. We all struggle with the same problems in our journey to mastery, especially early in our careers when we are apprentices.
- How is a programming book about the brain helpful?
You will always need to learn new things that will never stop if you want to stay relevant.
This book will help you understand yourself and your peers. Getting familiar with learning technics early in your journey will give you a huge opportunity to grow fast.
- I know both object-oriented and functional programming. can I skip this section?
There is a difference between writing code in a programming language and understanding a language’s paradigm. For example, the languages you write code in seldom dictate the type of code you can write.
Once you understand a paradigm, it can influence all your code, even in languages in other paradigms.
- Isn’t Object-Oriented Design about applying inheritance to reuse code?
Often, people think they have mastered OOP (Object-Oriented Programming) because they use inheritance to remove duplication. Object-Oriented programming is not about inheritance. Instead, it’s about the messages between objects.
Designing an OOP system is not easy. This programming book teaches you to design classes with a single responsibility and compose them with well-defined interfaces.
Harness the Combinatoric Power of Command-Line Tools and Utilities
Brian P. Hogan
- Why is the command-line so important?
Being comfortable with the command-line interface is the most cross-platform skill you can learn. It will most likely always be helpful and outlive most languages and environments.
Working with files, text, and networks is common for a developer. The command line can likely automate most of the tediousness of these tasks pretty quickly.
- I work as a programmer already, why is this useful?
These programming books will give a fundamental understanding of software craftsmanship. Being a programmer is more than just writing code. Therefore, you should also strive to do it well (which I assume you are because you are reading this).
There are bad and good coding habits. This programming book documents many and gives them context. Understanding what makes code difficult to read and change will help keep the codebase maintainable.
- I heard this programming book is promoting bad ideas.
Everyone won’t always agree with everything a programming book states, which is fine. But be careful to jump to conclusions without some reflections. You can read more about that in my article When programming books are wrong.
TDD (Test-Driven Development) is the idea of writing test code before production code and letting that drive your design. TDD is one of the most rewarding technics one can learn. Learning TDD is tough and will take time.
- I heard TDD is dead.
David Heinemeier Hansson wrote a blog post claiming that TDD can harm the quality of the production code, listen to the hangout discussion with Martin Fowler and Kent Beck, and read Uncle Bobs thoughts to find out if he was right.
This programming book will define and give you the recipe to be a pragmatic programmer. So don’t expect to be one just because you read it once. Instead, you need to follow their advice and take it to heart without
I’m sure your definition of a pragmatic programmer will change after you have read this programming book, and it will likely change again after reading it another time a few years down the road.
5. Computer science
- I have a computer science degree. Can I skip this section?
These are great programming books, but they might be rudimentary for someone with a master’s or doctorate in computer science.
- I was joking. I don’t have a computer science degree.
Having a computer science degree from a university is not required to be a master craftsman. Having an understanding of computer science is.
I’m not distilling the branch of computer science to a few programming books; doing so would be absurd and unjust.
The Hidden Language of Computer Hardware and Software
- I know what code is.
Writing code and understanding a computer are two different things. Knowing how a computer works can help you understand what to expect from a computer.
- I’m not an embedded developer, so it doesn’t apply to me.
The computer is what you are using to produce and run your program. Having a firm understanding of how it works will give you a better chance of predicting its behavior no matter what tech stack you are using.
An Illustrated Guide for Programmers and Other Curious People
- I have already memorized how to sort an inverted binary tree on a whiteboard.
Algorithms are repeatable steps where each step brings us closer to a solution. Being good at algorithms isn’t about remembering how to sort lists. Instead, it’s about understanding how to decompose problems and using the right tools for the job.
A Pragmatic Guide to Learning Programming Languages
Bruce A. Tate
- These programming languages seem old and irrelevant for the modern age of software development.
This programming book introduces seven paradigms through seven programming languages. The ideas and concepts from these languages have influenced many modern languages today. Without Haskell there would surely be no Swift, Kotlin, or Elm.
Exposing oneself to new ideas and concepts is helpful for perspective and problem-solving. For example, Prolog and Erlang might seem like strange programming languages with little application, but understanding them might be more beneficial than you first might think.
Don’t let the cover or the Socratic writing style throw you off into thinking this is a simple book. It’s a programming book about recursion and computation. The book is not long or complicated, but it can be mind-bending.
- Aren’t we programmers, not designers.
Code needs to be designed for testability, readability, extensibility, and reuse. It’s hard to achieve, and it will take you many iterations of refactoring to get there.
- I’m a doer, not a thinker. Can’t I focus on writing code and let someone else deal with the design of the system?
Writing code is all about design, and these programming books will give you a toolbox to create APIs that are both easy to test, understand, and use.
Building Extensible and Maintainable Object-Oriented Software
Eric Freeman & Elisabeth Robson
- What are design patterns?
Design patterns describe a problem and a general solution that can be applied in many variations depending on your specific context.
- Why recommend this book over the classic book Design Patterns by GoF (Gang of Four)
This programming book gives a thorough but gentle introduction to design patterns and goes through the most commonly used ones from the programming book Design Patterns. I strongly recommend that you also Design Patterns at some point but be prepared that it can be a challenging but rewarding read.
Test code is essential for a healthy software project. If you have no tests, you can’t refactor your code safely or avoid regression effortlessly.
Poorly written tests can become a burden instead of an advantage if one is not careful. Writing good tests is a skill like any other, and this is a great resource to learn how to improve your test writing skills.
This book defines legacy code as code without unit tests and describes technics (with examples) on how to put tests around the code.
- I do TDD, so why do I need this?
Legacy code is in all projects if large enough, and there are many good reasons for it.
Working with legacy code is tiring and makes long lead times for new features. It can also be a breeding ground for regression.
- I see all examples are in OOP languages. I use functional programming.
Code examples are in Java, C++, C, and C#, but the concepts are applicable in functional programing as well.
- What makes you a master software craftsman?
Programming is a vital part of being a master software craftsman, but an equally important skill is communication with people. If communication breaks, it will make everything harder than it has to be.
Never forget that projects and companies are just people. People who are trying to deliver value to users.
- Am I done now after reading the programming books in this section?
The road to mastery is never over. Like the black belt in martial arts, this is the beginning of something, not the end. So continue reading something from the extra page. You are only at the beginning of your journey.
Software is hard to build. The problems we face today in software projects are as old as software engineering. This book makes that abundantly clear. Written in 1975 about a software project at IBM in the 60s, this book feels as relevant today as it probably was back then.
- If nothing changes, aren’t we doomed to fail?
Knowing and understanding common software project problems helps us mitigate them or at least know what to expect.
“Adding manpower to a late software project makes it later” - Brooks’s law.
As the original design pattern book, it defines a vocabulary for problems and solutions. Knowing a lot of them gives you the flexibility to explore and talk about solutions at a higher level of abstraction.
- Okay, but I’m not sure I’m developing an enterprise application.
If you are getting paid to write software, you are probably working on an enterprise application. It’s tricky to get all the parts right, like database, network, and user interface code. This book will help you make the right trade-offs for the right reasons.
Design patterns solve problems, so they should not be applied if there is none. Therefore design patterns should be a product of refactorings. Never start with a design pattern but rather refactor towards or to them, and sometimes even away from them.