
Tips from the Pragmatic Programmer (2000) - gasull
https://pragprog.com/the-pragmatic-programmer/extracts/tips
======
dllthomas
_" DRY—Don’t Repeat Yourself Every piece of knowledge must have a single,
unambiguous, authoritative representation within a system."_

Always good to revisit original phrasings of things. I think the catchiness of
the lower-information acronym did this one a disservice. I find myself
explaining with some regularity that repetition of code is not _necessarily_
repetition of ideas, and if I have `f(x, g(y), h(z))` both here and there _but
for different reasons_ then it's introducing artificial coupling to break it
out into a single function. The focus, in the longer expression, on
_knowledge_ is exactly right. DRY isn't a call for "Huffman coding".

~~~
InclinedPlane
I like DRY and generally I'm the sort of person who's always spinning off
chunks of code into their own functions, classes, modules, etc. and almost
always hating anywhere I have duplicated code.

That said, I think DRY can sometimes lead people astray. One problem is that
the boiled down concept of "DRY" has nothing to say about _quality_. Reusing
bad code can often be much, much worse than the alternative. Sometimes it's
critical to "sunset" code that is "working" because it's not good code, and it
would take too much to make it good. Then tie any new attempt to reuse that
functionality to an effort to create a better replacement. If instead people
think "oh hey, this exists already and it sorta works, whelp, better be DRY!"
then they can turn a small problem of bad code into a big problem of horrible
code that becomes even less maintainable and more of an effort sink as it
acquires little patches and fixes to add support to all the new stuff using
it, and as it becomes more and more indispensable and costly to replace.
Whereas if the first person deciding to be aggressively DRY had looked at the
code and instead said "this is garbage, I'm writing my own better thing" then
maybe everyone else coming along later would have ended up using the better
replacement and over time it would have become trivial to migrate the one
usage of the original to the better version.

The mental model I've started to adopt is instead one around "littering".
Basically: don't create garbage code, and don't use it. Garbage code is code
that has future cleanup inherently attached to it. Repeated code can be
garbage code because there's inherently either deduplication work or
duplication of fixing/redesign/adaptation work attached to it, it's basically
like littering in the code base. But by the same token you don't solve that
problem by finding a use for garbage, you still have future cleanup and bug
fixing work attached to the code, only now it's worse because it has different
use cases to support and higher consequences if it breaks.

~~~
rimantas
As some have put it: "duplication is preferred to the wrong abstraction".

~~~
dllthomas
I think that agrees very much with my comment, but is sort of orthogonal to
the comment above - which I think would recommend reimplementing even the
right abstraction if the existing implementation is sufficiently poor.

~~~
_asummers
One way I've always heard it referred to is: refactor the code so your task is
easy to do. If making a new abstraction does that (just had this happen last
week for me) then so be it.

~~~
dllthomas
I think that is incomplete. One should be aware of what other tasks a refactor
is making more difficult or more error prone; it is not purely a matter of
whether it makes the current task easy.

------
lliamander
> Provide Options, Don’t Make Lame Excuses

This has helped my career more than any other single piece of advice. The
critical mindset of the engineer can quickly lead to cynicism (especially when
faced with bureaucracy). Don't get me wrong; cynics make great advisors. But
the money is in solving problems, not (merely) pointing them out.

~~~
mikeash
I like to put it this way: look for solutions, not problems. Many programmers
spend their effort on figuring out why something can't work, rather than how
it could work.

------
crazypyro
I haven't found a better source of software engineering knowledge than this
book combined with _Code Complete_.

~~~
dmux
Check out Leo Brodie's "Thinking Forth"

I read both The Pragmatic Programmer and Code Complete (2ed) before Thinking
Forth. The latter provides a wonderful software engineering foundation (in
clearer, more concise language too).

------
muzzio
> Use a Single Editor Well

This seems impossible to me, although I agree that it would be an extremely
useful practice. I mainly develop Java and Swift, and both languages are
extremely dependent on using an IDE. I honestly don't see how I would ever be
able to use only a single editor across all the languages I use, even though
Jetbrains seems to be trying their hardest to make that possible.
(Unfortunately I don't think AppCode is quite there yet.)

Even using the same tools across operating systems causes issues: Using
IntelliJ on MacOS at work has entirely different keybindings than on Linux,
because MacOS doesn't monopolize the Super/Command key so heavily.

...Or is this just referring to things like having Vim bindings across all
your editors? That seems much more doable.

~~~
jimminy
In the case of Java, while the IDE systems are good, the last time I used Java
I decided to do it within an editor and use CLI scripts for building and
packaging, and enjoyed it much more than any Java IDE in past experience. It
made me feel more productive, anecdotally.

Mind you most of my prior Java experience was 2007-2010, and the last time
with the editor + CLI was in 2014, and just with a fun example. The editor +
CLI workflow was still solid and similar to Node or Python workflow in that
regard.

~~~
muzzio
How did you handle things like import statements? That's really the biggest
thing for me: if I'm working in a large project, I don't want to have to think
about what package some really obscure utility is before using it.

Losing Shift+F6 refactoring is a little annoying, but definitely not something
that makes programming Java impossible. Autocomplete might get a little hairy
as well if you're referring to classes that exist in Jar files too, or am I
wrong about this?

As for everything else, using the CLI for source control and building is
something I do anyways, even when using an IDE. At least with Gradle, that is.
As long as some of those issues have solutions, though, I think this might be
possible. Maybe I'll have look into it a bit more.

~~~
stygiansonic
Decent Java IDEs handle import statements automatically. (And can also
organize them for you)

Many people don't like Eclipse but I find the Java-oriented distribution it
pretty decent for an IDE. Auto-complete is handled well, and searching through
classes/types is also easy. (Knowing the shortcut keys helps)

As for imports, when you start typing a class name that isn't currently
imported or in scope, you can use auto-complete to select which one you want.
There may be multiple matches from multiple packages if you are searching for
a class name of `Result`, so you can select the `org.foo.someframework.Result`
and the IDE will add the import statements for you.

In general, I haven't really had much trouble with Java and an IDE, even in
large projects with a huge number of dependencies.

I haven't really tried IntelliJ but from the feedback I've heard, it's a great
IDE as well.

------
gautamdivgi
“select” Isn’t Broken

So - this one I have mixed feelings about. It is normally true. But you could
have genuinely hit upon a bug. Granted it is much easier to investigate and
prove with open source today.

14 odd years ago I was working on HP-UX & C applications. One of the signal
commands caused things to crash. I finally figured out the test that could
cause it to crash. Now HP support seemed to think I was crazy for asking me to
debug their code. I took me ages to get them to understand - that the OS was
their code and not mine.

Well, either way, they got a tier-3 OS support person involved who collected
data, confirmed the bug and provided a fix.

The point is - it may very well be a platform bug. That is code too. It just
shouldn't be your first (or may be even second or third conclusion) and you
should have a unit test to exercise the bug.

~~~
beat
When I was a fresh junior programmer (a few years before the book was
written), making my first independently designed and significant change to the
system I worked on, I tripped over a "select is broken" kind of bug -
specifically, mmap() was broken on AIX 3.2.5, in certain cases. It was weird
and wonderful, because my code worked in the test environment, but not the
production environment.

The response of the senior engineers was "What's _really_ wrong with your
code?" Ultimately, I was able to prove an OS bug with IBM, but it required
extraordinary proof.

And you know what? If some smart junior programmer came to me and said "I
think there's a bug with a low-level OS call", my response would be "What's
_really_ wrong with your code?" As it should be. Heck, if a lead engineer said
that, I'd have the same response. If _I_ said it, that would be my response to
myself.

That's because select is very rarely broken. The exceptions just prove the
rule.

~~~
retbull
I ran across a bug in the JDK when I was an intern and spent 2 weeks
documenting and demonstrating that it was in fact a bug in Java not in my
code. :D funniest thing was I got to pull an I told you so on my professor who
claimed we would NEVER run into a bug in the JDK and to just try to figure out
what we did wrong.

~~~
beat
Yep. And if an intern of yours came to you and said "I think I found a bug in
the JDK", you'd probably say "What's _really_ wrong with your code?", wouldn't
you?

~~~
ktRolster
But if you're smart, you'd ask him to show you the bug.

~~~
beat
If she thinks she found a "select is broken", she needs to write a test to
exercise the behavior, independently of our existing code base. That's how I
chased down the mmap() bug - I wrote a program that showed the bug on the prod
servers but not the test servers, and sent the C code and the executable I
compiled off to IBM for analysis. (It was a charming bug, btw... it would
randomly overwrite pages of memory with nulls, maybe 10% of the time)

------
beat
I read that book when it first came out back in 1999 or so. It was the first
"software engineering" book that actually felt sensible to my pragmatist mind.
I still quote "tracer bullets", "boiling frogs", and "select isn't broken"
liberally.

------
100k
This is one of my favorite books about software development. I read it early
in my career, and it was a big influence on me (for example, motivating me to
learn Python).

One thing I've always thought ironic is how much nicer the typography and
design is in this book, which was published by Addison-Wesley, than the books
the Pragmatic Press publishes. And don't even get me started on Pragmatic's
embarrassing covers.

~~~
ktRolster
What's wrong with their covers?
[https://pragprog.com/titles?f[sort_by]=pubdate&f[category]=a...](https://pragprog.com/titles?f\[sort_by\]=pubdate&f\[category\]=all&f\[skill_level\]=All&f\[title_contains\]=)

~~~
100k
It looks like they did a Google image search for whatever the subject of the
book is, and slap the first thing they find on the cover.

Example: The Agile Samurai
[https://imagery.pragprog.com/products/176/jtrap.jpg?12985898...](https://imagery.pragprog.com/products/176/jtrap.jpg?1298589898)

Dart 1 For Everyone is even better.
[https://imagery.pragprog.com/products/432/csdart1.jpg?140865...](https://imagery.pragprog.com/products/432/csdart1.jpg?1408653364)

------
agentgt
_" Use Tracer Bullets to Find the Target

Tracer bullets let you home in on your target by trying things and seeing how
close they land."_

All the other tips I appreciate but _embarrassingly_ I have hard time with the
analogy on this one (besides the bullet reference). I mean I think I get it
but I can't figure out how it maps to anything I have done. I would say it is
like a "software spike" [1] but somehow the analogy description doesn't fit.

Maybe someone has a real world example?

[1]:
[https://en.wikipedia.org/wiki/Spike_(software_development)](https://en.wikipedia.org/wiki/Spike_\(software_development\))

~~~
ctb_mg
I work with a customer who is notorious for not defining requirements. Their
culture is that everyone is either too busy or not knowledgeable enough of all
the working parts of a system to define requirements. It's a culture problem
over there.

The tool I work on generates reports. Rather than defining requirements for
reports, the only way to make progress is to understand their general needs
through conversation, then provide them a draft report - your best guess. They
tell you what to change or what they don't want, then you make changes and
provide another draft. When enough tracer bullets are shot, you arrive at the
report they actually need.

~~~
daheza
Aren't at this point you doing the job of two people? I have a coworker who
would say this when the requirements are well defined. He would say its our
job to build the requirements that are given to us. Our job is not to create /
define a product. He would often follow this up by saying our company is worth
X Billions of dollars, they can afford to hire a Business Analyst/ Better
Product Manager.

Personally I don't agree with this. It goes against my core beliefs to make
something that I don't believe is good for the end user. I have a hard time
however coming up with arguments on why we should as a developer spend our
time creating basically a product plan.

~~~
jerven
I understand how you feel. You are being hired to solve problems, and figuring
out what to solve is a key part of the job. Solving problems is your aim,
writing code is only helpful if it solves the problem. I love the days where I
get into the office someone ask me streamline something, and all that really
is required is a whiteboard, some pens and no code ever. Solving the urgent
business issue at a cost of 30 minutes talking and 5 dollars of pens ;)

Hiding developers behind analysts and product managers makes everyones job
less fun.

In my first job we had analysts, product managers, user councils making
specifications. Specifications that where terrible and the developers in the
team would have loved to do this iterative design with the end users, because
the software would have been better fit for use. For me that was a soul
sucking experience. Much better to be able to understand why the software
needs to exist and how to make it good for users and the organisation (not
always 1:1 mapping either)

Wanting perfect specs is a good way to limit your career as a developer.
Because that way you will never be more than a glorified type writer with a
analyst to hold your hand. Solving the whole business problem from start to
end is the way to grow professionally.

Also perfect specs are impossible :( so iterating with your users is the fast
way to good enough for business applications.

If you want perfect specs write sudoko solvers...

------
bluetidepro
Great round-up of tips from the book! A co-founder ( _was also CTO_ ) of a
startup I used to work for recommended I read this book while I was still
developing my skills, and I cannot thank him enough. This book changed the way
I approached programming problems, and was an incredible influence on me. I
wish I had read it sooner in my career. I now always recommend it to any
developer still getting started, or even to senior developers who haven't read
the book yet. I have nothing but great things to say about this book!

------
zeveb
Wow, I can't believe The Pragmatic Programmer dates back to 1999 — seems like
I read it just yesterday!

~~~
beat
It's a timeless book. I read it and Kent Beck's _Extreme Programming
Explained_ at around the same time, and they completely changed my way of
thinking about software development. The only other book that shook my
foundations so hard was the classic K&R _The C Programming Language_.

------
rudedogg
This is one of the few programming books I've read from front to back. It's
full of so much good stuff, I've been meaning to read through it again.

Can anyone comment whether Programming Pearls is as good?

~~~
zphds
It definitely complements TPP. For me, Pragmatic Programmer was a better bed
time book.

------
clock_tower
That page has some impressive reverse-adblocking. I was somehow redirected to
a no-Javascript page despite having all Javascript from the site blocked
(including pragprog.com), and it looks like they only show content if you
specifically enable their advertising servers.

I don't know if adwalling is a term or not (analogous to paywalling), but
here's what's probably the same content without Javascript and ads:

[http://www.ccs.neu.edu/home/lieber/courses/csg110/sp08/Pragm...](http://www.ccs.neu.edu/home/lieber/courses/csg110/sp08/Pragmatic%20Quick%20Reference.htm)

~~~
gvb
It is very simple and very annoying:

    
    
          <noscript>
            <meta http-equiv="refresh" content="2;url=https://pragprog.com/no_js">
          </noscript>
    

Disabling autorefresh on Firefox: [http://lifehacker.com/5321420/disable-
automatic-web-page-ref...](http://lifehacker.com/5321420/disable-automatic-
web-page-refreshing)

