مرکزی صفحہ The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition

The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition

0 / 0
How much do you like this book?
What’s the quality of the file?
Download the book for quality assessment
What’s the quality of the downloaded files?
Straight from the trenches,The Pragmatic Programmer, 20th Anniversary Editioncuts through the increasing specialization and technicalities of modern software development to examine the core process: transforming a requirement into working, maintainable code that delights users. Extensively updated with ten new sections and major revisions throughout, this edition covers topics ranging from career development to architectural techniques for keeping code flexible, adaptable, and reusable.
Organized into self-contained sections -- and filled with compelling anecdotes, examples, and analogies -- The Pragmatic Programmer illustrates today's best practices and major pitfalls of many different aspects of software development. Wherever possible, the authors abstract away specific technologies, focusing on insights you can apply no matter what tools or languages you use -- or will use.
Whether you're a new coder, an experienced programmer, or a manager responsible for software projects, applying this guide's lessons will help you rapidly improve your productivity, quality, and job satisfaction. You'll learn skills and develop habits and attitudes that form the foundation for long-term success in your career. You'll become a Pragmatic Programmer.
سب زمرہ:
ناشر کتب:
Addison-Wesley Professional
352 / 497
ISBN 10:
ISBN 13:
PDF, 4.20 MB
ڈاؤن لوڈ کریں (pdf, 4.20 MB)

آپ کو دلچسپی ہوسکتی ہے Powered by Rec2Me


اہم جملے


آپ کتاب کا معائنہ کر سکتے ہیں اور اپنے تجربات شیئر کرسکتے ہیں۔ دوسرے قارئین کتابوں کے بارے میں آپ کی رائے میں ہمیشہ دلچسپی رکھیں گے۔ چاہے آپ کو کتاب پسند ہے یا نہیں ، اگر آپ اپنے دیانتدار اور تفصیلی خیالات دیںگے تو لوگوں کو نئی کتابیں ملیںگی جو ان کے لئے صحیح ہیں۔
The Pragmatic
Version: P1.0 (September 13, 2019)

Many of the designations used by manufacturers
and sellers to distinguish their products are
claimed as trademarks. Where those designations
appear in this book, and the publisher was aware of
a trademark claim, the designations have been
printed with initial capital letters or in all capitals.
"The Pragmatic Programmer" and the linking g
device are trademarks of The Pragmatic
Programmers, LLC.
The authors and publisher have taken care in the
preparation of this book, but make no expressed or
implied warranty of any kind and assume no
responsibility for errors or omissions. No liability
is assumed for incidental or consequential
damages in connection with or arising out of the
use of the information or programs contained
For information about buying this title in bulk
quantities, or for special sales opportunities (which
may include electronic versions; custom cover
designs; and content particular to your business,
training goals, marketing focus, or branding
interests), please contact our corporate sales
department at corpsales@pearsoned.com or
(800) 382-3419.
For government sales inquiries, please contact
governmentsales@pearsoned.com. For questions
about sales outside the U.S., please contact
intlcs@pearson.com. Visit us on the Web:

Library of Congress Control Number: 2019944178
Copyright © 2020 Pearson Education, Inc.
Cover images: Mihalec/Shutterstock,
All rights reserved. This publication is protected by
copyright, and permission must be obtained from
the publisher prior to any prohibited reproduction,
storage in a retrieval system, or transmission in
any form or by any means, electronic, mechanical,
photocopying, recording, or likewise. For
information regarding permissions, request forms
and the appro- priate contacts within the Pearson
Education Global Rights & Permissions
Department, please visit
www.pearsoned.com/permissions; .
ISBN-13: 978-0-13-595705-9
ISBN-10: 0-13-595705-2

For Juliet and Ellie,
Zachary and Elizabeth,
Henry and Stuart

Table of Contents




Preface to the Second Edition
1. How the Book Is Organized
2. What’s in a Name?
3. Source Code and Other Resources
4. Send Us Feedback
5. Second Edition Acknowledgments

From the Preface to the First Edition


1. Who Should Read This Book?
2. What Makes a Pragmatic Programmer?
3. Individual Pragmatists, Large Teams
4. It’s a Continuous Process
4. 1.

A Pragmatic Philosophy


Topic 1.

It’s Your Life


Topic 2.

The Cat Ate My Source Code


Topic 3.

Software Entropy


Topic 4.

Stone Soup and Boiled Frogs


Topic 5.

Good-Enough Software


Topic 6.

Your Knowledge Portfolio


Topic 7.


5. 2.

A Pragmatic Approach


Topic 8.

The Essence of Good Design


Topic 9.

DRY—The Evils of Duplication


Topic 10.



Topic 11.



Topic 12.

Tracer Bullets


Topic 13.

Prototypes and Post-it Notes


Topic 14.

Domain Languages


Topic 15.


6. 3.

The Basic Tools


Topic 16.

The Power of Plain Text


Topic 17.

Shell Games


Topic 18.

Power Editing


Topic 19.

Version Control


Topic 20.



Topic 21.

Text Manipulation


Topic 22.

Engineering Daybooks

7. 4.

Pragmatic Paranoia


Topic 23.

Design by Contract


Topic 24.

Dead Programs Tell No Lies


Topic 25.

Assertive Programming


Topic 26.

How to Balance Resources


Topic 27.

Don’t Outrun Your Headlights

8. 5.

Bend, or Break


Topic 28.



Topic 29.

Juggling the Real World


Topic 30.

Transforming Programming


Topic 31.

Inheritance Tax


Topic 32.


9. 6.



Topic 33.

Breaking Temporal Coupling


Topic 34.

Shared State Is Incorrect State


Topic 35.

Actors and Processes


Topic 36.


10. 7.

While You Are Coding


Topic 37.

Listen to Your Lizard Brain


Topic 38.

Programming by Coincidence


Topic 39.

Algorithm Speed


Topic 40.



Topic 41.

Test to Code


Topic 42.

Property-Based Testing


Topic 43.

Stay Safe Out There


Topic 44.

Naming Things

11. 8.

Before the Project


Topic 45.

The Requirements Pit


Topic 46.

Solving Impossible Puzzles


Topic 47.

Working Together


Topic 48.

The Essence of Agility

12. 9.

Pragmatic Projects


Topic 49.

Pragmatic Teams


Topic 50.

Coconuts Don’t Cut It


Topic 51.

Pragmatic Starter Kit


Topic 52.

Delight Your Users


Topic 53.

Pride and Prejudice

13. 10. Postface
14. A1. Bibliography
15. A2. Possible Answers to the Exercises

Copyright © 2020 Pearson Education, Inc.

Praise for the second edition of
The Pragmatic Programmer
Some say that with The Pragmatic Programmer, Andy and
Dave captured lightning in a bottle; that it’s unlikely anyone
will soon write a book that can move an entire industry as it
did. Sometimes, though, lightning does strike twice, and this
book is proof. The updated content ensures that it will stay
at the top of “best books in software development” lists for
another 20 years, right where it belongs.

VM (Vicky) Brasseur
Director of Open Source Strategy, Juniper Networks

If you want your software to be easy to modernize and
maintain, keep a copy of The Pragmatic Programmer close.
It’s filled with practical advice, both technical and
professional, that will serve you and your projects well for
years to come.

Andrea Goulet
CEO, Corgibytes; Founder, LegacyCode.Rocks

The Pragmatic Programmer is the one book I can point to
that completely dislodged the existing trajectory of my
career in software and pointed me in the direction of
success. Reading it opened my mind to the possibilities of
being a craftsman, not just a cog in a big machine. One of
the most significant books in my life.

Obie Fernandez
Author, The Rails Way

First-time readers can look forward to an enthralling
induction into the modern world of software practice, a
world that the first edition played a major role in shaping.
Readers of the first edition will rediscover here the insights
and practical wisdom that made the book so significant in
the first place, expertly curated and updated, along with
much that’s new.

David A. Black
Author, The Well-Grounded Rubyist

I have an old paper copy of the original Pragmatic
Programmer on my bookshelf. It has been read and re-read
and a long time ago it changed everything about how I
approached my job as a programmer. In the new edition
everything and nothing has changed: I now read it on my
iPad and the code examples use modern programming

languages—but the underlying concepts, ideas, and attitudes
are timeless and universally applicable. Twenty years later,
the book is as relevant as ever. It makes me happy to know
that current and future developers will have the same
opportunity to learn from Andy and Dave’s profound
insights as I did back in the day.

Sandy Mamoli
Agile coach, author of How Self-Selection Lets People Excel

Twenty years ago, the first edition of The Pragmatic
Programmer completely changed the trajectory of my
career. This new edition could do the same for yours.

Mike Cohn
Author of Succeeding with Agile,
Agile Estimating and Planning, and
User Stories Applied

I remember when Dave and Andy first tweeted about the new
edition of this book. It was big news. I watched as the coding
community responded with excitement. My feed buzzed with
anticipation. After twenty years, The Pragmatic Programmer is
just as relevant today as it was back then.
It says a lot that a book with such history had such a reaction. I
had the privilege of reading an unreleased copy to write this
foreword, and I understood why it created such a stir. While it’s
a technical book, calling it that does it a disservice. Technical
books often intimidate. They’re stuffed with big words, obscure
terms, convoluted examples that, unintentionally, make you feel
stupid. The more experienced the author, the easier it is to
forget what it’s like to learn new concepts, to be a beginner.
Despite their decades of programming experience, Dave and
Andy have conquered the difficult challenge of writing with the
same excitement of people who’ve just learned these lessons.
They don’t talk down to you. They don’t assume you are an
expert. They don’t even assume you’ve read the first edition.
They take you as you are—programmers who just want to be
better. They spend the pages of this book helping you get there,
one actionable step at a time.

To be fair, they’d already done this before. The original release
was full of tangible examples, new ideas, and practical tips to
build your coding muscles and develop your coding brain that
still apply today. But this updated edition makes two
improvements on the book.
The first is the obvious one: it removes some of the older
references, the out-of-date examples, and replaces them with
fresh, modern content. You won’t find examples of loop
invariants or build machines. Dave and Andy have taken their
powerful content and made sure the lessons still come through,
free of the distractions of old examples. It dusts off old ideas like
DRY (don’t repeat yourself) and gives them a fresh coat of paint,
really making them shine.
But the second is what makes this release truly exciting. After
writing the first edition, they had the chance to reflect on what
they were trying to say, what they wanted their readers to take
away, and how it was being received. They got feedback on
those lessons. They saw what stuck, what needed refining, what
was misunderstood. In the twenty years that this book has made
its way through the hands and hearts of programmers all over
the world, Dave and Andy have studied this response and
formulated new ideas, new concepts.
They’ve learned the importance of agency and recognized that
developers have arguably more agency than most other
professionals. They start this book with the simple but profound
message: “it’s your life.” It reminds us of our own power in our
code base, in our jobs, in our careers. It sets the tone for
everything else in the book—that it’s more than just another
technical book filled with code examples.

What makes it truly stand out among the shelves of technical
books is that it understands what it means to be a programmer.
Programming is about trying to make the future less painful. It’s
about making things easier for our teammates. It’s about getting
things wrong and being able to bounce back. It’s about forming
good habits. It’s about understanding your toolset. Coding is
just part of the world of being a programmer, and this book
explores that world.
I spend a lot of time thinking about the coding journey. I didn’t
grow up coding; I didn’t study it in college. I didn’t spend my
teenage years tinkering with tech. I entered the coding world in
my mid-twenties and had to learn what it meant to be a
programmer. This community is very different from others I’d
been a part of. There is a unique dedication to learning and
practicality that is both refreshing and intimidating.
For me, it really does feel like entering a new world. A new
town, at least. I had to get to know the neighbors, pick my
grocery store, find the best coffee shops. It took a while to get
the lay of the land, to find the most efficient routes, to avoid the
streets with the heaviest traffic, to know when traffic was likely
to hit. The weather is different, I needed a new wardrobe.
The first few weeks, even months, in a new town can be scary.
Wouldn’t it be wonderful to have a friendly, knowledgeable
neighbor who’d been living there a while? Who can give you a
tour, show you those coffee shops? Someone who’d been there
long enough to know the culture, understand the pulse of the
town, so you not only feel at home, but become a contributing
member as well? Dave and Andy are those neighbors.
As a relative newcomer, it’s easy to be overwhelmed not by the

act of programming but the process of becoming a programmer.
There is an entire mindset shift that needs to happen—a change
in habits, behaviors, and expectations. The process of becoming
a better programmer doesn’t just happen because you know
how to code; it must be met with intention and deliberate
practice. This book is a guide to becoming a better programmer
But make no mistake—it doesn’t tell you how programming
should be. It’s not philosophical or judgmental in that way. It
tells you, plain and simple, what a Pragmatic Programmer is—
how they operate, and how they approach code. They leave it up
to you to decide if you want to be one. If you feel it’s not for you,
they won’t hold it against you. But if you decide it is, they’re
your friendly neighbors, there to show you the way.


Saron Yitbarek

Founder & CEO of CodeNewbie
Host of Command Line Heroes

Copyright © 2020 Pearson Education, Inc.

Preface to the Second Edition
Back in the 1990s, we worked with companies whose projects
were having problems. We found ourselves saying the same
things to each: maybe you should test that before you ship it;
why does the code only build on Mary’s machine? Why didn’t
anyone ask the users?
To save time with new clients, we started jotting down notes.
And those notes became The Pragmatic Programmer. To our
surprise the book seemed to strike a chord, and it has continued
to be popular these last 20 years.
But 20 years is many lifetimes in terms of software. Take a
developer from 1999 and drop them into a team today, and
they’d struggle in this strange new world. But the world of the
1990s is equally foreign to today’s developer. The book’s
references to things such as CORBA, CASE tools, and indexed
loops were at best quaint and more likely confusing.
At the same time, 20 years has had no impact whatsoever on
common sense. Technology may have changed, but people
haven’t. Practices and approaches that were a good idea then
remain a good idea now. Those aspects of the book aged well.
So when it came time to create this 20th Anniversary Edition,

we had to make a decision. We could go through and update the
technologies we reference and call it a day. Or we could
reexamine the assumptions behind the practices we
recommended in the light of an additional two decades’ worth
of experience.
In the end, we did both.
As a result, this book is something of a Ship of Theseus.[1]
Roughly one-third of the topics in the book are brand new. Of
the rest, the majority have been rewritten, either partially or
totally. Our intent was to make things clearer, more relevant,
and hopefully somewhat timeless.
We made some difficult decisions. We dropped the Resources
appendix, both because it would be impossible to keep up-todate and because it’s easier to search for what you want. We
reorganized and rewrote topics to do with concurrency, given
the current abundance of parallel hardware and the dearth of
good ways of dealing with it. We added content to reflect
changing attitudes and environments, from the agile movement
which we helped launch, to the rising acceptance of functional
programming idioms and the growing need to consider privacy
and security.
Interestingly, though, there was considerably less debate
between us on the content of this edition than there was when
we wrote the first. We both felt that the stuff that was important
was easier to identify.
Anyway, this book is the result. Please enjoy it. Maybe adopt
some new practices. Maybe decide that some of the stuff we
suggest is wrong. Get involved in your craft. Give us feedback.

But, most important, remember to make it fun.

How the Book Is Organized
This book is written as a collection of short topics. Each topic is
self-contained, and addresses a particular theme. You’ll find
numerous cross references, which help put each topic in
context. Feel free to read the topics in any order—this isn’t a
book you need to read front-to-back.
Occasionally you’ll come across a box labeled Tip nn (such as
Tip 1, Care About Your Craft). As well as emphasizing points in
the text, we feel the tips have a life of their own—we live by
them daily. You’ll find a summary of all the tips on a pull-out
card inside the back cover.
We’ve included exercises and challenges where appropriate.
Exercises normally have relatively straightforward answers,
while the challenges are more open-ended. To give you an idea
of our thinking, we’ve included our answers to the exercises in
an appendix, but very few have a single correct solution. The
challenges might form the basis of group discussions or essay
work in advanced programming courses.
There’s also a short bibliography listing the books and articles
we explicitly reference.

What’s in a Name?
Scattered throughout the book you’ll find various bits of jargon
—either perfectly good English words that have been corrupted
to mean something technical, or horrendous made-up words
that have been assigned meanings by computer scientists with a
grudge against the language. The first time we use each of these
jargon words, we try to define it, or at least give a hint to its
meaning. However, we’re sure that some have fallen through
the cracks, and others, such as object and relational database,
are in common enough usage that adding a definition would be
boring. If you do come across a term you haven’t seen before,
please don’t just skip over it. Take time to look it up, perhaps on
the web, or maybe in a computer science textbook. And, if you
get a chance, drop us an email and complain, so we can add a
definition to the next edition.
Having said all this, we decided to get revenge against the
computer scientists. Sometimes, there are perfectly good jargon
words for concepts, words that we’ve decided to ignore. Why?
Because the existing jargon is normally restricted to a particular
problem domain, or to a particular phase of development.
However, one of the basic philosophies of this book is that most
of the techniques we’re recommending are universal:
modularity applies to code, designs, documentation, and team
organization, for instance. When we wanted to use the
conventional jargon word in a broader context, it got confusing
—we couldn’t seem to overcome the baggage the original term
brought with it. When this happened, we contributed to the
decline of the language by inventing our own terms.

Source Code and Other Resources
Most of the code shown in this book is extracted from
compilable source files, available for download from our
There you’ll also find links to resources we find useful, along
with updates to the book and news of other Pragmatic
Programmer developments.

Send Us Feedback
We’d appreciate hearing from you. Email us at

Second Edition Acknowledgments
We have enjoyed literally thousands of interesting
conversations about programming over the last 20 years,
meeting people at conferences, at courses, and sometimes even
on the plane. Each one of these has added to our understanding
of the development process, and has contributed to the updates
in this edition. Thank you all (and keep telling us when we’re
Thanks to the participants in the book’s beta process. Your
questions and comments helped us explain things better.
Before we went beta, we shared the book with a few folks for
comments. Thanks to VM (Vicky) Brasseur, Jeff Langr, and Kim
Shrier for your detailed comments, and to José Valim and Nick
Cuthbert for your technical reviews.
Thanks to Ron Jeffries for letting us use the Sudoku example.
Much gratitude to the folks at Pearson who agreed to let us
create this book our way.
A special thanks to the indispensable Janet Furlow, who
masters whatever she takes on and keeps us in line.
And, finally, a shout out to all the Pragmatic Programmers out
there who have been making programming better for everyone
for the last twenty years. Here’s to twenty more.

[1] If, over the years, every component of a ship is replaced as it fails, is the resulting vessel
the same ship?
[2] https://pragprog.com/titles/tpp20

Copyright © 2020 Pearson Education, Inc.

From the Preface to the First
This book will help you become a better programmer.
You could be a lone developer, a member of a large project
team, or a consultant working with many clients at once. It
doesn’t matter; this book will help you, as an individual, to do
better work. This book isn’t theoretical—we concentrate on
practical topics, on using your experience to make more
informed decisions. The word pragmatic comes from the Latin
pragmaticus—“skilled in business”—which in turn is derived
from the Greek πραγματικός, meaning “fit for use.”
This is a book about doing.
Programming is a craft. At its simplest, it comes down to getting
a computer to do what you want it to do (or what your user
wants it to do). As a programmer, you are part listener, part
advisor, part interpreter, and part dictator. You try to capture
elusive requirements and find a way of expressing them so that
a mere machine can do them justice. You try to document your
work so that others can understand it, and you try to engineer
your work so that others can build on it. What’s more, you try to
do all this against the relentless ticking of the project clock. You

work small miracles every day.
It’s a difficult job.
There are many people offering you help. Tool vendors tout the
miracles their products perform. Methodology gurus promise
that their techniques guarantee results. Everyone claims that
their programming language is the best, and every operating
system is the answer to all conceivable ills.
Of course, none of this is true. There are no easy answers. There
is no best solution, be it a tool, a language, or an operating
system. There can only be systems that are more appropriate in
a particular set of circumstances.
This is where pragmatism comes in. You shouldn’t be wedded to
any particular technology, but have a broad enough background
and experience base to allow you to choose good solutions in
particular situations. Your background stems from an
understanding of the basic principles of computer science, and
your experience comes from a wide range of practical projects.
Theory and practice combine to make you strong.
You adjust your approach to suit the current circumstances and
environment. You judge the relative importance of all the
factors affecting a project and use your experience to produce
appropriate solutions. And you do this continuously as the work
progresses. Pragmatic Programmers get the job done, and do it

Who Should Read This Book?
This book is aimed at people who want to become more effective
and more productive programmers. Perhaps you feel frustrated
that you don’t seem to be achieving your potential. Perhaps you
look at colleagues who seem to be using tools to make
themselves more productive than you. Maybe your current job
uses older technologies, and you want to know how newer ideas
can be applied to what you do.
We don’t pretend to have all (or even most) of the answers, nor
are all of our ideas applicable in all situations. All we can say is
that if you follow our approach, you’ll gain experience rapidly,
your productivity will increase, and you’ll have a better
understanding of the entire development process. And you’ll
write better software.

What Makes a Pragmatic Programmer?
Each developer is unique, with individual strengths and
weaknesses, preferences and dislikes. Over time, each will craft
their own personal environment. That environment will reflect
the programmer’s individuality just as forcefully as his or her
hobbies, clothing, or haircut. However, if you’re a Pragmatic
Programmer, you’ll share many of the following characteristics:
Early adopter/fast adapter

You have an instinct for technologies and techniques, and
you love trying things out. When given something new,
you can grasp it quickly and integrate it with the rest of
your knowledge. Your confidence is born of experience.

You tend to ask questions. That’s neat—how did you do
that? Did you have problems with that library? What’s
this quantum computing I’ve heard about? How are
symbolic links implemented? You are a pack rat for little
facts, each of which may affect some decision years from
Critical thinker

You rarely take things as given without first getting the
facts. When colleagues say “because that’s the way it’s
done,” or a vendor promises the solution to all your
problems, you smell a challenge.

You try to understand the underlying nature of each
problem you face. This realism gives you a good feel for

how difficult things are, and how long things will take.
Deeply understanding that a process should be difficult
or will take a while to complete gives you the stamina to
keep at it.
Jack of all trades

You try hard to be familiar with a broad range of
technologies and environments, and you work to keep
abreast of new developments. Although your current job
may require you to be a specialist, you will always be able
to move on to new areas and new challenges.
We’ve left the most basic characteristics until last. All Pragmatic
Programmers share them. They’re basic enough to state as tips:
Tip 1

Care About Your Craft

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

Think! About Your Work

In order to be a Pragmatic Programmer, we’re challenging you
to think about what you’re doing while you’re doing it. This isn’t
a one-time audit of current practices—it’s an ongoing critical
appraisal of every decision you make, every day, and on every
project. Never run on auto-pilot. Constantly be thinking,
critiquing your work in real time. The old IBM corporate motto,
THINK!, is the Pragmatic Programmer’s mantra.
If this sounds like hard work to you, then you’re exhibiting the
realistic characteristic. This is going to take up some of your

valuable time—time that is probably already under tremendous
pressure. The reward is a more active involvement with a job
you love, a feeling of mastery over an increasing range of
subjects, and pleasure in a feeling of continuous improvement.
Over the long term, your time investment will be repaid as you
and your team become more efficient, write code that’s easier to
maintain, and spend less time in meetings.

Individual Pragmatists, Large Teams
Some people feel that there is no room for individuality on large
teams or complex projects. “Software is an engineering
discipline,” they say, “that breaks down if individual team
members make decisions for themselves.”
We strongly disagree.
There should be engineering in software construction. However,
this doesn’t preclude individual craftsmanship. Think about the
large cathedrals built in Europe during the Middle Ages. Each
took thousands of person-years of effort, spread over many
decades. Lessons learned were passed down to the next set of
builders, who advanced the state of structural engineering with
their accomplishments. But the carpenters, stonecutters,
carvers, and glass workers were all craftspeople, interpreting
the engineering requirements to produce a whole that
transcended the purely mechanical side of the construction. It
was their belief in their individual contributions that sustained
the projects: We who cut mere stones must always be
envisioning cathedrals.
Within the overall structure of a project there is always room for
individuality and craftsmanship. This is particularly true given
the current state of software engineering. One hundred years
from now, our engineering may seem as archaic as the
techniques used by medieval cathedral builders seem to today’s
civil engineers, while our craftsmanship will still be honored.

It’s a Continuous Process
A tourist visiting England’s Eton College asked the gardener
how he got the lawns so perfect. “That’s easy,” he replied, “You
just brush off the dew every morning, mow them every other
day, and roll them once a week.”
“Is that all?” asked the tourist. “Absolutely,” replied the
gardener. “Do that for 500 years and you’ll have a nice lawn,
Great lawns need small amounts of daily care, and so do great
programmers. Management consultants like to drop the word
kaizen in conversations. “Kaizen” is a Japanese term that
captures the concept of continuously making many small
improvements. It was considered to be one of the main reasons
for the dramatic gains in productivity and quality in Japanese
manufacturing and was widely copied throughout the world.
Kaizen applies to individuals, too. Every day, work to refine the
skills you have and to add new tools to your repertoire. Unlike
the Eton lawns, you’ll start seeing results in a matter of days.
Over the years, you’ll be amazed at how your experience has
blossomed and how your skills have grown.
Copyright © 2020 Pearson Education, Inc.

Chapter 1

A Pragmatic Philosophy
This book is about you.
Make no mistake, it is your career, and more importantly, Topic
1, It’s Your Life. You own it. You’re here because you know you
can become a better developer and help others become better as
well. You can become a Pragmatic Programmer.
What distinguishes Pragmatic Programmers? We feel it’s an
attitude, a style, a philosophy of approaching problems and
their solutions. They think beyond the immediate problem,
placing it in its larger context and seeking out the bigger picture.
After all, without this larger context, how can you be pragmatic?
How can you make intelligent compromises and informed
Another key to their success is that Pragmatic Programmers
take responsibility for everything they do, which we discuss in
Topic 2, The Cat Ate My Source Code. Being responsible,
Pragmatic Programmers won’t sit idly by and watch their
projects fall apart through neglect. In Topic 3, Software
Entropy, we tell you how to keep your projects pristine.
Most people find change difficult, sometimes for good reasons,

sometimes because of plain old inertia. In Topic 4, Stone Soup
and Boiled Frogs, we look at a strategy for instigating change
and (in the interests of balance) present the cautionary tale of
an amphibian that ignored the dangers of gradual change.
One of the benefits of understanding the context in which you
work is that it becomes easier to know just how good your
software has to be. Sometimes near-perfection is the only
option, but often there are trade-offs involved. We explore this
in Topic 5, Good-Enough Software.
Of course, you need to have a broad base of knowledge and
experience to pull all of this off. Learning is a continuous and
ongoing process. In Topic 6, Your Knowledge Portfolio, we
discuss some strategies for keeping the momentum up.
Finally, none of us works in a vacuum. We all spend a large
amount of time interacting with others. Topic 7, Communicate!
lists ways we can do this better.
Pragmatic programming stems from a philosophy of pragmatic
thinking. This chapter sets the basis for that philosophy.

Topic 1

It’s Your Life

I’m not in this world to
live up to your
expectations and
you’re not in this world
to live up to mine.

It is your life. You own it. You run
it. You create it.

Many developers we talk to are
frustrated. Their concerns are
varied. Some feel they’re
stagnating in their job, others that
technology has passed them by.
Bruce Lee
Folks feel they are under
appreciated, or underpaid, or that
their teams are toxic. Maybe they
want to move to Asia, or Europe, or work from home.
And the answer we give is always the same.
“Why can’t you change it?”
Software development must appear close to the top of any list of
careers where you have control. Our skills are in demand, our
knowledge crosses geographic boundaries, we can work
remotely. We’re paid well. We really can do just about anything
we want.
But, for some reason, developers seem to resist change. They
hunker down, and hope things will get better. They look on,
passively, as their skills become dated and complain that their
companies don’t train them. They look at ads for exotic
locations on the bus, then step off into the chilling rain and

trudge into work.
So here’s the most important tip in the book.
Tip 3

You Have Agency

Does your work environment suck? Is your job boring? Try to
fix it. But don’t try forever. As Martin Fowler says, “you can
change your organization or change your organization.”[3]
If technology seems to be passing you by, make time (in your
own time) to study new stuff that looks interesting. You’re
investing in yourself, so doing it while you’re off-the-clock is
only reasonable.
Want to work remotely? Have you asked? If they say no, then
find someone who says yes.
This industry gives you a remarkable set of opportunities. Be
proactive, and take them.
Topic 4, Stone Soup and Boiled Frogs
Topic 6, Your Knowledge Portfolio

Topic 2

The Cat Ate My Source Code

One of the cornerstones of the
pragmatic philosophy is the idea of
The greatest of all
taking responsibility for yourself
weaknesses is the fear
and your actions in terms of your
of appearing weak.
career advancement, your learning
and education, your project, and
J.B. Bossuet, Politics from
your day-to-day work. Pragmatic
Holy Writ, 1709
Programmers take charge of their
own career, and aren’t afraid to
admit ignorance or error. It’s not the most pleasant aspect of
programming, to be sure, but it will happen—even on the best of
projects. Despite thorough testing, good documentation, and
solid automation, things go wrong. Deliveries are late.
Unforeseen technical problems come up.
These things happen, and we try to deal with them as
professionally as we can. This means being honest and direct.
We can be proud of our abilities, but we must own up to our
shortcomings—our ignorance and our mistakes.
Above all, your team needs to be able to trust and rely on you—
and you need to be comfortable relying on each of them as well.
Trust in a team is absolutely essential for creativity and
collaboration according to the research literature.[4] In a healthy
environment based in trust, you can safely speak your mind,
present your ideas, and rely on your team members who can in

turn rely on you. Without trust, well…
Imagine a high-tech, stealth ninja team infiltrating the villain’s
evil lair. After months of planning and delicate execution, you’ve
made it on site. Now it’s your turn to set up the laser guidance
grid: “Sorry, folks, I don’t have the laser. The cat was playing
with the red dot and I left it at home.”
That sort of breach of trust might be hard to repair.
Responsibility is something you actively agree to. You make a
commitment to ensure that something is done right, but you
don’t necessarily have direct control over every aspect of it. In
addition to doing your own personal best, you must analyze the
situation for risks that are beyond your control. You have the
right not to take on a responsibility for an impossible situation,
or one in which the risks are too great, or the ethical
implications too sketchy. You’ll have to make the call based on
your own values and judgment.
When you do accept the responsibility for an outcome, you
should expect to be held accountable for it. When you make a
mistake (as we all do) or an error in judgment, admit it honestly
and try to offer options.
Don’t blame someone or something else, or make up an excuse.
Don’t blame all the problems on a vendor, a programming
language, management, or your coworkers. Any and all of these
may play a role, but it is up to you to provide solutions, not
If there was a risk that the vendor wouldn’t come through for

you, then you should have had a contingency plan. If your mass
storage melts—taking all of your source code with it—and you
don’t have a backup, it’s your fault. Telling your boss “the cat ate
my source code’’ just won’t cut it.
Tip 4

Provide Options, Don’t Make Lame Excuses

Before you approach anyone to tell them why something can’t
be done, is late, or is broken, stop and listen to yourself. Talk to
the rubber duck on your monitor, or the cat. Does your excuse
sound reasonable, or stupid? How’s it going to sound to your
Run through the conversation in your mind. What is the other
person likely to say? Will they ask, “Have you tried this…” or
“Didn’t you consider that?” How will you respond? Before you
go and tell them the bad news, is there anything else you can
try? Sometimes, you just know what they are going to say, so
save them the trouble.
Instead of excuses, provide options. Don’t say it can’t be done;
explain what can be done to salvage the situation. Does code
have to be deleted? Tell them so, and explain the value of
refactoring (see Topic 40, Refactoring).
Do you need to spend time prototyping to determine the best
way to proceed (see Topic 13, Prototypes and Post-it Notes)? Do
you need to introduce better testing (see Topic 41, Test to Code,
and Ruthless and Continuous Testing) or automation to prevent
it from happening again?
Perhaps you need additional resources to complete this task. Or

maybe you need to spend more time with the users? Or maybe
it’s just you: do you need to learn some technique or technology
in greater depth? Would a book or a course help? Don’t be
afraid to ask, or to admit that you need help.
Try to flush out the lame excuses before voicing them aloud. If
you must, tell your cat first. After all, if little Tiddles is going to
take the blame….
Topic 49, Pragmatic Teams

How do you react when someone—such as a bank teller, an auto
mechanic, or a clerk—comes to you with a lame excuse? What do
you think of them and their company as a result?
When you find yourself saying, “I don’t know,” be sure to follow it
up with “—but I’ll find out.” It’s a great way to admit what you don’t
know, but then take responsibility like a pro.

Topic 3

Software Entropy

While software development is immune from almost all physical
laws, the inexorable increase in entropy hits us hard. Entropy is
a term from physics that refers to the amount of “disorder” in a
system. Unfortunately, the laws of thermodynamics guarantee
that the entropy in the universe tends toward a maximum.
When disorder increases in software, we call it “software rot.”
Some folks might call it by the more optimistic term, “technical
debt,” with the implied notion that they’ll pay it back someday.
They probably won’t.
Whatever the name, though, both debt and rot can spread
There are many factors that can contribute to software rot. The
most important one seems to be the psychology, or culture, at
work on a project. Even if you are a team of one, your project’s
psychology can be a very delicate thing. Despite the best-laid
plans and the best people, a project can still experience ruin and
decay during its lifetime. Yet there are other projects that,
despite enormous difficulties and constant setbacks,
successfully fight nature’s tendency toward disorder and
manage to come out pretty well.
What makes the difference?
In inner cities, some buildings are beautiful and clean, while
others are rotting hulks. Why? Researchers in the field of crime

and urban decay discovered a fascinating trigger mechanism,
one that very quickly turns a clean, intact, inhabited building
into a smashed and abandoned derelict.[5]
A broken window.
One broken window, left unrepaired for any substantial length
of time, instills in the inhabitants of the building a sense of
abandonment—a sense that the powers that be don’t care about
the building. So another window gets broken. People start
littering. Graffiti appears. Serious structural damage begins. In
a relatively short span of time, the building becomes damaged
beyond the owner’s desire to fix it, and the sense of
abandonment becomes reality.
Why would that make a difference? Psychologists have done
studies[6] that show hopelessness can be contagious. Think of
the flu virus in close quarters. Ignoring a clearly broken
situation reinforces the ideas that perhaps nothing can be fixed,
that no one cares, all is doomed; all negative thoughts which can
spread among team members, creating a vicious spiral.
Tip 5

Don’t Live with Broken Windows

Don’t leave “broken windows’’ (bad designs, wrong decisions, or
poor code) unrepaired. Fix each one as soon as it is discovered.
If there is insufficient time to fix it properly, then board it up.
Perhaps you can comment out the offending code, or display a
“Not Implemented” message, or substitute dummy data instead.
Take some action to prevent further damage and to show that
you’re on top of the situation.

We’ve seen clean, functional systems deteriorate pretty quickly
once windows start breaking. There are other factors that can
contribute to software rot, and we’ll touch on some of them
elsewhere, but neglect accelerates the rot faster than any other
You may be thinking that no one has the time to go around
cleaning up all the broken glass of a project. If so, then you’d
better plan on getting a dumpster, or moving to another
neighborhood. Don’t let entropy win.
Andy once had an acquaintance who was obscenely rich. His
house was immaculate, loaded with priceless antiques, objets
d’art, and so on. One day, a tapestry that was hanging a little too
close to a fireplace caught on fire. The fire department rushed in
to save the day—and his house. But before they dragged their
big, dirty hoses into the house, they stopped—with the fire
raging—to roll out a mat between the front door and the source
of the fire.
They didn’t want to mess up the carpet.
Now that sounds pretty extreme. Surely the fire department’s
first priority is to put out the fire, collateral damage be damned.
But they clearly had assessed the situation, were confident of
their ability to manage the fire, and were careful not to inflict
unnecessary damage to the property. That’s the way it must be
with software: don’t cause collateral damage just because there’s
a crisis of some sort. One broken window is one too many.
One broken window—a badly designed piece of code, a poor
management decision that the team must live with for the

duration of the project—is all it takes to start the decline. If you
find yourself working on a project with quite a few broken
windows, it’s all too easy to slip into the mindset of “All the rest
of this code is crap, I’ll just follow suit.” It doesn’t matter if the
project has been fine up to this point. In the original experiment
leading to the “Broken Window Theory,” an abandoned car sat
for a week untouched. But once a single window was broken, the
car was stripped and turned upside down within hours.
By the same token, if you find yourself on a project where the
code is pristinely beautiful—cleanly written, well designed, and
elegant—you will likely take extra special care not to mess it up,
just like the firefighters. Even if there’s a fire raging (deadline,
release date, trade show demo, etc.), you don’t want to be the
first one to make a mess and inflict additional damage.
Just tell yourself, “No broken windows.”
Topic 10, Orthogonality
Topic 40, Refactoring
Topic 44, Naming Things

Help strengthen your team by surveying your project
neighborhood. Choose two or three broken windows and discuss
with your colleagues what the problems are and what could be done
to fix them.
Can you tell when a window first gets broken? What is your
reaction? If it was the result of someone else’s decision, or a
management edict, what can you do about it?

Topic 4

Stone Soup and Boiled Frogs

The three soldiers returning home from war were hungry.
When they saw the village ahead their spirits lifted—they were
sure the villagers would give them a meal. But when they got
there, they found the doors locked and the windows closed.
After many years of war, the villagers were short of food, and
hoarded what they had.
Undeterred, the soldiers boiled a pot of water and carefully
placed three stones into it. The amazed villagers came out to
“This is stone soup,” the soldiers explained. “Is that all you put
in it?” asked the villagers. “Absolutely—although some say it
tastes even better with a few carrots…” A villager ran off,
returning in no time with a basket of carrots from his hoard.
A couple of minutes later, the villagers again asked “Is that it?”
“Well,” said the soldiers, “a couple of potatoes give it body.” Off
ran another villager.
Over the next hour, the soldiers listed more ingredients that
would enhance the soup: beef, leeks, salt, and herbs. Each time
a different villager would run off to raid their personal stores.
Eventually they had produced a large pot of steaming soup.
The soldiers removed the stones, and they sat down with the
entire village to enjoy the first square meal any of them had

eaten in months.
There are a couple of morals in the stone soup story. The
villagers are tricked by the soldiers, who use the villagers’
curiosity to get food from them. But more importantly, the
soldiers act as a catalyst, bringing the village together so they
can jointly produce something that they couldn’t have done by
themselves—a synergistic result. Eventually everyone wins.
Every now and then, you might want to emulate the soldiers.
You may be in a situation where you know exactly what needs
doing and how to do it. The entire system just appears before
your eyes—you know it’s right. But ask permission to tackle the
whole thing and you’ll be met with delays and blank stares.
People will form committees, budgets will need approval, and
things will get complicated. Everyone will guard their own
resources. Sometimes this is called “start-up fatigue.’’
It’s time to bring out the stones. Work out what you can
reasonably ask for. Develop it well. Once you’ve got it, show
people, and let them marvel. Then say “of course, it would be
better if we added…’’ Pretend it’s not important. Sit back and
wait for them to start asking you to add the functionality you
originally wanted. People find it easier to join an ongoing
success. Show them a glimpse of the future and you’ll get them
to rally around.[7]
Tip 6

Be a Catalyst for Change

On the other hand, the stone soup story is also about gentle and

gradual deception. It’s about focusing too tightly. The villagers
think about the stones and forget about the rest of the world.
We all fall for it, every day. Things just creep up on us.
We’ve all seen the symptoms. Projects slowly and inexorably get
totally out of hand. Most software disasters start out too small
to notice, and most project overruns happen a day at a time.
Systems drift from their specifications feature by feature, while
patch after patch gets added to a piece of code until there’s
nothing of the original left. It’s often the accumulation of small
things that breaks morale and teams.
Tip 7

Remember the Big Picture

We’ve never tried this—honest. But “they” say that if you take a
frog and drop it into boiling water, it will jump straight back out
again. However, if you place the frog in a pan of cold water, then
gradually heat it, the frog won’t notice the slow increase in
temperature and will stay put until cooked.
Note that the frog’s problem is different from the broken
windows issue discussed in Topic 3, Software Entropy. In the
Broken Window Theory, people lose the will to fight entropy
because they perceive that no one else cares. The frog just
doesn’t notice the change.
Don’t be like the fabled frog. Keep an eye on the big picture.
Constantly review what’s happening around you, not just what
you personally are doing.
Topic 1, It’s Your Life

Topic 38, Programming by Coincidence

While reviewing a draft of the first edition, John Lakos raised the
following issue: The soldiers progressively deceive the villagers, but
the change they catalyze does them all good. However, by
progressively deceiving the frog, you’re doing it harm. Can you
determine whether you’re making stone soup or frog soup when
you try to catalyze change? Is the decision subjective or objective?
Quick, without looking, how many lights are in the ceiling above
you? How many exits in the room? How many people? Is there
anything out of context, anything that looks like it doesn’t belong?
This is an exercise in situational awareness, a technique practiced
by folks ranging from Boy and Girl Scouts to Navy SEALs. Get in
the habit of really looking and noticing your surroundings. Then do
the same for your project.

Topic 5

Good-Enough Software

There’s an old(ish) joke about a
company that places an order for
Striving to better, oft
100,000 ICs with a Japanese
we mar what’s well.
manufacturer. Part of the
specification was the defect rate:
Shakespeare, King Lear 1.4
one chip in 10,000. A few weeks
later the order arrived: one large
box containing thousands of ICs, and a small one containing
just ten. Attached to the small box was a label that read: “These
are the faulty ones.’’
If only we really had this kind of control over quality. But the
real world just won’t let us produce much that’s truly perfect,
particularly not bug-free software. Time, technology, and
temperament all conspire against us.
However, this doesn’t have to be frustrating. As Ed Yourdon
described in an article in IEEE Software, When good-enough
software is best [You95], you can discipline yourself to write
software that’s good enough—good enough for your users, for
future maintainers, for your own peace of mind. You’ll find that
you are more productive and your users are happier. And you
may well find that your programs are actually better for their
shorter incubation.
Before we go any further, we need to qualify what we’re about to
say. The phrase “good enough’’ does not imply sloppy or poorly

produced code. All systems must meet their users’ requirements
to be successful, and meet basic performance, privacy, and
security standards. We are simply advocating that users be
given an opportunity to participate in the process of deciding
when what you’ve produced is good enough for their needs.
Normally you’re writing software for other people. Often you’ll
remember to find out what they want.[8] But do you ever ask
them how good they want their software to be? Sometimes
there’ll be no choice. If you’re working on pacemakers, an
autopilot, or a low-level library that will be widely disseminated,
the requirements will be more stringent and your options more
However, if you’re working on a brand-new product, you’ll have
different constraints. The marketing people will have promises
to keep, the eventual end users may have made plans based on a
delivery schedule, and your company will certainly have cashflow constraints. It would be unprofessional to ignore these
users’ requirements simply to add new features to the program,
or to polish up the code just one more time. We’re not
advocating panic: it is equally unprofessional to promise
impossible time scales and to cut basic engineering corners to
meet a deadline.
The scope and quality of the system you produce should be
discussed as part of that system’s requirements.
Tip 8

Make Quality a Requirements Issue

Often you’ll be in situations where trade-offs are involved.

Surprisingly, many users would rather use software with some
rough edges today than wait a year for the shiny, bells-andwhistles version (and in fact what they will need a year from
now may be completely different anyway). Many IT
departments with tight budgets would agree. Great software
today is often preferable to the fantasy of perfect software
tomorrow. If you give your users something to play with early,
their feedback will often lead you to a better eventual solution
(see Topic 12, Tracer Bullets).
In some ways, programming is like painting. You start with a
blank canvas and certain basic raw materials. You use a
combination of science, art, and craft to determine what to do
with them. You sketch out an overall shape, paint the
underlying environment, then fill in the details. You constantly
step back with a critical eye to view what you’ve done. Every
now and then you’ll throw a canvas away and start again.
But artists will tell you that all the hard work is ruined if you
don’t know when to stop. If you add layer upon layer, detail over
detail, the painting becomes lost in the paint.
Don’t spoil a perfectly good program by overembellishment and
overrefinement. Move on, and let your code stand in its own
right for a while. It may not be perfect. Don’t worry: it could
never be perfect. (In Chapter 7, While You Are Coding, we’ll
discuss philosophies for developing code in an imperfect world.)
Topic 45, The Requirements Pit

Topic 46, Solving Impossible Puzzles

Look at the software tools and operating systems that you use
regularly. Can you find any evidence that these organizations
and/or developers are comfortable shipping software they know is
not perfect? As a user, would you rather (1) wait for them to get all
the bugs out, (2) have complex software and accept some bugs, or
(3) opt for simpler software with fewer defects?
Consider the effect of modularization on the delivery of software.
Will it take more or less time to get a tightly coupled monolithic
block of software to the required quality compared with a system
designed as very loosely coupled modules or microservices? What
are the advantages or disadvantages of each approach?
Can you think of popular software that suffers from feature bloat?
That is, software containing far more features than you would ever
use, each feature introducing more opportunity for bugs and
security vulnerabilities, and making the features you do use harder
to find and manage. Are you in danger of falling into this trap

Topic 6

Your Knowledge Portfolio

An investment in
knowledge always
pays the best interest.
Benjamin Franklin

Ah, good old Ben Franklin—never
at a loss for a pithy homily. Why, if
we could just be early to bed and
early to rise, we’d be great
programmers—right? The early
bird might get the worm, but what
happens to the early worm?

In this case, though, Ben really hit
the nail on the head. Your knowledge and experience are your
most important day-to-day professional assets.
Unfortunately, they’re expiring assets.[9] Your knowledge
becomes out of date as new techniques, languages, and
environments are developed. Changing market forces may
render your experience obsolete or irrelevant. Given the everincreasing pace of change in our technological society, this can
happen pretty quickly.
As the value of your knowledge declines, so does your value to
your company or client. We want to prevent this from ever
Your ability to learn new things is your most important strategic
asset. But how do you learn how to learn, and how do you know
what to learn?

We like to think of all the facts programmers know about
computing, the application domains they work in, and all their
experience as their knowledge portfolios. Managing a
knowledge portfolio is very similar to managing a financial
1. Serious investors invest regularly—as a habit.
2. Diversification is the key to long-term success.
3. Smart investors balance their portfolios between conservative and
high-risk, high-reward investments.
4. Investors try to buy low and sell high for maximum return.
5. Portfolios should be reviewed and rebalanced periodically.

To be successful in your career, you must invest in your
knowledge portfolio using these same guidelines.
The good news is that managing this kind of investment is a
skill just like any other—it can be learned. The trick is to make
yourself do it initially and form a habit. Develop a routine which
you follow until your brain internalizes it. At that point, you’ll
find yourself sucking up new knowledge automatically.
Invest regularly

Just as in financial investing, you must invest in your
knowledge portfolio regularly, even if it’s just a small
amount. The habit is as important as the sums, so plan to
use a consistent time and place, away from interruptions.
A few sample goals are listed in the next section.

The more different things you know, the more valuable

you are. As a baseline, you need to know the ins and outs
of the particular technology you are working with
currently. But don’t stop there. The face of computing
changes rapidly—hot technology today may well be close
to useless (or at least not in demand) tomorrow. The
more technologies you are comfortable with, the better
you will be able to adjust to change. And don’t forget all
the other skills you need, including those in nontechnical areas.
Manage risk

Technology exists along a spectrum from risky,
potentially high-reward to low-risk, low-reward
standards. It’s not a good idea to invest all of your money
in high-risk stocks that might collapse suddenly, nor
should you invest all of it conservatively and miss out on
possible opportunities. Don’t put all your technical eggs
in one basket.
Buy low, sell high

Learning an emerging technology before it becomes
popular can be just as hard as finding an undervalued
stock, but the payoff can be just as rewarding. Learning
Java back when it was first introduced and unknown may
have been risky at the time, but it paid off handsomely for
the early adopters when it became an industry mainstay
Review and rebalance

This is a very dynamic industry. That hot technology you
started investigating last month might be stone cold by
now. Maybe you need to brush up on that database
technology that you haven’t used in a while. Or perhaps

you could be better positioned for that new job opening if
you tried out that other language….
Of all these guidelines, the most important one is the simplest
to do:
Tip 9

Invest Regularly in Your Knowledge Portfolio

Now that you have some guidelines on what and when to add to
your knowledge portfolio, what’s the best way to go about
acquiring intellectual capital with which to fund your portfolio?
Here are a few suggestions:
Learn at least one new language every year

Different languages solve the same problems in different
ways. By learning several different approaches, you can
help broaden your thinking and avoid getting stuck in a
rut. Additionally, learning many languages is easy thanks
to the wealth of freely available software.
Read a technical book each month

While there’s a glut of short-form essays and occasionally
reliable answers on the web, for deep understanding you
need long-form books. Browse the booksellers for
technical books on interesting topics related to your
current project.[10] Once you’re in the habit, read a book a
month. After you’ve mastered the technologies you’re
currently using, branch out and study some that don’t
relate to your project.
Read nontechnical books, too

It is important to remember that computers are used by
people—people whose needs you are trying to satisfy. You
work with people, are employed by people, and get
hacked by people. Don’t forget the human side of the
equation, as that requires an entirely different skill set
(we ironically call these soft skills, but they are actually
quite hard to master).
Take classes

Look for interesting courses at a local or online college or
university, or perhaps at the next nearby trade show or
Participate in local user groups and meetups

Isolation can be deadly to your career; find out what
people are working on outside of your company. Don’t
just go and listen: actively participate.
Experiment with different environments

If you’ve worked only in Windows, spend some time with
Linux. If you’ve used only makefiles and an editor, try a
sophisticated IDE with cutting-edge features, and vice
Stay current

Read news and posts online on technology different from
that of your current project. It’s a great way to find out
what experiences other people are having with it, the
particular jargon they use, and so on.
It’s important to continue investing. Once you feel comfortable
with some new language or bit of technology, move on. Learn
another one.

It doesn’t matter whether you ever use any of these technologies
on a project, or even whether you put them on your resume. The
process of learning will expand your thinking, opening you to
new possibilities and new ways of doing things. The crosspollination of ideas is important; try to apply the lessons you’ve
learned to your current project. Even if your project doesn’t use
that technology, perhaps you can borrow some ideas. Get
familiar with object orientation, for instance, and you’ll write
procedural programs differently. Understand the functional
programming paradigm and you’ll write object-oriented code
differently, and so on.
So you’re reading voraciously, you’re on top of all the latest
breaking developments in your field (not an easy thing to do),
and somebody asks you a question. You don’t have the faintest
idea what the answer is, and freely admit as much.
Don’t let it stop there. Take it as a personal challenge to find the
answer. Ask around. Search the web—the scholarly parts too,
not just the consumer parts.
If you can’t find the answer yourself, find out who can. Don’t let
it rest. Talking to other people will help build your personal
network, and you may surprise yourself by finding solutions to
other, unrelated problems along the way. And that old portfolio
just keeps getting bigger….
All of this reading and researching takes time, and time is
already in short supply. So you need to plan ahead. Always have
something to read in an otherwise dead moment. Time spent
waiting for doctors and dentists can be a great opportunity to
catch up on your reading—but be sure to bring your own e-

reader with you, or you might find yourself thumbing through a
dog-eared 1973 article about Papua New Guinea.
The last important point is to think critically about what you
read and hear. You need to ensure that the knowledge in your
portfolio is accurate and unswayed by either vendor or media
hype. Beware of the zealots who insist that their dogma provides
the only answer—it may or may not be applicable to you and
your project.
Never underestimate the power of commercialism. Just because
a web search engine lists a hit first doesn’t mean that it’s the
best match; the content provider can pay to get top billing. Just
because a bookstore features a book prominently doesn’t mean
it’s a good book, or even popular; they may have been paid to
place it there.
Tip 10

Critically Analyze What You Read and Hear

Critical thinking is an entire discipline unto itself, and we
encourage you to read and study all you can about it. In the
meantime, here’s a head start with a few questions to ask and
think about.
Ask the “Five Whys”

A favorite consulting trick: ask “why?” at least five times.
Ask a question, and get an answer. Dig deeper by asking
“why?” Repeat as if you were a petulant four-year old
(but a polite one). You might be able to get closer to a
root cause this way.

Who does this benefit?

It may sound cynical, but follow the money can be a very
helpful path to analyze. The benefits to someone else or
another organization may be aligned with your own, or
What’s the context?

Everything occurs in its own context, which is why “one
size fits all” solutions often don’t. Consider an article or
book touting a “best practice.” Good questions to
consider are “best for who?” What are the prerequisites,
what are the consequences, short and long term?
When or Where would this work?

Under what circumstances? Is it too late? Too early?
Don’t stop with first-order thinking (what will happen
next), but use second-order thinking: what will happen
after that?
Why is this a problem?

Is there an underlying model? How does the underlying
model work?
Unfortunately, there are very few simple answers anymore. But
with your extensive portfolio, and by applying some critical
analysis to the torrent of technical articles you will read, you can
understand the complex answers.
Topic 1, It’s Your Life
Topic 22, Engineering Daybooks

Start learning a new language this week. Always programmed in the
same old language? Try Clojure, Elixir, Elm, F#, Go, Haskell,
Python, R, ReasonML, Ruby, Rust, Scala, Swift, TypeScript, or
anything else that appeals and/or looks as if you might like it.[11]
Start reading a new book (but finish this one first!). If you are doing
very detailed implementation and coding, read a book on design
and architecture. If you are doing high-level design, read a book on
coding techniques.
Get out and talk technology with people who aren’t involved in your
current project, or who don’t work for the same company. Network
in your company cafeteria, or maybe seek out fellow enthusiasts at
a local meetup.

Topic 7


I believe that it is
better to be looked over
than it is to be
Mae West, Belle of the
Nineties, 1934

Maybe we can learn a lesson from
Ms. West. It’s not just what you’ve
got, but also how you package it.
Having the best ideas, the finest
code, or the most pragmatic
thinking is ultimately sterile unless
you can communicate with other
people. A good idea is an orphan
without effective communication.

As developers, we have to communicate on many levels. We
spend hours in meetings, listening and talking. We work with
end users, trying to understand their needs. We write code,
which communicates our intentions to a machine and
documents our thinking for future generations of developers.
We write proposals and memos requesting and justifying
resources, reporting our status, and suggesting new approaches.
And we work daily within our teams to advocate our ideas,
modify existing practices, and suggest new ones. A large part of
our day is spent communicating, so we need to do it well.
Treat English (or whatever your native tongue may be) as just
another programming language. Write natural language as you
would write code: honor the DRY principle, ETC, automation,
and so on. (We discuss the DRY and ETC design principles in
the next chapter.)

Tip 11

English is Just Another Programming Language

We’ve put together a list of additional ideas that we find useful.
You’re communicating only if you’re conveying what you mean
to convey—just talking isn’t enough. To do that, you need to
understand the needs, interests, and capabilities of your
audience. We’ve all sat in meetings where a development geek
glazes over the eyes of the vice president of marketing with a
long monologue on the merits of some arcane technology. This
isn’t communicating: it’s just talking, and it’s annoying.[12]
Say you want to change your remote monitoring system to use a
third-party message broker to disseminate status notifications.
You can present this update in many different ways, depending
on your audience. End users will appreciate that their systems
can now interoperate with other services that use the broker.
Your marketing department will be able to use this fact to boost
sales. Development and operations managers will be happy
because the care and maintenance of that part of the system is
now someone else’s problem. Finally, developers may enjoy
getting experience with new APIs, and may even be able to find
new uses for the message broker. By making the appropriate
pitch to each group, you’ll get them all excited about your
As with all forms of communication, the trick here is to gather
feedback. Don’t just wait for questions: ask for them. Look at
body language, and facial expressions. One of the Neuro
Linguistic Programming presuppositions is “The meaning of
your communication is the response you get.” Continuously
improve your knowledge of your audience as you communicate.

Probably the most difficult part of the more formal styles of
communication used in business is working out exactly what it
is you want to say. Fiction writers often plot out their books in
detail before they start, but people writing technical documents
are often happy to sit down at a keyboard, enter:
1. Introduction

and start typing whatever comes into their heads next.
Plan what you want to say. Write an outline. Then ask yourself,
“Does this communicate what I want to express to my audience
in a way that works for them?” Refine it until it does.
This approach works for more than just documents. When
you’re faced with an important meeting or a chat with a major
client, jot down the ideas you want to communicate, and plan a
couple of strategies for getting them across.
Now that you know what your audience wants, let’s deliver it.
It’s six o’clock on Friday afternoon, following a week when the
auditors have been in. Your boss’s youngest is in the hospital,
it’s pouring rain outside, and the commute home is guaranteed
to be a nightmare. This probably isn’t a good time to ask her for
a memory upgrade for your laptop.
As part of understanding what your audience needs to hear, you
need to work out what their priorities are. Catch a manager
who’s just been given a hard time by her boss because some

source code got lost, and you’ll have a more receptive listener to
your ideas on source code repositories. Make what you’re saying
relevant in time, as well as in content. Sometimes all it takes is
the simple question, “Is this a good time to talk about…?’’
Adjust the style of your delivery to suit your audience. Some
people want a formal “just the facts’’ briefing. Others like a long,
wide-ranging chat before getting down to business. What is
their skill level and experience in this area? Are they experts?
Newbies? Do they need hand-holding or just a quick tl;dr? If in
doubt, ask.
Remember, however, that you are half of the communication
transaction. If someone says they need a paragraph describing
something and you can’t see any way of doing it in less than
several pages, tell them so. Remember, that kind of feedback is
a form of communication, too.
Your ideas are important. They deserve a good-looking vehicle
to convey them to your audience.
Too many developers (and their managers) concentrate solely
on content when producing written documents. We think this is
a mistake. Any chef (or watcher of the Food Network) will tell
you that you can slave in the kitchen for hours only to ruin your
efforts with poor presentation.
There is no excuse today for producing poor-looking printed
documents. Modern software can produce stunning output,
regardless of whether you’re writing using Markdown or using a

word processor. You need to learn just a few basic commands. If
you’re using a word processor, use its style sheets for
consistency. (Your company may already have defined style
sheets that you can use.) Learn how to set page headers and
footers. Look at the sample documents included with your
package to get ideas on style and layout. Check the spelling, first
automatically and then by hand. After awl, their are spelling
miss steaks that the chequer can knot ketch.
We often find that the documents we produce end up being less
important than the process we go through to produce them. If
possible, involve your readers with early drafts of your
document. Get their feedback, and pick their brains. You’ll build
a good working relationship, and you’ll probably produce a
better document in the process.
There’s one technique that you must use if you want people to
listen to you: listen to them. Even if this is a situation where you
have all the information, even if this is a formal meeting with
you standing in front of 20 suits—if you don’t listen to them,
they won’t listen to you.
Encourage people to talk by asking questions, or ask them to
restate the discussion in their own words. Turn the meeting into
a dialog, and you’ll make your point more effectively. Who
knows, you might even learn something.
If you ask someone a question, you feel they’re impolite if they
don’t respond. But how often do you fail to get back to people

when they send you an email or a memo asking for information
or requesting some action? In the rush of everyday life, it’s easy
to forget. Always respond to emails and voicemails, even if the
response is simply “I’ll get back to you later.’’ Keeping people
informed makes them far more forgiving of the occasional slip,
and makes them feel that you haven’t forgotten them.
Tip 12

It’s Both What You Say and the Way You Say It

Unless you work in a vacuum, you need to be able to
communicate. The more effective that communication, the
more influential you become.
Finally, there’s the matter of communicating via
documentation. Typically, developers don’t give much thought
to documentation. At best it is an unfortunate necessity; at
worst it is treated as a low-priority task in the hope that
management will forget about it at the end of the project.
Pragmatic Programmers embrace documentation as an integral
part of the overall development process. Writing documentation
can be made easier by not duplicating effort or wasting time,
and by keeping documentation close at hand—in the code itself.
In fact, we want to apply all of our pragmatic principles to
documentation as well as to code.
Tip 13

Build Documentation In, Don’t Bolt It On

It’s easy to produce good-looking documentation from the
comments in source code, and we recommend adding

comments to modules and exported functions to give other
developers a leg up when they come to use it.
However, this doesn’t mean we agree with the folks who say that
every function, data structure, type declaration, etc., needs its
own comment. This kind of mechanical comment writing
actually makes it more difficult to maintain code: now there are
two things to update when you make a change. So restrict your
non-API commenting to discussing why something is done, its
purpose and its goal. The code already shows how it is done, so
commenting on this is redundant—and is a violation of the DRY
Commenting source code gives you the perfect opportunity to
document those elusive bits of a project that can’t be
documented anywhere else: engineering trade-offs, why
decisions were made, what other alternatives were discarded,
and so on.
Know what you want to say.
Know your audience.
Choose your moment.
Choose a style.
Make it look good.
Involve your audience.
Be a listener.
Get back to people.
Keep code and documentation together.

Topic 15, Estimating
Topic 18, Power Editing
Topic 45, The Requirements Pit
Topic 49, Pragmatic Teams

Online Communication
Everything we’ve said about communicating in writing applies equally to email, social
media posts, blogs, and so on. Email in particular has evolved to the point where it is a
mainstay of corporate communications; it’s used to discuss contracts, to settle disputes,
and as evidence in court. But for some reason, people who would never send out a
shabby paper document are happy to fling nasty-looking, incoherent emails around the
Our tips are simple:
Proofread before you hit SEND .
Check your spelling and look for any accidental auto-correct mishaps.
Keep the format simple and clear.
Keep quoting to a minimum. No one likes to receive back their own 100-line
email with “I agree” tacked on.
If you’re quoting other people’s email, be sure to attribute it, and quote it inline
(rather than as an attachment). Same when quoting on social media
Don’t flame or act like a troll unless you want it to come back and haunt you
later. If you wouldn’t say it to someone’s face, don’t say it online.
Check your list of recipients before sending. It’s become a cliché to criticize
the boss over departmental email without realizing that the boss is on the cc
list. Better yet, don’t criticize the boss over email.

As countless large corporations and politicians have discovered, email and social
media posts are forever. Try to give the same attention and care to email as you would
to any written memo or report.


There are several good books that contain sections on
communications within teams, including The Mythical ManMonth: Essays on Software Engineering [Bro96] and Peopleware:
Productive Projects and Teams [DL13]. Make it a point to try to
read these over the next 18 months. In addition, Dinosaur Brains:
Dealing with All Those Impossible People at Work [BR89]
discusses the emotional baggage we all bring to the work
The next time you have to give a presentation, or write a memo
advocating some position, try working through the advice in this
section before you start. Explicitly identify the audience and what
you need to communicate. If appropriate, talk to your audience
afterward and see how accurate your assessment of their needs was.

[3] http://wiki.c2.com/?ChangeYourOrganization
[4] See, for example, a good meta-analysis at Trust and team performance: A metaanalysis of main effects, moderators, and covariates,
[5] See The police and neighborhood safety [WH82]
[6] See Contagious depression: Existence, specificity to depressed symptoms, and the role
of reassurance seeking [Joi94]
[7] While doing this, you may be comforted by the line attributed to Rear Admiral Dr. Grace
Hopper: “It’s easier to ask forgiveness than it is to get permission.’’
[8] That was supposed to be a joke!
[9] An expiring asset is something whose value diminishes over time. Examples include a
warehouse full of bananas and a ticket to a ball game.
[10] We may be biased, but there’s a fine selection available at https://pragprog.com.
[11] Never heard of any of these languages? Remember, knowledge is an expiring asset, and
so is popular technology. The list of hot new and experimental languages was very
different for the first edition, and is probably different again by the time you read this.
All the more reason to keep learning.

[12] The word annoy comes from the Old French enui, which also means “to bore.’’

Copyright © 2020 Pearson Education, Inc.

Chapter 2

A Pragmatic Approach
There are certain tips and tricks that apply at all levels of
software development, processes that are virtually universal,
and ideas that are almost axiomatic. However, these approaches
are rarely documented as such; you’ll mostly find them written
down as odd sentences in discussions of design, project
management, or coding. But for your convenience, we’ll bring
these ideas and processes together here.
The first and maybe most important topic gets to the heart of
software development: Topic 8, The Essence of Good Design.
Everything follows from this.
The next two sections, Topic 9, DRY—The Evils of Duplication
and Topic 10, Orthogonality, are closely related. The first warns
you not to duplicate knowledge throughout your systems, the
second not to split any one piece of knowledge across multiple
system components.
As the pace of change increases, it becomes harder and harder
to keep our applications relevant. In Topic 11, Reversibility,
we’ll look at some techniques that help insulate your projects
from their changing environment.

The next two sections are also related. In Topic 12, Tracer
Bullets, we talk about a style of development that allows you to
gather requirements, test designs, and implement code at the
same time. It’s the only way to keep up with the pace of modern
Topic 13, Prototypes and Post-it Notes shows you how to use
prototyping to test architectures, algorithms, interfaces, and
ideas. In the modern world, it’s critical to test ideas and get
feedback before you commit to them whole-heartedly.
As computer science slowly matures, designers are producing
increasingly higher-level languages. While the compiler that
accepts “make it so” hasn’t yet been invented, in Topic 14,
Domain Languages we present some more modest suggestions
that you can implement for yourself.
Finally, we all work in a world of limited time and resources.
You can survive these scarcities better (and keep your bosses or
clients happier) if you get good at working out how long things
will take, which we cover in Topic 15, Estimating.
Keep these fundamental principles in mind during
development, and you’ll write code that’s better, faster, and
stronger. You can even make it look easy.

Topic 8

The Essence of Good Design

The world is full of gurus and pundits, all eager to pass on their
hard-earned wisdom when it comes to How to Design Software.
There are acronyms, lists (which seem to favor five entries),
patterns, diagrams, videos, talks, and (the internet being the
internet) probably a cool series on the Law of Demeter
explained using interpretive dance.
And we, your gentle authors, are guilty of this too. But we’d like
to make amends by explaining something that only became
apparent to us fairly recently. First, the general statement:
Tip 14

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. So we believe in the
ETC principle: Easier to Change. ETC. That’s it.
As far as we can tell, every design principle out there is a special
case of ETC.
Why is decoupling good? Because by isolating concerns we
make each easier to change. ETC.
Why is the single responsibility principle useful? Because a
change in requirements is mirrored by a change in just one
module. ETC.

Why is naming important? Because good names make code
easier to read, and you have to read it to change it. ETC!
Values are things that help you make decisions: should I do this,
or that? When it comes to thinking about software, ETC is a
guide, helping you choose between paths. Just like all your
other values, it should be floating just behind your conscious
thought, subtly nudging you in the right direction.
But how do you make that happen? Our experience is that it
requires some initial conscious reinforcement. You may need to
spend a week or so deliberately asking yourself “did the thing I
just did make the overall system easier or harder to change?” Do
it when you save a file. Do it when you write a test. Do it when
you fix a bug.
There’s an implicit premise in ETC. It assumes that a person can
tell which of many paths will be easier to change in the future.
Much of the time, common sense will be correct, and you can
make an educated guess.
Sometimes, though, you won’t have a clue. That’s OK. In those
cases, we think you can do two things.
First, given that you’re not sure what form change will take, you
can always fall back on the ultimate “easy to change” path: try to
make what you write replaceable. That way, whatever happens
in the future, this chunk of code won’t be a roadblock. It seems
extreme, but actually it’s what you should be doing all the time,
anyway. It’s really just thinking about keeping code decoupled
and cohesive.

Second, treat this as a way to develop instincts. Note the
situation in your engineering day book: the choices you have,
and some guesses about change. Leave a tag in the source.
Then, later, when this code has to change, you’ll be able to look
back and give yourself feedback. It might help the next time you
reach a similar fork in the road.
The rest of the sections in this chapter have specific ideas on
design, but all are motivated by this one principle.
Topic 9, DRY—The Evils of Duplication
Topic 10, Orthogonality
Topic 11, Reversibility
Topic 14, Domain Languages
Topic 28, Decoupling
Topic 30, Transforming Programming
Topic 31, Inheritance Tax

Think about a design principle you use regularly. Is it intended to
make things easy-to-change?
Also think about languages and programming paradigms (OO, FP,
Reactive, and so on). Do any have either big positives or big
negatives when it comes to helping you write ETC code? Do any
have both?
When coding, what can you do to eliminate the negatives and
accentuate the positives?[13]

Many editors have support (either built-in or via extensions) to run
commands when you save a file. Get your editor to popup an ETC?
message every time you save[14] and use it as a cue to think about
the code you just wrote. Is it easy to change?

Topic 9

DRY—The Evils of Duplication

Giving a computer two contradictory pieces of knowledge was
Captain James T. Kirk’s preferred way of disabling a marauding
artificial intelligence. Unfortunately, the same principle can be
effective in bringing down your code.
As programmers, we collect, organize, maintain, and harness
knowledge. We document knowledge in specifications, we make
it come alive in running code, and we use it to provide the
checks needed during testing.
Unfortunately, knowledge isn’t stable. It changes—often rapidly.
Your understanding of a requirement may change following a
meeting with the client. The government changes a regulation
and some business logic gets outdated. Tests may show that the
chosen algorithm won’t work. All this instability means that we
spend a large part of our time in maintenance mode,
reorganizing and reexpressing the knowledge in our systems.
Most people assume that maintenance begins when an
application is released, that maintenance means fixing bugs and
enhancing features. We think these people are wrong.
Programmers are constantly in maintenance mode. Our
understanding changes day by day. New requirements arrive
and existing requirements evolve as we’re heads-down on the
project. Perhaps the environment changes. Whatever the
reason, maintenance is not a discrete activity, but a routine part
of the entire development process.

When we perform maintenance, we have to find and change the
representations of things—those capsules of knowledge
embedded in the application. The problem is that it’s easy to
duplicate knowledge in the specifications, processes, and
programs that we develop, and when we do so, we invite a
maintenance nightmare—one that starts well before the
application ships.
We feel that the only way to develop software reliably, and to
make our developments easier to understand and maintain, is
to follow what we call the DRY principle:
Every piece of knowledge must have a single, unambiguous,
authoritative representation within a system.
Why do we call it DRY?
Tip 15

DRY—Don’t Repeat Yourself

The alternative is to have the same thing expressed in two or
more places. If you change one, you have to remember to
change the others, or, like the alien computers, your program
will be brought to its knees by a contradiction. It isn’t a question
of whether you’ll remember: it’s a question of when you’ll
You’ll find the DRY principle popping up time and time again
throughout this book, often in contexts that have nothing to do
with coding. We feel that it is one of the most important tools in
the Pragmatic Programmer’s tool box.
In this section we’ll outline the problems of duplication and

suggest general strategies for dealing with it.
Let’s get something out of the way up-front. In the first edition
of this book we did a poor job of explaining just what we meant
by Don’t Repeat Yourself. Many people took it to refer to code
only: they thought that DRY means “don’t copy-and-paste lines
of source.”
That is part of DRY, but it’s a tiny and fairly trivial part.
DRY is about the duplication of knowledge, of intent. It’s about
expressing the same thing in two different places, possibly in
two totally different ways.
Here’s the acid test: when some single facet of the code has to
change, do you find yourself making that change in multiple
places, and in multiple different formats? Do you have to
change code and documentation, or a database schema and a
structure that holds it, or…? If so, your code isn’t DRY.
So let’s look at some typical examples of duplication.
It may be trivial, but code duplication is oh, so common. Here’s
an example:
def print_balance(account)
printf "Debits: %10.2f\n", account.debits
printf "Credits: %10.2f\n", account.credits
if account.fees < 0
printf "Fees: %10.2f-\n", -account.fees
printf "Fees: %10.2f\n", account.fees

printf "
if account.balance < 0
printf "Balance: %10.2f-\n", -account.balance
printf "Balance: %10.2f\n", account.balance

For now ignore the implication that we’re committing the
newbie mistake of storing currencies in floats. Instead see if you
can spot duplications in this code. (We can see at least three
things, but you might see more.)
What did you find? Here’s our list.
First, there’s clearly a copy-and-paste duplication of handling
the negative numbers. We can fix that by adding another
def format_amount(value)
result = sprintf("%10.2f", value.abs)
if value < 0
result + "-"
result + " "
def print_balance(account)
printf "Debits: %10.2f\n", account.debits
printf "Credits: %10.2f\n", account.credits
printf "Fees: %s\n", format_amount(account.fees)
printf "
printf "Balance: %s\n", format_amount(account.balance)

Another duplication is the repetition of the field width in all the
printf calls. We could fix this by introducing a constant and

passing it to each call, but why not just use the existing
def format_amount(value)
result = sprintf("%10.2f", value.abs)
if value < 0
result + "-"
result + " "
def print_balance(account)
printf "Debits: %s\n", format_amount(account.debits)
printf "Credits: %s\n", format_amount(account.credits)
printf "Fees: %s\n", format_amount(account.fees)
printf "
printf "Balance: %s\n", format_amount(account.balance)

Anything more? Well, what if the client asks for an extra space
between the labels and the numbers? We’d have to change five
lines. Let’s remove that duplication:
def format_amount(value)
result = sprintf("%10.2f", value.abs)
if value < 0
result + "-"
result + " "
def print_line(label, value)
printf "%-9s%s\n", label, value
def report_line(label, amount)
print_line(label + ":", format_amount(amount))

def print_balance(account)
report_line("Debits", account.debits)
report_line("Credits", account.credits)
report_line("Fees", account.fees)
report_line("Balance", account.balance)

If we have to change the formatting of amounts, we change
format_amount. If we want to change the label format, we change
There’s still an implicit DRY violation: the number of hyphens
in the separator line is related to the width of the amount field.
But it isn’t an exact match: it’s currently one character shorter,
so any trailing minus signs extend beyond the column. This is
the customer’s intent, and it’s a different intent to the actual
formatting of amounts.
Not All Code Duplication Is Knowledge Duplication

As part of your online wine ordering application you’re
capturing and validating your user’s age, along with the quantity
they’re ordering. According to the site owner, they should both
be numbers, and both greater than zero. So you code up the
def validate_age(value):
validate_type(value, :integer)
validate_min_integer(value, 0)
def validate_quantity(value):
validate_type(value, :integer)
validate_min_integer(value, 0)

During code review, the resident know-it-all bounces this code,
claiming it’s a DRY violation: both function bodies are the same.

They are wrong. The code is the same, but the knowledge they
represent is different. The two functions validate two separate
things that just happen to have the same rules. That’s a
coincidence, not a duplication.
Somehow the myth was born that you should comment all your
functions. Those who believe in this insanity then produce
something such as this:
# Calculate the fees for this account.
# * Each returned check costs $20
# * If the account is in overdraft for more than 3 days,
# charge $10 for each day
# * If the average account balance is greater that $2,000
# reduce the fees by 50%
def fees(a)
if a.returned_check_count > 0
f += 20 * a.returned_check_count
if a.overdraft_days > 3
f += 10*a.overdraft_days
if a.average_balance > 2_000
f /= 2

The intent of this function is given twice: once in the comment
and again in the code. The customer changes a fee, and we have
to update both. Given time, we can pretty much guarantee the
comment and the code will get out of step.
Ask yourself what the comment adds to the code. From our

point of view, it simply compensates for some bad naming and
layout. How about just this:
def calculate_account_fees(account)
fees = 20 * account.returned_check_count
fees += 10 * account.overdraft_days if account.overdraft_days > 3
fees /= 2
if account.average_balance > 2_000

The name says what it does, and if someone needs details,
they’re laid out in the source. That’s DRY!
DRY Violations in Data

Our data structures represent knowledge, and they can fall afoul
of the DRY principle. Let’s look at a class representing a line:
class Line {
Point start;
Point end;
double length;

At first sight, this class might appear reasonable. A line clearly
has a start and end, and will always have a length (even if it’s
zero). But we have duplication. The length is defined by the
start and end points: change one of the points and the length
changes. It’s better to make the length a calculated field:
class Line {
Point start;
Point end;
double length() { return start.distanceTo(end); }

Later on in the development process, you may choose to violate
the DRY principle for performance reasons. Frequently this
occurs when you need to cache data to avoid repeating

expensive operations. The trick is to localize the impact. The
violation is not exposed to the outside world: only the methods
within the class have to worry about keeping things straight:
class Line {
private double length;
private Point start;
private Point end;
public Line(Point start, Point end) {
this.start = start;
this.end = end;
// public
void setStart(Point p) { this.start = p; calculateLength(); }
void setEnd(Point p) { this.end = p; calculateLength(); }
Point getStart()
Point getEnd()
double getLength()

{ return start; }
{ return end; }
{ return length; }

private void calculateLength() {
this.length = start.distanceTo(end);

This example also illustrates an important issue: whenever a
module exposes a data structure, you’re coupling all the code
that uses that structure to the implementation of that module.
Where possible, always use accessor functions to read and write
the attributes of objects. It will make it easier to add
functionality in the future.
This use of accessor functions ties in with Meyer’s Uniform
Access principle, described in Object-Oriented Software
Construction [Mey97], which states that

All services offered by a module should be available through a
uniform notation, which does not betray whether they are
implemented through storage or through computation.
Your code interfaces to the outside world: other libraries via
APIs, other services via remote calls, data in external sources,
and so on. And pretty much each time you do, you introduce
some kind of DRY violation: your code has to have knowledge
that is also present in the external thing. It needs to know the
API, or the schema, or the meaning of error codes, or whatever.
The duplication here is that two things (your code and the
external entity) have to have knowledge of the representation of
their interface. Change it at one end, and the other end breaks.
This duplication is inevitable, but can be mitigated. Here are
some strategies.
Duplication Across Internal APIs

For internal APIs, look for tools that let you specify the API in
some kind of neutral format. These tools will typically generate
documentation, mock APIs, functional tests, and API clients,
the latter in a number of different languages. Ideally the tool
will store all your APIs in a central repository, allowing them to
be shared across teams.
Duplication Across External APIs

Increasingly, you’ll find that public APIs are documented
formally using something like OpenAPI.[15] This allows you to
import the API spec into your local API tools and integrate more
reliably with the service.
If you can’t find such a specification, consider creating one and

publishing it. Not only will others find it useful; you may even
get help maintaining it.
Duplication with Data Sources

Many data sources allow you to introspect on their data schema.
This can be used to remove much of the duplication between
them and your code. Rather than manually creating the code to
contain this stored data, you can generate the containers
directly from the schema. Many persistence frameworks will do
this heavy lifting for you.
There’s another option, and one we often prefer. Rather than
writing code that represents external data in a fixed structure
(an instance of a struct or class, for example), just stick it into a
key/value data structure (your language might call it a map,
hash, dictionary, or even object).
On its own this is risky: you lose a lot of the security of knowing
just what data you’re working with. So we recommend adding a
second layer to this solution: a simple table-driven validation
suite that verifies that the map you’ve created contains at least
the data you need, in the format you need it. Your API
documentation tool might be able to generate this.
Perhaps the hardest type of duplication to detect and handle
occurs between different developers on a project. Entire sets of
functionality may be inadvertently duplicated, and that
duplication could go undetected for years, leading to
maintenance problems. We heard firsthand of a U.S. state
whose governmental computer systems were surveyed for Y2K
compliance. The audit turned up more than 10,000 programs
that each contained a different version of Social Security

Number validation code.
At a high level, deal with the problem by building a strong,
tight-knit team with good communications.
However, at the module level, the problem is more insidious.
Commonly needed functionality or data that doesn’t fall into an
obvious area of responsibility can get implemented many times
We feel that the best way to deal with this is to encourage active
and frequent communication between developers.
Maybe run a daily scrum standup meeting. Set up forums (such
as Slack channels) to discuss common problems. This provides
a nonintrusive way of communicating—even across multiple
sites—while retaining a permanent history of everything said.
Appoint a team member as the project librarian, whose job is to
facilitate the exchange of knowledge. Have a central place in the
source tree where utility routines and scripts can be deposited.
And make a point of reading other people’s source code and
documentation, either informally or during code reviews. You’re
not snooping—you’re learning from them. And remember, the
access is reciprocal—don’t get twisted about other people poring
(pawing?) through your code, either.
Tip 16

Make It Easy to Reuse

What you’re trying to do is foster an environment where it’s
easier to find and reuse existing stuff than to write it yourself. If
it isn’t easy, people won’t do it. And if you fail to reuse, you risk

duplicating knowledge.
Topic 8, The Essence of Good Design
Topic 28, Decoupling
Topic 32, Configuration
Topic 38, Programming by Coincidence
Topic 40, Refactoring

Topic 10


Orthogonality is a critical concept if you want to produce
systems that are easy to design, build, test, and extend.
However, the concept of orthogonality is rarely taught directly.
Often it is an implicit feature of various other methods and
techniques you learn. This is a mistake. Once you learn to apply
the principle of orthogonality directly, you’ll notice an
immediate improvement in the quality of systems you produce.
“Orthogonality’’ is a term
borrowed from geometry. Two
lines are orthogonal if they meet at
right angles, such as the axes on a
graph. In vector terms, the two
lines are independent. As the
number 1 on the diagram moves north, it doesn’t change how
far east or west it is. The number 2 moves east, but not north or

In computing, the term has come to signify a kind of
independence or decoupling. Two or more things are orthogonal
if changes in one do not affect any of the others. In a welldesigned system, the database code will be orthogonal to the
user interface: you can change the interface without affecting
the database, and swap databases without changing the

Before we look at the benefits of orthogonal systems, let’s first
look at a system that isn’t orthogonal.
A Nonorthogonal System

You’re on a helicopter tour of the Grand Canyon when the pilot,
who made the obvious mistake of eating fish for lunch, suddenly
groans and faints. Fortunately, he left you hovering 100 feet
above the ground.
As luck would have it, you had read a Wikipedia page about
helicopters the previous night. You know that helicopters have
four basic controls. The cyclic is the stick you hold in your right
hand. Move it, and the helicopter moves in the corresponding
direction. Your left hand holds the collective pitch lever. Pull up
on this and you increase the pitch on all the blades, generating
lift. At the end of the pitch lever is the throttle. Finally you have
two foot pedals, which vary the amount of tail rotor thrust and
so help turn the helicopter.
“Easy!,” you think. “Gently lower the collective pitch lever and
you’ll descend gracefully to the ground, a hero.” However, when
you try it, you discover that life isn’t that simple. The
helicopter’s nose drops, and you start to spiral down to the left.
Suddenly you discover that you’re flying