Pragmatic Programmer Tips
pragprog.com/tips
Buy →
For twenty years, the lessons from The Pragmatic Programmer
have helped a generation of programmers examine the very
essence of software development, independent of any particular
language, framework, or methodology. This classic title is
regularly featured on “Top Ten” lists, and many corporations
issue it to their new hires.
Andy and Dave wrote this influential, classic book to help their
clients create better software and rediscover the joy of coding.
Almost twenty years later, its advice is still spot on, and the Pragmatic philosophy has
spawned hundreds of books, screencasts, and audio books, as well as thousands of careers
and success stories.
We’ve posted the 100 tips from the book here for your reference and enjoyment. Tweet
and share your favorites!
Tip #1, pg. xxi:
Care About Your Craft
Why spend your life developing software unless you care about doing it well?
Tweet this
Tip #2, pg. xxi:
Think! About Your Work
Turn off the autopilot and take control. Constantly critique and appraise your work.
Tweet this
Tip #3, pg. 2:
You Have Agency
It’s your life. Grab hold of it and make it what you want.
Tweet this
Tip #4, pg. 4:
1/17
Provide Options, Don’t Make Lame Excuses
Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done.
Tweet this
Tip #5, pg. 7:
Don’t Live with Broken Windows
Fix bad designs, wrong decisions, and poor code when you see them.
Tweet this
Tip #6, pg. 9:
Be a Catalyst for Change
You can’t force change on people. Instead, show them how the future might be and help
them participate in creating it.
Tweet this
Tip #7, pg. 10:
Remember the Big Picture
Don’t get so engrossed in the details that you forget to check what’s happening around
you.
Tweet this
Tip #8, pg. 12:
Make Quality a Requirements Issue
Involve your users in determining the project’s real quality requirements.
Tweet this
Tip #9, pg. 15:
Invest Regularly in Your Knowledge Portfolio
Make learning a habit.
Tweet this
Tip #10, pg. 17:
Critically Analyze What You Read and Hear
2/17
Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you
and your project.
Tweet this
Tip #11, pg. 20:
English is Just Another Programming Language
Treat English as Just Another Programming Language. Write documents as you would
write code: honor the DRY principle, ETC, automation, and so on.
Tweet this
Tip #12, pg. 22:
It’s Both What You Say and the Way You Say It
There’s no point in having great ideas if you don’t communicate them effectively.
Tweet this
Tip #13, pg. 23:
Build Documentation In, Don’t Bolt It On
Documentation created separately from code is less likely to be correct and up to date.
Tweet this
Tip #14, pg. 28:
Good Design Is Easier to Change Than Bad Design
A thing is well designed if it adapts to the people who use it. For code, that means it must
adapt by changing.
Tweet this
Tip #15, pg. 31:
DRY—Don't Repeat Yourself
Every piece of knowledge must have a single, unambiguous, authoritative representation
within a system.
Tweet this
Tip #16, pg. 38:
Make It Easy to Reuse
3/17
If it’s easy to reuse, people will. Create an environment that supports reuse.
Tweet this
Tip #17, pg. 40:
Eliminate Effects Between Unrelated Things
Design components that are self-contained, independent, and have a single, well-defined
purpose.
Tweet this
Tip #18, pg. 48:
There Are No Final Decisions
No decision is cast in stone. Instead, consider each as being written in the sand at the
beach, and plan for change.
Tweet this
Tip #19, pg. 49:
Forgo Following Fads
Neal Ford says, “Yesterday’s Best Practice Becomes Tomorrow’s Antipattern.” Choose
architectures based on fundamentals, not fashion.
Tweet this
Tip #20, pg. 51:
Use Tracer Bullets to Find the Target
Tracer bullets let you home in on your target by trying things and seeing how close they
land.
Tweet this
Tip #21, pg. 57:
Prototype to Learn
Prototyping is a learning experience. Its value lies not in the code you produce, but in the
lessons you learn.
Tweet this
Tip #22, pg. 60:
Program Close to the Problem Domain
4/17
Design and code in the language of the problem domain.
Tweet this
Tip #23, pg. 66:
Estimate to Avoid Surprises
Estimate before you start. You’ll spot potential problems up front.
Tweet this
Tip #24, pg. 70:
Iterate the Schedule with the Code
Use experience you gain as you implement to refine the project time scales.
Tweet this
Tip #25, pg. 75:
Keep Knowledge in Plain Text
Plain text won’t become obsolete. It helps leverage your work and simplifies debugging
and testing.
Tweet this
Tip #26, pg. 79:
Use the Power of Command Shells
Use the shell when graphical user interfaces don’t cut it.
Tweet this
Tip #27, pg. 81:
Achieve Editor Fluency
An editor is your most important tool. Know how to make it do what you need, quickly
and accurately.
Tweet this
Tip #28, pg. 85:
Always Use Version Control
Version control is a time machine for your work; you can go back.
5/17
Tweet this
Tip #29, pg. 89:
Fix the Problem, Not the Blame
It doesn’t really matter whether the bug is your fault or someone else’s—it is still your
problem, and it still needs to be fixed.
Tweet this
Tip #30, pg. 89:
Don’t Panic
This is true for galactic hitchhikers and for developers.
Tweet this
Tip #31, pg. 91:
Failing Test Before Fixing Code
Create a focussed test that reveals the bug before you try fixing it.
Tweet this
Tip #32, pg. 92:
Read the Damn Error Message
Most exceptions tell both what failed and where it failed. If you’re lucky you might even
get parameter values.
Tweet this
Tip #33, pg. 95:
“select” Isn't Broken
It is rare to find a bug in the OS or the compiler, or even a third-party product or library.
The bug is most likely in the application.
Tweet this
Tip #34, pg. 96:
Don’t Assume It—Prove It
Prove your assumptions in the actual environment—with real data and boundary
conditions.
6/17
Tweet this
Tip #35, pg. 98:
Learn a Text Manipulation Language
You spend a large part of each day working with text. Why not have the computer do some
of it for you?
Tweet this
Tip #36, pg. 102:
You Can’t Write Perfect Software
Software can’t be perfect. Protect your code and users from the inevitable errors.
Tweet this
Tip #37, pg. 107:
Design with Contracts
Use contracts to document and verify that code does no more and no less than it claims to
do.
Tweet this
Tip #38, pg. 113:
Crash Early
A dead program normally does a lot less damage than a crippled one.
Tweet this
Tip #39, pg. 115:
Use Assertions to Prevent the Impossible
If it can’t happen, use assertions to ensure that it won’t. Assertions validate your
assumptions. Use them to protect your code from an uncertain world.
Tweet this
Tip #40, pg. 118:
Finish What You Start
Where possible, the function or object that allocates a resource should be responsible for
deallocating it.
7/17
Tweet this
Tip #41, pg. 121:
Act Locally
Keep the scope of mutable variables and open resources short and easily visible.
Tweet this
Tip #42, pg. 126:
Take Small Steps—Always
Small steps always; check the feedback; and adjust before proceeding.
Tweet this
Tip #43, pg. 127:
Avoid Fortune-Telling
Only look ahead as far as you can see.
Tweet this
Tip #44, pg. 131:
Decoupled Code Is Easier to Change
Coupling ties things together, so that it’s harder to change just one thing.
Tweet this
Tip #45, pg. 132:
Tell, Don’t Ask
Don’t get values from an object, transform them, and then stick them back. Make the
object do the work.
Tweet this
Tip #46, pg. 134:
Don’t Chain Method Calls
Try not to have more than one dot when you access something.
Tweet this
Tip #47, pg. 136:
8/17
Avoid Global Data
It’s like adding an extra parameter to every method.
Tweet this
Tip #48, pg. 136:
If It’s Important Enough To Be Global, Wrap It in an API
…but only if you really, really want it to be global.
Tweet this
Tip #49, pg. 149:
Programming Is About Code, But Programs Are About Data
All programs transform data, converting an input into an output. Start designing using
transformations.
Tweet this
Tip #50, pg. 153:
Don’t Hoard State; Pass It Around
Don’t hang on to data within a function or module. Take one down and pass it around.
Tweet this
Tip #51, pg. 161:
Don't Pay Inheritance Tax
Consider alternatives that better fit your needs, such as interfaces, delegation, or mixins
Tweet this
Tip #52, pg. 162:
Prefer Interfaces to Express Polymorphism
Interfaces make polymorphism explicit without the coupling introduced by inheritance.
Tweet this
Tip #53, pg. 163:
Delegate to Services: Has-A Trumps Is-A
Don’t inherit from services: contain them.
9/17
Tweet this
Tip #54, pg. 165:
Use Mixins to Share Functionality
Mixins add functionality to classes without the inheritance tax. Combine with interfaces
for painless polymorphism.
Tweet this
Tip #55, pg. 166:
Parameterize Your App Using External Configuration
When code relies on values that may change after the application has gone live, keep those
values external to the app. When you application will run in different environments, and
potentially for different customers, keep the environment and customer specific values
outside the app.
Tweet this
Tip #56, pg. 171:
Analyze Workflow to Improve Concurrency
Exploit concurrency in your user’s workflow.
Tweet this
Tip #57, pg. 174:
Shared State Is Incorrect State
Shared state opens a large can of worms that can often only be fixed by rebooting.
Tweet this
Tip #58, pg. 180:
Random Failures Are Often Concurrency Issues
Variations in timing and context can expose concurrency bugs, but in inconsistent and
irreproducible ways.
Tweet this
Tip #59, pg. 182:
Use Actors For Concurrency Without Shared State
Use Actors to manage concurrent state without explicit synchronization.
10/17
Tweet this
Tip #60, pg. 189:
Use Blackboards to Coordinate Workflow
Use blackboards to coordinate disparate facts and agents, while maintaining
independence and isolation among participants.
Tweet this
Tip #61, pg. 194:
Listen to Your Inner Lizard
When it feels like your code is pushing back, it’s really your subconscious trying to tell you
something’s wrong.
Tweet this
Tip #62, pg. 200:
Don’t Program by Coincidence
Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy
coincidence with a purposeful plan.
Tweet this
Tip #63, pg. 207:
Estimate the Order of Your Algorithms
Get a feel for how long things are likely to take before you write code.
Tweet this
Tip #64, pg. 208:
Test Your Estimates
Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in
its target environment.
Tweet this
Tip #65, pg. 212:
Refactor Early, Refactor Often
Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code
when it needs it. Fix the root of the problem.
11/17
Tweet this
Tip #66, pg. 214:
Testing Is Not About Finding Bugs
A test is a perspective into your code, and gives you feedback about its design, api, and
coupling.
Tweet this
Tip #67, pg. 216:
A Test Is the First User of Your Code
Use its feedback to guide what you do.
Tweet this
Tip #68, pg. 218:
Build End-To-End, Not Top-Down or Bottom Up
Build small pieces of end-to-end functionality, learning about the problem as you go.
Tweet this
Tip #69, pg. 221:
Design to Test
Start thinking about testing before you write a line of code.
Tweet this
Tip #70, pg. 223:
Test Your Software, or Your Users Will
Test ruthlessly. Don’t make your users find bugs for you.
Tweet this
Tip #71, pg. 224:
Use Property-Based Tests to Validate Your Assumptions
Property-based tests will try things you never thought to try, and exercise your code in
ways is wasn’t meant to be used.
Tweet this
12/17
Tip #72, pg. 234:
Keep It Simple and Minimize Attack Surfaces
Complex code creates a breeding ground for bugs and opportunities for attackers to
exploit.
Tweet this
Tip #73, pg. 235:
Apply Security Patches Quickly
Attackers deploy exploits as quick as they can, you have to be quicker.
Tweet this
Tip #74, pg. 242:
Name Well; Rename When Needed
Name to express your intent to readers, and rename as soon as that intent shifts.
Tweet this
Tip #75, pg. 244:
No One Knows Exactly What They Want
They might know a general direction, but they won’t know the twists and turns.
Tweet this
Tip #76, pg. 245:
Programmers Help People Understand What They Want
Software development is an act of co-creation between users and programmers.
Tweet this
Tip #77, pg. 246:
Requirements Are Learned in a Feedback Loop
Understanding requirements requires exploration and feedback, so the consequences of
decisions can be used to refine the initial ideas.
Tweet this
Tip #78, pg. 247:
13/17
Work with a User to Think Like a User
It’s the best way to gain insight into how the system will really be used.
Tweet this
Tip #79, pg. 248:
Policy Is Metadata
Don’t hardcode policy into a system; instead express it as metadata used by the system.
Tweet this
Tip #80, pg. 251:
Use a Project Glossary
Create and maintain a single source of all the specific terms and vocabulary for a project.
Tweet this
Tip #81, pg. 254:
Don’t Think Outside the Box—Find the Box
When faced with an impossible problem, identify the real constraints. Ask yourself: “Does
it have to be done this way? Does it have to be done at all?”
Tweet this
Tip #82, pg. 259:
Don't Go into the Code Alone
Programming can be difficult and demanding. Take a friend with you.
Tweet this
Tip #83, pg. 259:
Agile Is Not a Noun; Agile Is How You Do Things
Agile is an adjective: it’s how you do something.
Tweet this
Tip #84, pg. 264:
Maintain Small Stable Teams
14/17
Teams should be small and stable, where everyone trusts each other and depends on each
other.
Tweet this
Tip #85, pg. 266:
Schedule It to Make It Happen
If you don’t schedule it, it’s not going to happen. Schedule reflection, experimentation,
learning and skills improvement.
Tweet this
Tip #86, pg. 268:
Organize Fully Functional Teams
Organize Around Functionality, Not Job Functions. Don’t separate UI/UX designers from
coders, frontend from backend, testers from data modelers, design from deployment.
Build teams so you can build code end-to-end, incrementally and iteratively.
Tweet this
Tip #87, pg. 271:
Do What Works, Not What’s Fashionable
Don’t adopt a development method or technique just because other companies are doing
it. Adopt what works for your team, in your context.
Tweet this
Tip #88, pg. 273:
Deliver When Users Need It
Don’t wait weeks or months to deliver just because your process demands it.
Tweet this
Tip #89, pg. 274:
Use Version Control to Drive Builds, Tests, and Releases
Use commits or pushes to trigger builds, tests, releases. Use a version control tag to
deploy to production.
Tweet this
Tip #90, pg. 275:
15/17
Test Early, Test Often, Test Automatically
Tests that run with every build are much more effective than test plans that sit on a shelf.
Tweet this
Tip #91, pg. 275:
Coding Ain’t Done ’Til All the Tests Run
’Nuff said.
Tweet this
Tip #92, pg. 277:
Use Saboteurs to Test Your Testing
Introduce bugs on purpose in a separate copy of the source to verify that testing will catch
them.
Tweet this
Tip #93, pg. 278:
Test State Coverage, Not Code Coverage
Identify and test significant program states. Testing just lines of code isn’t enough.
Tweet this
Tip #94, pg. 278:
Find Bugs Once
Once a human tester finds a bug, it should be the last time a human tester finds that bug.
Automatic tests should check for it from then on.
Tweet this
Tip #95, pg. 279:
Don't Use Manual Procedures
A computer will execute the same instructions, in the same order, time after time.
Tweet this
Tip #96, pg. 281:
Delight Users, Don’t Just Deliver Code
16/17
Develop solutions that produce business value for your users and delight them every day.
Tweet this
Tip #97, pg. 282:
Sign Your Work
Artisans of an earlier age were proud to sign their work. You should be, too.
Tweet this
Tip #98, pg. 286:
First, Do No Harm
Failure is inevitable. Make sure no one will suffer because of it.
Tweet this
Tip #99, pg. 287:
Don’t Enable Scumbags
Because you risk becoming one, too.
Tweet this
Tip #100, pg. 287:
It’s Your Life. Share it. Celebrate it. Build it. AND HAVE FUN!
Enjoy this amazing life we have, and do great things.
Tweet this
17/17