When I first started programming seriously, I had no reference or guide for learning the soft and hard skills of software engineering. I didn’t have a computer science degree (and I didn’t plan on going back to college), so I felt like I missed a certain aspect of this education. I went looking all over the internet and there were quite a few book recommendations, but one that was almost always atop every list was The Pragmatic Programmer.

The book is structured as a collection of tips, with each tip being expanded upon with explanations, war stories, and analogies. At the end of each chapter, there were exercises which tested critical thinking and/or code practices. I found I really liked this format as it kept me constantly engaged. With that said, I will structure my notes based on the tips that resonated with me the most (prefaced with ◆). You can find all the tips listed here.

◆ Care About Your Craft

The most important tip for me, and likely the authors’ as its the first tip we encounter. To quote,

“We feel that there is no point in developing software unless you care about doing it well.”

In my opinion, this holds true for most things in life as well. If we care, all our intentions become clear, all our actions deliberate. When I sit down to write code, I do my best to engage myself fully in what I’m doing – minimizing all distractions. I find this helps greatly, and I often find myself finding elegant, clean solutions to problems.

◆ Provide Options, Don’t Make Lame Excuses

Whenever I have an urge to make an excuse, it usually means I didn’t want to take responsibility for my actions. This shows a lack of respect both for myself and for the other party. However, providing options means that I have done due diligence with regards to what I would have otherwise given an excuse for – be it a deadline, a responsibility, or otherwise.

◆ Remember the Big Picture

I’m a “big picture” learner. I find I need to see how things interact on a large scale before diving into the details. But oftentimes I find myself diving into the details anyway, focusing too tightly, and over-engineering. The authors use the analogy of the boiling frog: supposedly, if you take a frog and drop it in boiling water, it will immediately jump out. But, if you place the frog in cold water and gradually increase the temperature, it will eventually cook itself. We just don’t notice the insidious change. A reminder to look at the forest instead of the trees.

◆ Invest Regularly in Your Knowledge Portfolio

Always be learning. The authors list out some steps on how best to go about doing that: a new language every year, a technical book each quarter, classes, and staying current. This might have been more difficult when the book was first published (1999), but we are lucky to live in a time where blog posts, Hacker News, MOOCs, and e-books are just a few clicks away. We have no excuse – so many resources are at our fingertips, it’s easy to find something we might enjoy and go learn as much about it as possible.

◆ DRY – Don’t Repeat Yourself

We see this tip parrotted everywhere now, it’s become one of the most mainstream ideas of the book and for good reason. Having a single source of truth pays dividends in time and structure. There is a great interview with the authors that expand on the topic and how it’s been misunderstood to mean no code duplication.

◆ Eliminate Effects Between Unrelated Things

Here the authors introduce the topic of orthogonality. The concept meaning that if two or more things are orthogonal to each other, changes in one will not affect any of the others. I believe this also incorporates modular systems. The two major benefits of orthogonal systems being increased productivity and reduced risk. When changes are localized to a particular component, one does not have to scour the entire codebase for other places where changes might be needed. Reduced risk entails not having to worry about breaking other parts of the software when making pinpoint changes. Code is isolated to its component.

◆ Separate Views from Models

A model handles all the logic, a view handles only displaying the information, and the controller is the interface between the two. I first learned about this in the context of Rails and then eventually React. However, this appeared way before web applications and applies to all systems that require user interfaces. By building our applications with Model-View-Controller in mind, we gain flexibility, and it forces us to build modular, orthogonal systems where the model is our single source of truth.

◆ Configure, Don’t Integrate

Make our systems highly configurable. Use metadata to describe configuration options. In my limited understanding, this can be as simple as environment variables or JSON. I see this often nowadays but it really didn’t click with me until I read this specific tip. The authors go on to specify to “program for the general case, and put specifics somewhere else”. I know I have a tendency to integrate for all cases in my code, but this tip has started making me re-think my design.

◆ Put Abstractions in Code, Details in Metadata

Harking to the previous tip, the idea behind this tip is that we want to defer implementation of the details until the very last step. This allows decoupling of our design from the specifics. By implementing in such a way, we give ourselves room to adapt to changes swiftly.

◆ Sign Your Work

Finally, we should be proud of the work we do. Taking ownership means we accept responsibility for our work, and we put in all our effort into it.


The book contains a lot of valuable tips, and the examples and advice the authors give are timeless. I really enjoyed this book and I can see why it sits at the top of everyone’s recommendation lists. If you’re looking for a book to start reading, I highly recommend it.