
Ask HN: What habits make a programmer great? - zachng
A quote by Kent Beck:
I&#x27;m not a great programmer; I&#x27;m just a good programmer with great habits.<p>So what are the habits I should cultivate to be a great programmer or even a good one?
What are the bad habits that I should drop?
======
perlgeek
The "developer on fire" podcast closes out each episode by asking the guest to
provide three tips for delivering more value.

Some that occur frequently are:

* Take care of yourself. Get enough sleep, exercise and healthy food. Have hobbies.

* Constantly learn new stuff

* Practice communication skills. Building stuff fast and well doesn't help if you're building the wrong thing, and you need communication skills to prevent that

* Think about the context that your program will run in (related to the reason above)

* Practice empathy

~~~
grub5000
> * Practice empathy

Any tips on how to do this? I don't often feel things for myself and it's even
rarer to experience empathy at a level I can detect. I meditate to try to
better understand and learn to detect my feelings, but haven't made much
progress yet (I use Headspace).

~~~
skytreader
Read (good) fiction.

Backed by science! [https://www.scientificamerican.com/article/novel-finding-
rea...](https://www.scientificamerican.com/article/novel-finding-reading-
literary-fiction-improves-empathy/)
[https://www.theguardian.com/books/booksblog/2013/oct/08/lite...](https://www.theguardian.com/books/booksblog/2013/oct/08/literary-
fiction-improves-empathy-study) [https://www.washingtonpost.com/news/speaking-
of-science/wp/2...](https://www.washingtonpost.com/news/speaking-of-
science/wp/2016/07/22/does-reading-fiction-make-you-a-better-person/)
[https://www.psychologytoday.com/blog/the-athletes-
way/201412...](https://www.psychologytoday.com/blog/the-athletes-
way/201412/can-reading-fictional-story-make-you-more-empathetic)

I've been confronted with this question a couple of times even before I read
the articles linked above and I always answered the same. Always felt like
it's such an "obvious" answer since reading fiction puts you in the
perspective of another person/character, so it's good empathy exercise. My
__personal __experience confirms this as well, that when I want to shift my
perspective to that of another, reading fiction helps.

(Emphasis on "personal" as, in this use case, YMMV.)

~~~
Taylor_OD
On this note... the books I've found most interesting over the last couple
years are ones that expand my mind to a viewpoint or a perspective of another
people group that is different than my own.

Two very different books but, Between the World and Me, and How to Get Filthy
Rich in Rising Asia both made me think in ways I cant quite describe.

------
ankurdhama
Focus on the problem and not the tools ceremony around it. Don't follow the
herd and the hype. When given a problem, keep drilling the problem until it is
absolutely clear to you and then only work on solution.

~~~
mdular
This.

I often encounter situations where a day or two were spent creating a mess of
classes and abstractions, yet the actual logic to solve the problem still
hasn't materialised. A defense about "code quality" or "not wanting to write
spaghetti code" is often made.

My recommendations for a problem you don't have a clear solution in mind for:

1) Hack some pseudo-code spaghetti together in a blank file until you think
"you got it"

2) Write some theoretical test scenarios in another blank file (given state,
steps, outcome) to verify that it's actually "solved". Discuss with a team
member if possible.

3) then write out those functions from 1) inside the existing codebase

4) verify stuff is working

5) only then do abstractions / splitting up into multiple files

For a problem where the solution is already existing, but the implementation
lacking (e.g. a refactoring)

1) design the new code (data structures, interfaces)

2) always propose to the team - no ninja-architecture/refactors

3) ensure the solution can be tested, document what should be tested

4) execute on the implementation

YMMV

~~~
pricechild
Suggesting that is all well and good, but surely the concern is that the
process will inevitably end after 4), or even 1) since "it works" and there
are other higher priorities?

~~~
Fradow
That's a communication problem, I think. You should outline that something
working is a prototype, not an end-product. That means it's not maintainable,
hard to extend etc...

To convert from a prototype to an end-product, you need to do the other steps.

------
henrik_w
A few habits I've found that work well for me:

1\. Start small, then extend.

2\. Change one thing at a time.

3\. Add logging and error handling early.

4\. All new lines must be executed at least once.

5\. Test the parts before the whole.

6\. Fix the known errors, then see what’s left.

Taken from here: [https://henrikwarne.com/2015/04/16/lessons-learned-in-
softwa...](https://henrikwarne.com/2015/04/16/lessons-learned-in-software-
development/)

~~~
majewsky
> All new lines must be executed at leaat once.

What if you write a function in Go that's littered with the usual

    
    
      if err != nil {
        return err
      }
    

and the error that's being propagated is hard to reproduce, e.g. a filesystem
error? I never cover those "return err" in actual programs.

~~~
henrik_w
I sometimes temporarily modify the program by for example misspelling a file
name of a data base column name just to provoke an error that will execute the
error handling code. Or changing a condition from == to != to cause an
exception. Not ideal, but at least the new code is executed at least once, so
I see that it executes as expected.

Creating tests for some of these cases would involve mocking things out, and
then you have to make assumptions that may not hold anyway. That's why I like
to see it execute in the real environment at least once.

~~~
vram22
>I sometimes temporarily modify the program by for example misspelling a file
name of a data base column name just to provoke an error that will execute the
error handling code.

Yes, a lot of things like that are possible. I remember in one client-server
project I worked on, we unplugged the network cable from one PC (while the
program was communicating between client and server), to see if we got the
correct error message that we had written for that case. And did other stuff
like that.

~~~
vram22
To continue the anecdote:

This was done in a project I handled, for the World Bank. I had a team of 9
motivated though young developers (first project for most of them). Near the
end, before we sent the software to the client, a colleague was assigned to
test the software - testing by a member external to the team, a slightly
senior guy, ex-CITIL (a Citi IT subsidiary which had more mature software
processes than we did then), though of course we did test the software
ourselves a lot, first. I remember what happened:

We prepared the machines and software for the test. Called him over.

He said: I am going to sit down and destroy your software.

We said: Go ahead, please try.

And he tried to. But could not. He only found a few minor cosmetic defects.

Getting up after a few hours of rigorous testing, he said something like - I
am happy with your work.

------
photonios
\- Add value. Train yourself to only do things that add value. Value is
loosely defined. It can be going the extra mile smashing that bug that
everybody is complaining about. It can be whipping up a mind blowing demo to
pull in that big customer. Nobody cares if you work 80 hours a week, but it's
not adding any value. Get in the habit of working on things that bring value
to others.

\- More communicating, less coding. This is extremely important in teams and
large organisations. Communicate to make sure nobody does double work.
Communicate to have your ideas and opinions heard. Communicate to avoid doing
pointless work. The list goes on. Communicate with your peers, your boss, your
customers.

\- Have healthy habits. Eat well, sleep well, exercise. When you're young you
can pull off all nighters and eating pizza's all week. As you get older, you
cannot.

\- Be reliable. When you say you're going to do something, do it. Write
reliable, well-tested code that works.

\- Fail. Make mistakes. And learn from them. Don't be afraid to take on a
challenge. You cannot expect to be great without having made mistakes. You'll
make them once and hopefully never again.

\- Follow up. When people send you e-mails and messages. Answer as fast as you
can. Things move a whole lot more quickly when people don't wait on each
other.

\- Be on time. Nobody likes people who are late.

\- Always learn. Try new things. If you don't like them, then at least you
tried and learned something new. Keep exploring and reading.

~~~
psynapse
+1 for value. Unless you are a sales channel, every job can be generalised to
creating value.

"Value is loosely defined"

This is a really worthwhile thing to think about - not only creating value,
but levering it up.

If you spend the time to work/find something out, demonstrate it to others. If
you change someone else's code for the better, explain why.

Minimise the cost of organisational communication - operate transparently.
Pro-actively communicate your status/progress and respond quickly and clearly
to requests for such.

Boost others. Communicate success upward in terms of the team - even if you
did it.

------
nostrademons
Meta-habit: learn to adopt different habits for different situations. With
that in mind, some techniques I've found useful for various situations:

"Researchey" green-field development for data-science-like problems:

1\. If it can be done manually first, do it manually. You'll gain an intuition
for how you might approach it.

2\. Collect examples. Start with a spreadsheet of data that highlights the
data you have available.

3\. Make it work for one case before you make it work for all cases.

4\. Build debugging output into your algorithm itself. You should be able to
dump the intermediate results of each step and inspect them manually with a
text editor or web browser.

5\. Don't bother with unit tests - they're useless until you can define what
correct behavior is, and when you're doing this sort of programming, by
definition you can't.

Maintenance programming for a large, unfamiliar codebase:

1\. Take a look at filesizes. The biggest files usually contain the meat of
the program, or at least a dispatcher that points to the meat of the program.
main.cc is usually tiny and useless for finding your way around.

2\. Single-step through the program with a debugger, starting at the main
dispatch loop. You'll learn a lot about control flow.

3\. Look for data structures, particularly ones that are passed into many
functions as parameters. Most programs have a small set of key data
structures; find them and orienting yourself to the rest becomes much easier.

4\. Write unit tests. They're the best way to confirm that your understanding
of the code is actually how the code works.

5\. Remove code and see what breaks. (Don't check it in though!)

Performance work:

0\. Don't, unless you've built it and it's too slow for users. Have
performance targets for how much you need to improve, and stop when you hit
them.

1\. Before all else (even profiling!), build a set of benchmarks representing
typical real-world use. Don't let your performance regress unless you're
_very_ certain you're stuck at a local maxima and there's a better global
solution just around the corner. (And if that's the case, tag your branch in
the VCS so you can back out your changes if you're wrong.)

2\. Many performance bottlenecks are at the intersection between systems.
Collect timing stats in any RPC framework, and have some way of propagating &
visualizing the time spent for a request to make its way through each server,
as well as which parts of the request happen in parallel and where the
critical path is.

3\. Profile.

4\. Oftentimes you can get big initial wins by avoiding unnecessary work.
Cache your biggest computations, and lazily evaluate things that are usually
not needed.

5\. Don't ignore constant factors. Sometimes an algorithm with asymptotically
worse performance will perform better in practice because it has much better
cache locality. You can identify opportunities for this in the functions that
are called a lot.

6\. When you've got a flat profile, there are often still very significant
gains that can be obtained through changing your data structures. Pay
attention to memory use; often shrinking memory requirements speeds up the
system significantly through less cache pressure. Pay attention to locality,
and put commonly-used data together. If your language allows it (shame on you,
Java), eliminate pointer-chasing in favor of value containment.

General code hygiene:

1\. Don't build speculatively. Make sure there's a customer for every feature
you put in.

2\. Control your dependencies carefully. That library you pulled in for one
utility function may have helped you save an hour implementing the utility
function, but it adds many more places where things can break - deployment,
versioning, security, logging, unexpected process deaths.

3\. When developing for yourself or a small team, let problems accumulate and
fix them all at once (or throw out the codebase and start anew). When
developing for a large team, never let problems accumulate; the codebase
should always be in a state where a new developer could look at it and say "I
know what this does and how to change it." This is a consequence of the
reader:writer ratio - startup code is written a lot more than it is read and
so readability matters little, but mature code is read much more than it is
written. (Switching to the latter culture when you need to develop like the
former to get users & funding & stay alive is left as an exercise for the
reader.)

~~~
Stratoscope
> _Take a look at filesizes. The biggest files usually contain the meat of the
> program, or at least a dispatcher that points to the meat of the program.
> main.cc is usually tiny and useless for finding your way around._

This is my #1 pet peeve with GitHub. When I first look at an unfamiliar repo,
I want to get a sense of what the code is about and what it looks like. The
way I do that with a local project is by looking at the largest files first.
But GitHub loves their clean uncluttered interface so much, they won't show me
the file sizes!

~~~
arocks
[https://chrome.google.com/webstore/detail/github-
repository-...](https://chrome.google.com/webstore/detail/github-repository-
size/apnjnioapinblneaedefcnopcjepgkci)

I think this Chrome extension called "GitHub Repository Size" might be exactly
what you are looking for

~~~
Stratoscope
Nice, thanks!

------
brian-armstrong
Study the idioms of whatever language you are using. If you're writing
production code, consistency is everything. Don't write anything surprising or
clever - you'll just paint yourself into a corner later, and it'll be
impossible to maintain. Boring code is good code.

Take error handling really seriously. A program that can gracefully reject
input with a detailed error message is far better than one that crashes
mysteriously

~~~
sgift
Please, everyone who thinks, "I just expect correct inputs" take note of part
two. I've had so many discussions with colleagues about that "Why don't you
check for null pointers and give an error message?" "I think it's perfectly
fine to just crash with a null pointer, I don't expect null pointers."

That attitude hurts everyone who has to support what you write.

edit: Reformatted as a habit "Make sure whatever you write can be supported
without unnecessary headaches."

~~~
nostrademons
Only if a.) you can do something to recover from the null pointer or b.) you
can provide more information about its cause than you could recover from an
ordinary stack trace. Otherwise you're just adding code without changing the
ultimate result of the NPE: a debugging session.

Assertions, however, are great. If you can force the program to throw that NPE
closer to the point where it actually illegitimately became null, the
debugging session becomes much shorter. Null-safety in the type system (like
with most modern languages: Swift, Haskell, Kotlin, Scala, Rust, etc.) is even
better.

~~~
brlewis
This! I especially see this problem in Java, where IDEs always suggest
catching an exception. Like a dog chasing cars, you really should think
through what you're going to do when you catch one. I've wasted a lot of time
debugging problems that get masked over by try/catch only to pop up at some
later point in a seemingly unrelated part of the code.

------
klibertp
One of the most important things, in my opinion, is being able to admit that
you don't know or don't understand something. The opposite attitude gets in
the way of learning new things, which is really bad for programmers.

~~~
Bdiem
This exactly, but let me add: Develop an urge to understand things. One needs
to understand the whole system environment just to be able to make good
choices.

To give "urge" more meaning: These days I get a noticeable weird feeling in my
gut if I'm working in a environment where there are too many unknowns.

~~~
grub5000
>I get a noticeable weird feeling in my gut if I'm working in a environment
where there are too many unknowns.

That's fear for me. Always a chance I'll knock something important over...

------
zabana
The most valuable habit I've developed IMO is reinventing the wheel. When you
face a new challenge with new concepts you're unfamiliar with, the best way to
get a good grasp of the environment/tools/techniques is to rebuild it (them)
from scratch. Example: I was spending a lot of time interacting with external
REST API's (foursquare, twitter and other services) but never really
understood the inner workings, so I just decided to build my own RESTful API
for fun. It doesn't really help anybody but now I know what the request /
response cycle is and how it works, how to pass headers, what they're used
for, the actual meaning of response codes etc.

Oh and also, NEVER make any assumptions about how people will use your
software

~~~
opportune
I think it's important to distinguish reinventing the wheel for practice or
understanding, and reinventing the wheel out of stubbornness or "not built
here". The first is important because, as you said, it really helps you
understand some things that might be rather opaque initially. I didn't
understand backpropagation until I implemented it myself.

But what you don't want to do is reinvent the wheel just because you can.
Don't write your own crypto, and use whatever FOSS software (with a license
approved by your employer) and existing solutions that you can, unless you
really need a feature that they don't have. Programming is awesome in part
because we can build solutions on top of other pre-exsting solutions; it's
2017 and I can code Python in a web browser with interspersed markdown.

------
inDigiNeous
Hard to say any definite habits that work for everyone, as each person is so
different, but just for the fun of it, I'll try to list habits that work for
me:

* Keep a diary. Write out problems and solution propositions first, if the solution is not trivial.

* Keep your mind clean, always finish what you started, so you can have completion and not clutter your thought process. This means not leaving code in a state of disarray, should compile when returned back to

* Let go. If the solution does not propose itself, take a break. Sleep over it. The solution will come, with time, not by bruteforcing of overdosing caffeine. Sometimes these work too, but as a habit, better to focus on long term goals than short term successes.

* KEEP IT SIMPLE. KISS! When solution starts to look too complex, it probably is. Break it down, simplify, line by line, so that the code is understandable and easy to read. Write for humans to read, not for machines to parse.

* There is no ready made solution. Accept the fact that to get results, work must be done and days and even weeks might go before getting there.

* It's ok to write code that is not "smart", that is not "perfect", that just freaking works right now as should and expected. It's just code, and in the end it all transforms into zeros and ones. Implement new features gradually towards more flexible and standardized solutions, first find a solution for the problem at hand and remember KISS again.

Some of the main points that come to mind. Especially the point of KISS, is so
easy to go overboard with, starting to overthink all kinds of fancy structs,
class inherintance models, whatever fancy code-beauty around a solution that
could be solved with a simple function and evolved later if needed to
something more flexible.

This KISS also applies to general software design, user interfaces etc also,
probably the most useful habit is to remember when thinking about systems,
keep it simple! It should also be fun to write at least in some level, if it
feels like crap, don't do it for your own sake.

~~~
noway421
One way I started to look at KISS is that there are so many ways for software
to be complex on higher architectural level, that there is absolutely no
reason to make your life harder and go for implementing complex solutions on
low level. Get it to a point where it's simple, the complexity will come
later.

------
itamarst
Assume there's always a better, faster solution to the problem than the one
you've come up with. Finding it will require deeply understanding the problem,
and sometimes redefining the problem.

Put another way, working long hours is a bad habit because you end up solving
problems the brute force way instead of figuring out how to come up with
better solutions.

I think of this aiming towards becoming a 0.1× programmer: achieving same or
better results with 1/10th the lines of code and effort. More here:
[https://codewithoutrules.com/2016/08/25/the-01x-programmer/](https://codewithoutrules.com/2016/08/25/the-01x-programmer/)

------
lj3
1\. Embrace the grind. Motivation comes and goes, but the grind remains. This
doesn't mean working all day every day, but rather setting aside specific
blocks of time and doing the same thing every single day. Workouts should
happen at the same time every day. Work should happen at the same time every
day. Each of these things should be daily habits and doing them at the same
time every day helps them become habits.

2\. Avoid flow[0]. It's tempting, seducing and addicting, but you don't learn
anything when you're in a state of flow. Anything sufficiently hard as to
improve your skills should leave you feeling a little frustrated. Get used to
that feeling.

3\. Drop TV, Porn, news, music and video games. These things all give you
rewards without having to do any work. In doing so, they steal your motivation
and energy.

4\. Stop eating sugar. If you want to get things done, strive for a steady
blood sugar level. It's hard to work when your blood sugar drops and you fall
asleep at your desk.

5\. Sleep during the hours of 10pm and 2am[1]. That's when your body makes
most of the hormones you need every day.

6\. Do the opposite of this video: 7 ways to maximize misery by CGP Grey:
[https://www.youtube.com/watch?v=LO1mTELoj6o](https://www.youtube.com/watch?v=LO1mTELoj6o)

[0]: [http://calnewport.com/blog/2011/12/23/flow-is-the-opiate-
of-...](http://calnewport.com/blog/2011/12/23/flow-is-the-opiate-of-the-
medicore-advice-on-getting-better-from-an-accomplished-piano-player/)

[1]: [http://www.anitarossiter.com.au/blog/early-nights-are-in-
ord...](http://www.anitarossiter.com.au/blog/early-nights-are-in-order)

~~~
kennydude
> Drop TV, Porn, news, music and video games.

No fun allowed then?

~~~
lj3
Active things. Go for a hike, play frisbee, walk the dog, play piano or guitar
or whatever floats your boat. The whole point is to work for your rewards
instead of getting them instantly at the push of a button.

------
mhomde
One habit that I think is important, and often overlooked, is to be able to
break out of a mindset and questioning yourself with:

"Am I solving the problem at the correct level, using the appropriate
method/technique/tool? Don't forget the big picture"

It's easy to just keep coding and add to existing code, architecture and
methods. But sometimes the frog is starting to boil. Better then to re-
evaluate whether to do some major refactoring, or add some layer of
abstraction to keep it maintainable.

Sometimes you need to recognize that you're merely treating symptoms rather
than a underlying problem. Sometimes you need to recognize that there are some
library/tool/algorithm etc that can eliminate the need to solve a problem
yourself.

------
bencollier49
"Don't surprise me". The best code doesn't make you double-take when you're
reading it.

~~~
cwilkes
Thanks for making that so succinct. I can't count the number of times I've run
into code like that. I used to have scorn for devs that handed code over like
that but I've since turned around to thinking that this is mostly due to time
crunches. Maybe something worked and then it didn't so they hacked in
something and moved on. Also I have the benefit of seeing this for the first
time and not glossing over it with a mental "oh yeah that junk, let me get to
the next issue" So my advice would be like the scouting / camping / hiking
saying of leave it better than you found it.

------
DrNuke
From my 25+ years experience, the main quality for being called great is
getting sh*t done. It is never easy because of distorted but still very human
mental (tinkering, overthinking, underthinking), physical (laziness, low
morale, disorders) and relational (team dynamics, managers, politics) habits.

------
DanielBMarkham
1\. Don't "give up" when trying something new and cut-and-paste and thrash
around blindly sticking things places. It takes just as long to learn why
things work the way they do as it does to slash and burn -- and you'll pick up
something useful along the way

2\. Check your ego at the door. A good friend begins a class he teaches having
coders say "I'm a programmer and I make mistakes"

3\. I've seen a lot of simple systems that did useful things that grew into
complex systems. I've never seen a system that started off complex being
anything but a huge PITA for everybody involved. Keep It Simple, Stupid

4\. Learn all the major programming paradigms and be able to solve problems in
all of them. In my opinion, this is the first step to being any kind of
programmer at all, much less a great one

5\. We write code to help people. We write code alongside other people. People
are a critical component, yet we hardly talk about them. Programming is about
95% social, 5% technical. But reading the latest industry news, you'd never
think that. Keep your focus on the people, not the tech. Knowing and
manipulating the tech is how you get in the game. How your work impacts real
people is how you master it. You should be a professional and write clean
code, but nobody cares about your standards if you're not getting along with
others or making something somebody actually wants

6\. Study mistakes and disasters. In every true professional field, folks
spend a lot of time picking over and thinking about things when they go wrong.
You should do the same. A big part of success is simple failure avoidance

7\. Pair/mob program and use TDD if you're deep in OO or complex/mutable code.
Nothing shows you how much you still have to learn like making what looks like
a simple change and watching dozens of tests go red

8\. Keep learning more about text processing and command line utilities. There
are a ton of people right now writing complex code for things that can be done
in a few lines of shell scripting. Don't try to solve everything in the shell,
but know that a little bit of code can replace a ton of work if you know what
you're doing.

9\. Pick 2 or 3 IDE shortcuts and practice them each week. The less you touch
your mouse and the more you can do work without moving your hands the faster
you'll be. (This is one I need to work on)

10\. Hang out with people that are better than you and pay attention.
Greatness tends to rub off over time.

~~~
tome
> 3\. I've seen a lot of simple systems that did useful things that grew into
> complex systems. I've never seen a system that started off complex being
> anything but a huge PITA for everybody involved. Keep It Simple, Stupid

Seems to be Gall's law:

[https://en.wikipedia.org/wiki/John_Gall_(author)#Gall.27s_la...](https://en.wikipedia.org/wiki/John_Gall_\(author\)#Gall.27s_law)

------
dep_b
Refactoring is like the Fight Club. Never talk about Refactoring. Instead do
it all the time while implementing new features instead of saving it up until
the building falls apart.

------
brad0
Understand the tools and languages you use day to day inside and out.

If you know how these things work internally you'll be 3x better than most
programmers.

Fail as much as possible in an environment that is okay with failure. My
environments have been side projects at home and professional work as well.
Make sure you know why it failed and what you can do better next time.

------
ryandrake
1\. Make it compile

2\. Make it run

3\. Make it work

4\. Make it robust - Correct the errors

5\. Make it failsafe - Handle the edge cases (out of memory, disk full)

6\. Make it fast

7\. Make it small

8\. Make it clean (warnings, lint, beautify/style, clean up dead/commented
code, in other words, polish the back of the cabinet)

I've met programmers in school who stop at #1 or #2. Most programming jobs get
bogged down endlessly trying to get through the #4 backlog until the deadline
comes along and they have to ship. Most developers, when asked to provide an
effort estimate for a particular task only budget for #1, #2, and #3 (and with
experience will learn to account for #4).

------
agumonkey
Being "meta", not a in pompous manner, but in a attack all dimensions with
simple automation.

See videos like Gary Bernhardt - The Unix Chainsaw on how he gathers very nice
data on just about anything in his system with a few pipes. It's easy to try
to be awesome in OOP, or in javascript but waste time and energy clicking
around or digging manually in repos for information.

I find that is the nicest and most efficient advice I ever took.

The other habit is: improving your maths skills (sophisticated combinatorics,
probabilities, statistics) ..

------
waivek
This article sheds some light on John Carmack's workflow:

[http://bookofhook.blogspot.in/2013/03/smart-guy-
productivity...](http://bookofhook.blogspot.in/2013/03/smart-guy-productivity-
pitfalls.html)

~~~
Fifer82
Having just read Masters of Doom, he doesn't give nearly enough credit to diet
soda! For me though, I don't feel John Carmack is the kind of guy to hold up
like simba to the morning rays. He did his best programming when there wasn't
people going on about agile and test driven development and all of the stuff
that leeches away at creativity and fun.

~~~
swah
Its interesting to see a game programmer working, and luckily with Youtube and
Twitch, its quite easy to do so nowadays:
[https://handmadehero.org/](https://handmadehero.org/),
twitter.com/jonathan_blow,
[https://twitter.com/nothingsand](https://twitter.com/nothingsand) so many
others.

They are very concerned about compile times and having a short
edit/compile/run cycle.

------
chroem-
Laziness, impatience, and hubris.

[http://threevirtues.com/](http://threevirtues.com/)

------
newscracker
Logic and logical thinking - this is the fundamental quality. Thinking,
analyzing, contemplating and wondering.

Attention to detail everywhere - be it code or design or documentation.

Communication skills - if one cannot communicate ideas, break them down and
simplify them to oneself and others, the work will not really deliver a lot of
value over time.

Curiosity to learn more and delve deeper to understand how things work (at a
lower level).

Be lazy and optimize - optimize things, avoid repetitive work by building
tools and tools that use tools.

"Limited resource" thinking - you may have 16GB RAM, a 4TB drive and a 100Mbps
Internet connection, but your users may not. As much as possible, try to
minimize things - the size of your program, the amount of data you store, the
amount of data you transfer over the network, etc. It might sound silly, but
this never goes out of fashion. It just comes back around once every few
decades as we invent new devices and ecosystems with different constraints.

------
faizmokhtar
Another quote by Kent Beck that I value it highly and practised is "Make it
work, make it right, make it fast".

-

I'm not a great programmer myself but some of the habits I've developed and
found effective are:

1\. to start exercising.

I started running and going to the gym early last year and managed to make it
part of my weekly routines now. I feel like I can focus on doing programming
tasks much longer now. Oh, and it also helps me in term of accomplishing my
short-term goals.

2\. to always carry a book

Always be learning. Be it a medium articles, fiction or non-fictions, etc, it
doesn't matter. As long as I am constantly learning new stuff, it's fine. It
also help keep my ego in check since there are so much unknown I've yet to
learn.

3\. to stop whenever I'm feeling tired

I take a break from codes every now and then. Sometimes a few days or weeks.
This allows me to avoid burnout which I've experienced once in the past.

------
Clubber
Pro/Con list everything. Don't read something as a best practice and take it
as gospel. If best practices were really best practices, there wouldn't always
be new best practices. When you pro/con it, you understand why.

It's not that everyone is full of beans, but what works for their environment
doesn't necessarily work for yours. The best shoe size is 10 wide. I know,
I've been wearing them for over 20 years.

Also test your assumptions. It's super simple to determine if doing it this
way is faster/slower better/worse than doing it that way. Write a short script
/ console app prototype and put timers on it. It's much faster than arguing
endlessly with someone over it. Collect some metrics.

------
patatino
Help the customer on their way to realize what product they want. Don't assume
they have it laid out for you. It's a process for both of you, most of the
time they do not know exactly what they want at the start.

------
john_moscow
Spend at least as much time evangelizing what you have developed and promoting
it to others as you spent developing it. Otherwise even the best code will
risk ending up in a trash can.

~~~
hueving
This is risky. You can end up investing your time into promoting a turd rather
than spending it on writing something better. If your tool isn't obviously
useful to the target audience, it needs a UX or documentation improvement at a
minimum.

------
mattlondon
A bad habit of mine is jumping into a problem and trying to get a final &
complete solution first time.

This means that I often get bogged down in the finer details and corner-cases
before even the most significant functionality is complete because I am trying
to deliver a gold-plated, perfect, thought-of-everything solution the first
time.

I've found time and time again that it really helps to take a step back,
_acknowledge to yourself and /or others_ that there will be TODOs, and start
building up the core functionality piece-by-piece starting from the
fundamentals and working your way up to the details & corner-cases.

That might mean you play around with a few approaches for an hour, pick one
and then commit once, or it might mean that you go through many refactorings
and commits over a period of days or weeks.

Whatever approach you take, I've found the feel-good factor/reassurance of
having working-code but with known TODOs really helps keep me going and avoids
me getting irritated/burnt-out fighting with problems before I've got
_anything_ working.

It is not going to be perfect first time, but "mighty oaks from little acorns
grow" as they say.

tl;dr - get the fundamentals working first, refactor later to handle the edge-
cases or make it sophisticated/elegant.

------
jimiray
3 pieces of advice that have helped me.

1\. RTFM, I was told this for about every question I had as a beginner, and
had to prove that I at least attempted a solution. This was before Q&A sites
like we have now. 2\. Learn to create head space, be that meditation, yoga,
going for a walk, whatever it is for you. Find it and use it to your
advantage. 3\. Expand your consciousness - Understand you are not the center
of the universe, how every you choose to get there.

------
Spearchucker
I've been doing this for 29 years, and I've learnt two useful things. The
first is that anything you don't know can be learnt, and if this is your
career, probably will be learnt.

The second is that the hardest won skill is getting things done. Whether you
hate doing them, have done the thing 1M times before, are bored, or otherwise
lack motivation. Applying yourself - _really_ applying yourself only becomes
possible when you have a reason to.

------
overgard
They learn their tools really well. I can't tell you how many good
professional programmers I know that are utterly handicapped in their speed
because they navigate the code base in an inefficient way, can't rename things
quickly, can't catch something with the debugger, etc. Once a lot of those
inefficiencys are gone it makes more mental room to think about the problem
without distractions.

------
exabrial
Empathetic coding rather than "show off" coding. Basically rather than trying
to impress the next person with the least amount of lines you can write with
the most ridiculous variable names, use consistent formatting spacing naming
logging and comments to explain your decision process.

Always remember code does not capture the decision process it only captures
the outcome.

------
hultner
Two core thoughts that have lead me throughout my professional career is:

How does what I do benefit the customer? What happens with this if I die
tomorrow?

You can code the most elegant, clever and beautiful code in your pet projects
but in a professional setting major importance lies in delivering values to
the customer and writing code which can be handed over to be maintained by
your successor.

------
krosaen
There are so many frameworks, tools and layers of abstraction out there that I
find it helps to dip down a layer and taste what life is like without
framework or tool X. Ideally, it's quite painful and you immediately
appreciate what the tool is getting for you. You also might learn that the
tool would be very helpful for circumstances you do not currently face (e.g
large scale software engineering when you are exploring via a side project),
and hang out in the lower layer until further motivated to climb back up.

Some concrete examples:

\- you are using THREE.js. Try out raw webgl to draw a square. Run frighted
back to THREE.js' arms and have some appreciation for what it is doing for you

\- you are new to web development. Try working with the DOM directly. Then try
something like knockout or angular that helps track dependencies between your
view model and the dom. Then try out React. React has achieved wide-spread
acceptance for a reason, I think it's the best pattern. But it's also the most
abstract from the reality of what's happening underneath the hood, so taking
steps up to the top can really help

\- you are playing with scikit-learn and throwing various models at a
classification problem. try implementing basic logistic regression using only
numpy arrays. Try to understand how you could adapt your implementation `fit`,
`transform` and `predict` interface used by sklearn.

A couple of recent articles that show this habit in practice:

[https://zapier.com/engineering/how-to-build-
redux/](https://zapier.com/engineering/how-to-build-redux/)

[https://medium.com/@karpathy/yes-you-should-understand-
backp...](https://medium.com/@karpathy/yes-you-should-understand-
backprop-e2f06eab496b)

------
wiremine
1\. Get good at decomposing problems.

2\. Be attentive to "flow" and how you achieve it. Space/surroundings, time of
date, amount of time, etc.

3\. Be aware of your energy level, and match the task to your energy level.
Get away from the keyboard and get your brain engaged in other activities to
keep you fresh and excited about programming.

4\. Write great documentation. This takes as much practice as programming
itself. Understand "great" is not equal to "a lot"

5\. Don't overbuild on the first pass. Refactoring is your friend.

6\. Prototyping is very valuable, but be aware the prototype that doesn't die.
I tend to use languages that force the prototype to be thrown away.

7\. Profile.

8\. Always be learning about your craft and related areas. Business, design,
security are all handy when you're a programmer.

9\. Don't be a jerk.

10\. Learn a variety of languages. You'll likely have a few favorite
languages, which is fine, but always be picking up new ideas.

------
lukeholder
Read other peoples (good) code.

~~~
hultner
And read bad code as well so you'll know the difference.

------
p0nce
Don't think that cognitive biases don't apply to you.

------
coldcode
You will never get a group of programmers to agree on such a list. Like the
old Jewish saying (paraphrased) for every 3 Rabbis there are 4 opinions. In
the end you have to find something that you believe in but be willing to alter
if something isn't working, assuming you can tell.

~~~
_asummers
"Strong opinions, loosely held."

------
Poiesis
Make it easy to verify what you have written works. This can be done in
several ways, and which ones to use depends on the people you're working with
and what access to the production code you have. Debug log levels are a
popular way to do this.

* Always make a way to examine the data that's coming in (over network, arguments, whatever) to make sure your code is receiving the input it expects, and to be able to predict output/state changes.

* Similarly, have a way to see the data/state changes produced by what you wrote.

* Don't log all this by default.

* ...except for unexpected outcomes. By all means, check your inputs and loudly complain if they are garbage in a way that's unrecoverable.

* Be judicious about how much of this you normally expose to a user; don't overwhelm a user with unactionable noise.

------
calafrax
Don't think you are smart. Remember that you are average and that for everyone
who you might think you are smarter than there is someone else who is equally
smarter than you.

You will move in the direction you face. If you look down on people your skill
will diminish. If you look up to people your skill will improve.

Be a dilettante. Do general study of many different fields but recognize the
limitations of your knowledge and show the appropriate respect to specialists
and experts in their respective fields.

Pay close attention to your errors. Do root cause analysis on every error you
make and formulate a plan of action to avoid it in the future.

Analyze your own habits and the habits of your peers. Seek to adopt practices
that work for others where possible but only if they prove to work for you as
well.

------
jamesmishra
When you see something you don't understand _, find out how it works.

_ There are varying definitions of "understand", but I am confident that I
understand something when I can give a lecture on it with no preparation... or
when I can code it without checking any references.

------
Taylor_OD
Getting 8 hours of sleep a night.

------
scandox
I define this in the negative using myself as the non-great exemplar:

Taking the time to properly understand the concepts, protocols, formats, apis
and tools that you use when working on something.

This I never seem to have the time or mental energy to do.

------
mezod
Great thread! One of my habits is to try to think of what I learnt the
previous day, and if it involves some specific lines of code, briefly go
through them to recap. The other is to try to learn something new every day,
no matter how little the learning is, I want to feel I did learn something.
Consequently, I developed this little app
[https://everydaycheck.com](https://everydaycheck.com) to track these habits
among many others that are not necessarily related to programming.

------
rszrama
1\. Generous function level and inline comments that explain the rationale
behind code organization / approach. Code can be self-documenting, but
intentions are not. A great programmer will ensure future maintainers /
contributors don't break something for lack of understanding the original
context.

2\. No magic configurations. No implicit behaviors. Every optional behavior
should be explicitly opt-in or opt-out.

3\. Treat one as a special case of many. You will thank yourself later when
you would otherwise curse the day you were born.

~~~
kazinator
What will prevent future maintainers from breaking something is regression
tests, not comments.

------
factorialboy
Based on my experience:

\- Beginner's mind, with discretion

\- Ability to avoid buzzwords / marketing mumbo jumbo and identifying true
value (or lack of) of any tool

\- Remembering you are here to solve a problem, beautiful code is not an end
to itself

\- Beautiful code is maintainable

\- Maintainable code makes you productive

\- Productivity is everything: The more problems you, can solve the better you
are

\- Personally, Hatha Yoga and certain related practices (Kriyas) have
rejuvenated me every time I felt burnt out. I'm not a hippy new age shill and
if you contact me, I'll share more information.

------
kennydude
* Work/Life Balance

* Willing to learn new stuff and prove themselves wrong

* Talks to users

* Keep it simple. Nobody is impressed because it's overly complicated without a VERY good reason

------
Syzygies
I made a list as I worked, to avoid repeating classes of errors. I found this
list decades later. Last entry:

Forgot to eat. Got sick.

------
jasim
Depth.

Every programmer I admire has worked on their chosen field for years. You can
keep flitting between languages and frameworks, but mastery ultimately comes
from hankering down on one thing and advancing our collective knowledge a bit
further. You can achieve mastery in any field - it can be a business domain -
as mundane as a Time Tracking or a Todo list app, or it can be a technical
domain - like compilers or databases or browsers. You however can't achieve
mastery by consuming what others produce. Becoming an expert in CSS and its
quirks is a good vocational investment, but you're no closer to a fundamental
understanding of the field by just consuming an API.

You should spend years working on a problem domain that interests you. Look at
prettydiff
([https://github.com/prettydiff/prettydiff](https://github.com/prettydiff/prettydiff)).
It is a diff tool, a parser, a pretty printer, a minifier, all rolled into
one. It is the most comprehensive publicly available tool in terms of language
and dialect support in the world right now. Its code is not the most modular
and new contributors might have trouble getting in, but its author has been at
this problem for years, and if you called a conference for pretty-printing, he
would be one among the few thousand people in the world to meaningfully
participate.

Consider blueimp's jQuery File Upload plugin
([https://github.com/blueimp/jQuery-File-
Upload](https://github.com/blueimp/jQuery-File-Upload)). While this isn't as
foundational a work as prettydiff, the project spans seven years and a
thousand commits. It solves a mundane problem, but the sheer effort that has
went into it makes it a formidable solution.

Consider Martin Odersky, watch Compilers are Databases
([https://www.youtube.com/watch?v=WxyyJyB_Ssc](https://www.youtube.com/watch?v=WxyyJyB_Ssc)).
He has been writing compilers for like forever. He's worked on the field for
decades, and has written compilers for everything from Fortran to Java to
Scala.

You don't have to be a genius to be a master. You just need to go as deep into
a field as you can. Here are a few interesting links you might want to read:

The Joys of Having a Forever Project:
[http://web.archive.org/web/20130125011224/http://www.dev.gd/...](http://web.archive.org/web/20130125011224/http://www.dev.gd/20130122-the-
joys-of-having-a-forever-project.html)

Rich Hickey on becoming a better developer:
[https://gist.github.com/prakhar1989/1b0a2c9849b2e1e912fb](https://gist.github.com/prakhar1989/1b0a2c9849b2e1e912fb)

You and Your Research by Richard Hamming:
[http://www.cs.virginia.edu/~robins/YouAndYourResearch.html](http://www.cs.virginia.edu/~robins/YouAndYourResearch.html)

~~~
rf15
Counterpoint: Breadth.

(...Don't polarize on one end of the Specialist vs Generalist debate.)

Since improvement of experience and quality of output is roughly logarithmic,
it is (depending on the specialisation of the task at hand) better to have a
person that has worked ten years to be 7/10 in 5 displines than 10/10 in one
and 2/10 in the remaining 4.

Of course, if you only care about the one discipline, get the 10/10 guy. But
in real use cases, things are only occasionally atomic, and lack of
understanding of adjacent processes and disciplines can prove fatal.

------
webnrrd2k
One small addition: if you have the choice between a complex data structure
(w/simple algo) or a complex algorithm (w/simple data structure), choose the
simple algorithm. It's very often easier to reason about data as it's
relatively static, vs a complex algorithm.

Once everything is working then, if it's warranted, change the algorithm.

------
rb808
First you have to define what a great programmer is. Best CS knowledge?
Highest Pay? Most prolific? Leading edge? Knows lots of languages? Most
famous? Makes software that users love? Makes profitable companies?

Usually great programmers are good at some of the above but never all, so you
have to be clear about what you mean by great. After that its easy :)

------
Poiesis
Something more habit-like that I am still trying to cultivate: log what you
do. It's really useful to be able to look up what you did when. It helps with
reviews/invoices, and it helps you get better at estimating how long it takes
you to do things, which is essential.

------
wolco
Learn how to say no.

Learn how to get paid when working for yourself.

Try to learn or at least play around with a new language every year.

Keep writing code.

------
jryan49
There is no silver bullet.

Programming is the art of compromise. All solutions have pros and cons, the
first thing to know is what things are more important than others in this
situation (performance, maintainability, easy to program, etc, etc) and
figuring how to deliver the optimal solution.

------
circlefavshape
I say don't worry about being "great". Just do your best on each individual
task

------
zachng
From Kent Beck himself that is of relevance to this topic:

[https://news.ycombinator.com/item?id=11858667](https://news.ycombinator.com/item?id=11858667)

------
mustardo
Google for solutions before making another wheel

------
jimjimjim
One size does not fit all.

+

There is no one true way.

=

Anybody that claims that there is only one way to do something is selling
dogma.

that and, listen to many voices, especially those that aren't the loudest.

------
eibrahim
My number one skill is "Googling"

------
gdubs
Sleep.

Make it concise, not clever.

Keep functions short.

Small, frequent commits.

Instrument before you optimize.

------
fscherer
Regularly refactoring old code. Really helps to think more about abstractions
& code design.

------
bsvalley
Good communication skills and positiveness. Technology alone doesn't do
anything.

------
sidcool
This is a great discussion. Worthy of getting more comments. Thanks all!

------
alecco
Make a routine and stick to it no matter what. No excuses.

------
epynonymous
attention to quality a.k.a thorough testing, i require that all interviews
with dev candidates include being drilled on automation and testing. curiosity
to learn new techniques and technologies, is this person playing around with
new stacks, languages, etc in his/her spare time, does he/she have open source
projects, that tells me that this person is quite passionate about
development. i think another one is comprehension of the requirements, often
times i see poor developers jump into a solution without fully understanding
the requirements.

------
FroshKiller
Always look both ways before crossing a one-way street.

------
martin_a
Love what you do. The rest will follow.

------
Powerofmene
Communicate w customers.

------
insulanian
Attention to details.

------
fergie
Define great.

------
anoplus
standardization and automation.

~~~
sidcool
By standardization, do you mean having a style guide for the project code
style? Because that would differ from team to team.

------
known
Reuse code;

------
juliansamarjiev
git status

------
misterAxiom
1\. All programmers should drop the "I don't have to be good at math"
habit...you're disrespecting people who are likely in possession of knowledge
that will help you later. Being "good at math" means you communicate and try
to understand concepts. It's more about attitude than knowledge.

2\. All programmers should learn Galois theory, not only to get over the idea
that they can't be good at math, but to learn to appreciate math. The book by
Ian Stewart is good, although I would supplement it with Artin or Dummit and
Foote.

3\. Try to figure out why Ken Thompson and Dennis Ritchie did what they did,
when they did it. Very important for getting a historical understanding of
programming. Also, try to figure out why Ken Thompson said what he did in
"Coders at Work".

4\. Read The New Hacker's Dictionary.

5\. Read Naive Set Theory

6\. Try (and fail, at least for a year) to read A Shorter Model Theory (don't
give up!)

7\. Read Code Complete followed by the Python 2.x source code

8\. Read SICP and write a scheme interpreter in a language of your choice

9\. Implement a simple LR parser, instructions here:
[https://en.wikipedia.org/wiki/Simple_LR_parser](https://en.wikipedia.org/wiki/Simple_LR_parser)

10\. Play Kitten's game
[http://bloodrizer.ru/games/kittens/](http://bloodrizer.ru/games/kittens/)

11\. Play the UC Berkeley CS 61a adventure game
[https://inst.eecs.berkeley.edu/~cs61a/reader/](https://inst.eecs.berkeley.edu/~cs61a/reader/)

12\. Play JSRobowar
[https://statico.github.io/jsrobowar/](https://statico.github.io/jsrobowar/)

13\. Read "Development of the C Language" [https://www.bell-
labs.com/usr/dmr/www/chist.html](https://www.bell-
labs.com/usr/dmr/www/chist.html)

14\. Read "The Mythical Man-Month"

15\. Read "Simply Scheme"

16\. Read "The C Programming Language"

~~~
horatiocain
Why the kittens game? To demonstrate the effects of scale?

------
minademian
such a great thread, guys. thank you.

------
justforFranz
Oh god, again with this.

~~~
sidcool
I believe you have already read such threads in past, can you share those?

