The Pragmatic Programmer — Your Journey to Mastery (20th Anniversary Edition)
Authors: David Thomas & Andrew Hunt
Edition: 20th Anniversary (2nd Edition, 2019)
Topics: 53 | Tips: 100 | Pages: 497
Book in One Paragraph
A pragmatic programmer is defined by attitude — taking ownership of their work, thinking deliberately, and applying universal principles (not fashionable tools) to produce software that is correct, maintainable, and flexible. The book covers 53 topics across individual philosophy, design principles, basic tools, code practices, concurrency, project management, and ethics, unified by a single root idea: write code that is easy to change.
Structure Overview
| Chapter | Topics | Core Theme |
|---|---|---|
| 1: A Pragmatic Philosophy | 1–7 | Ownership, attitude, knowledge investment, communication |
| 2: A Pragmatic Approach | 8–15 | ETC, DRY, orthogonality, reversibility, tracer bullets, prototypes, domain languages, estimation |
| 3: The Basic Tools | 16–22 | Plain text, shell, editor fluency, VCS, debugging, text manipulation, daybooks |
| 4: Pragmatic Paranoia | 23–27 | DBC, crash early, assertions, resource balancing, small steps |
| 5: Bend, or Break | 28–32 | Decoupling, event strategies, transformations, inheritance tax, configuration |
| 6: Concurrency | 33–36 | Temporal coupling, shared state, actor model, blackboards |
| 7: While You Are Coding | 37–44 | Lizard brain, coincidence, Big-O, refactoring, testing, property tests, security, naming |
| 8: Before the Project | 45–48 | Requirements, impossible puzzles, working together, agility |
| 9: Pragmatic Projects | 49–53 | Teams, methodology, starter kit, delighting users, pride |
| 10: Postface | — | Ethical responsibility |
The 100 Tips (Quick Reference)
| # | Tip |
|---|---|
| 1 | Care About Your Craft |
| 2 | Think! About Your Work |
| 3 | You Have Agency |
| 4 | Provide Options, Don’t Make Lame Excuses |
| 5 | Don’t Live with Broken Windows |
| 6 | Be a Catalyst for Change |
| 7 | Remember the Big Picture |
| 8 | Make Quality a Requirements Issue |
| 9 | Invest Regularly in Your Knowledge Portfolio |
| 10 | Critically Analyze What You Read and Hear |
| 11 | English is Just Another Programming Language |
| 12 | It’s Both What You Say and the Way You Say It |
| 13 | Build Documentation In, Don’t Bolt It On |
| 14 | Good Design Is Easier to Change Than Bad Design |
| 15 | DRY — Don’t Repeat Yourself |
| 16 | Make It Easy to Reuse |
| 17 | Eliminate Effects Between Unrelated Things |
| 18 | There Are No Final Decisions |
| 19 | Forgo Following Fads |
| 20 | Use Tracer Bullets to Find the Target |
| 21 | Prototype to Learn |
| 22 | Program Close to the Problem Domain |
| 23 | Estimate to Avoid Surprises |
| 24 | Iterate the Schedule with the Code |
| 25 | Keep Knowledge in Plain Text |
| 26 | Use the Power of Command Shells |
| 27 | Achieve Editor Fluency |
| 28 | Always Use Version Control |
| 29 | Fix the Problem, Not the Blame |
| 30 | Don’t Panic |
| 31 | Failing Test Before Fixing Code |
| 32 | Read the Damn Error Message |
| 33 | ”select” Isn’t Broken |
| 34 | Don’t Assume It — Prove It |
| 35 | Learn a Text Manipulation Language |
| 36 | You Can’t Write Perfect Software |
| 37 | Design with Contracts |
| 38 | Crash Early |
| 39 | Use Assertions to Prevent the Impossible |
| 40 | Finish What You Start |
| 41 | Act Locally |
| 42 | Take Small Steps — Always |
| 43 | Avoid Fortune-Telling |
| 44 | Decoupled Code Is Easier to Change |
| 45 | Tell, Don’t Ask |
| 46 | Don’t Chain Method Calls |
| 47 | Avoid Global Data |
| 48 | If It’s Important Enough to Be Global, Wrap It in an API |
| 49 | Programming Is About Code, But Programs Are About Data |
| 50 | Don’t Hoard State; Pass It Around |
| 51 | Don’t Pay Inheritance Tax |
| 52 | Prefer Interfaces to Express Polymorphism |
| 53 | Delegate to Services: Has-A Trumps Is-A |
| 54 | Use Mixins to Share Functionality |
| 55 | Parameterize Your App Using External Configuration |
| 56 | Analyze Workflow to Improve Concurrency |
| 57 | Shared State Is Incorrect State |
| 58 | Random Failures Are Often Concurrency Issues |
| 59 | Use Actors For Concurrency Without Shared State |
| 60 | Use Blackboards to Coordinate Workflow |
| 61 | Listen to Your Inner Lizard |
| 62 | Don’t Program by Coincidence |
| 63 | Estimate the Order of Your Algorithms |
| 64 | Test Your Estimates |
| 65 | Refactor Early, Refactor Often |
| 66 | Testing Is Not About Finding Bugs |
| 67 | A Test Is the First User of Your Code |
| 68 | Build End-to-End, Not Top-Down or Bottom Up |
| 69 | Design to Test |
| 70 | Test Your Software, or Your Users Will |
| 71 | Use Property-Based Tests to Validate Your Assumptions |
| 72 | Keep It Simple and Minimize Attack Surfaces |
| 73 | Apply Security Patches Quickly |
| 74 | Name Well; Rename When Needed |
| 75 | No One Knows Exactly What They Want |
| 76 | Programmers Help People Understand What They Want |
| 77 | Requirements Are Learned in a Feedback Loop |
| 78 | Work with a User to Think Like a User |
| 79 | Policy Is Metadata |
| 80 | Use a Project Glossary |
| 81 | Don’t Think Outside the Box — Find the Box |
| 82 | Don’t Go into the Code Alone |
| 83 | Agile Is Not a Noun; Agile Is How You Do Things |
| 84 | Maintain Small, Stable Teams |
| 85 | Schedule It to Make It Happen |
| 86 | Organize Fully Functional Teams |
| 87 | Do What Works, Not What’s Fashionable |
| 88 | Deliver When Users Need It |
| 89 | Use Version Control to Drive Builds, Tests, and Releases |
| 90 | Test Early, Test Often, Test Automatically |
| 91 | Coding Ain’t Done ‘Til All the Tests Run |
| 92 | Use Saboteurs to Test Your Testing |
| 93 | Test State Coverage, Not Code Coverage |
| 94 | Find Bugs Once |
| 95 | Don’t Use Manual Procedures |
| 96 | Delight Users, Don’t Just Deliver Code |
| 97 | Sign Your Work |
| 98 | First, Do No Harm |
| 99 | Don’t Enable Scumbags |
| 100 | It’s Your Life. Share it. Celebrate it. Build it. AND HAVE FUN! |
The Unifying Idea
Everything in the book flows from ETC — Easier to Change:
- DRY → one representation = one place to change
- Orthogonality → independent components = local changes
- Decoupling → loose coupling = isolated changes
- Reversibility → no final decisions = freedom to change
- Refactoring → gardening, not construction = continuous change
- Agility → feedback loop = capability to change
- Good naming → clarity = easier to understand before changing
- Testing → safety net = confidence to change