
Productive Programming - taylorwc
http://www.gabrielweinberg.com/blog/2010/08/productive-programming.html
======
jakevoytko
_"When approaching debugging, I first find out where the problem is, i.e. the
exact line of code or config file or whatever that is causing the problem.
That_ should not take long _, and before you ask anyone else about it you
should know exactly where the problem lies."_

For crashes: Get backtraces! Knowing the line and the state of the callstack
makes many common errors trivial to fix. Some languages (Java, Python) are
helpful and generate them automatically. Others (C, C++) require a debugger.
I've seen lots of programmers ignore gdb or Visual Studio and spend minutes
with printf() looking for the exact line of a crash. Code crashes all the
time. Dealing with it methodically and effectively will add minutes - or even
hours - to your day.

~~~
dasil003
The article was decent, but the debugging section offers no insight at all.
Shotgun debugging is a strawman, only the incompetent rely on that. Of
_course_ you should identify the exact line causing the problem, and of
_course_ it should be fast on average, but sometimes it is exceedingly
difficult. Bugs come in three flavors:

Trivial bugs where available evidence points directly to a cause. The scope of
these increases with experience, but most bugs that come up in day to day
coding are of this variety.

Deep bugs are reproducible, but require bisecting the problem to figure out
the cause. Performing optimal bisections requires skill, experience, and raw
brain capacity. This is where a good, but let's say, not virtuoso developer
can distinguish himself from his less-than-average colleagues in a major way.

Heisenbugs are the most difficult because you can't reproduce them, either
because it's a concurrency problem or some limitation of the environment the
bug occurs in. To solve these bugs, a functional language and pure mathematics
may be the best way to get reasonable assurances that a bug is gone, but also
radical creativity in code instrumentation or expensive test scenarios with
dedicated hardware may be necessary.

So, yes, being a productive programmer requires a level of skill where most
bugs are trivial. But nevertheless, the second two flavors exist no matter how
smart you are, and being productive over the long term means being able to
tackle those systematically, even if it takes days or weeks to solve, and if
all else fails, figuring out a workaround.

~~~
aufreak3
Debugging offers a most excellent opportunity to practice science - Observe,
Hypothesize, Test, Repeat. And just like regular science, bugs span the entire
range of trivial to the head-explodingly-elusive.

Observation is in particular quite a hard practice. On several occasions I've
realized that the evidence was staring at me in the face from day one, but my
eyes were too clouded to see it. Sometimes, it helps if you know the system
inside-out, but at other times that itself happens to be a blinding
disadvantage.

~~~
vlisivka
> Observe, Hypothesize, Test, Repeat.

Forget all that stuff. Just improve your code until it will tell you problem
and it exact cause, you will save a lot on "Repeat" step.

------
xentronium
Productivity is a topic too complicated to put into a few sentences but there
is one tip I'd like to contribute: paper and pen are underrated.

There were awful lot of tasks I tried to achieve via pure coding and rewriting
/ rewiring blocks here and there. All they actually needed was some analysis
on paper.

~~~
kenjackson
For me a white board is a lot better. No idea why. But something about
standing up in my office at the white board gets the juices flowing more than
a pen and paper.

~~~
xentronium
I think there's some explanation in biomechanics and different courses of
blood flow, but even more than that, whiteboard allows you to share your
findings and troubles with the colleagues which is probably why you needed
whiteboard in the first place :)

------
jonpaul
One of the most productive programming techniques that I have used (it's saved
my ass) is to make sure that most of my code is unit tested. In the short-term
you will feel like you're moving much slower. In the long term, it'll pay
dividends.

~~~
Lewisham
Yeah, BDD/TDD will also stop the necessity for "running the code all the time"
like Gabriel espouses... what is better is to test the code all the time. Hit
those green marks. Manual run-throughs of code paths is boring, to say the
least.

This I guess is less applicable to the web dev/machine learning domains that
Gabriel operates in.

------
briancooley
"I also found sleeping on it often magically produces a solution in the
morning."

I think this is a great reason to take a nap in the middle of the day if your
environment is conducive to it. It works for me as long as the code is the top
thing on my mind when I fall asleep.

~~~
hswolff
This has happened to me on the past two consecutive days (and nights). A
problem that I couldn't figure out at 11pm, one that I spent at least 30
minutes pouring through Google Groups, searching through APIs, trial and
error, etc...After sleeping on it the solution revealed itself to me in the
morning in less than five minutes. Truly phenomenal and hugely rewarding.

~~~
Tyrannosaurs
My scariest one was dreaming a solution. I woke up about 3am absolutely clear
what I'd done wrong, scribbled a note and went back to sleep.

Next morning I looked at the note and it was exactly right.

~~~
markkanof
I've done this and actually find it a bit disturbing.

It's great when I can't solve a problem in the evening, get a good nights
sleep, and then I am able to quickly solve the problem in the morning.
Sometimes though I actually have dreams about sitting at my desk writing the
code that I couldn't come up with during the day. On the one hand it's great
to wake up in the morning with the solution to my coding problem. But on the
other hand, I'm not sure it's healthy to have my dreams filled with the same
thing that I do all day while awake. Whenever that happens I definitely make
some extra time for my hobbies that don't involve computers.

------
agentultra
I wouldn't say this is an article on productivity so much as an approach to
learning. I find a lot of auto-didact programmers learned this way. The
compiler is a great TA after-all.

If there was one thing I could add it would be _take notes_. If you can
explain to someone else the "whys" and "hows" of your solution to a problem,
you've got it down pat. Sometimes we get something to work by googling a quick
solution, but we forget to try and understand that solution. This doesn't
serve us well. Taking notes helps me to submlimate what I learn on the job
into hard-referenceable tomes of knowledge.

~~~
epi0Bauqu
In addition, start a blog for the pieces you can make public. Blogs have so
many other benefits that you should be doing one anyway (especially if you are
also involved in startups).

That said, writing about programming on your public blog is scary because you
(usually) know that whatever topic you write on there are people who know more
about that topic. You just have to get over that and learn to embrace the
benefits of the conversations that ensue. Or write to a private audience.

~~~
bostonvaulter2
If you just one day decide to start a blog. Chances are it will be mostly
private audience for quite a while. Of course that is dis-regarding the
spammers.

------
tieTYT
The article mentioned the dangers of clever code and asked for a particular
quote he couldn't remember. I couldn't help but be reminded of this one:

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it. -Brian Kernighan

------
wslh
It well depends of the problem domain, sometimes productive programming is
about best algorithms, for example if you develop a software playing chess you
can't left it for later improvements.

I can add some of my experience (since I was 8 years old?), it works in my
personal framework:

\- Hybrid languages/technologies: for some solutions I need to use jython to
develop in python + java libraries that you don't found in other languages
(i.e: htmlunit).

\- I have always an interactive console opened to test stuff while using an
editor.Sometimes the language doesn't have a good interactive interpreter, my
preference is using python (if using .net, then ironpython, if using java, the
jython, etc).

\- Since I do a lot of research for customers, research and proof of concept
are first in the list to reduce the real risk in the project.

\- When I need optimizacion/speed C/C++ is the language, but try to glue with
python, ruby, COM, etc (SWIG is your friend).

\- Sometimes debugging is the best option, sometimes focusing in the code and
try to find the bugs in my head.

\- Then I agree with Gabriel.

------
robryan
A bad habit I can get into is thinking about a feature in terms of all it's
parts and getting mentally stuck on starting trying to put the whole thing
together from the start. When as the advice in the article gives it is much
better to focus on getting the critical path of a feature working. The mental
block of thinking about the whole can easily lead to procrastination for me,
something I am trying to avoid.

------
smithbits
I appreciate the call to find the exact line of code that is causing the
problem. I've done a fair number of code reviews where there was a bug, and it
was "fixed", but no one knew _why_. The developer had simply kept changing
things until the problem seemed to go away. That would mark the bug as closed,
but it always seemed to show up again some months later in a new guise. These
days I'm a terrible nuisance as I always want to know why the bug was
happening. In my experience it's not enough to "fix" the bug you really do
need to understand why it was happening in the first place, which is something
that not all programmers do.

------
jolan
> I initially try to accomplish X in the simplest way possible by breaking it
> down into trivial steps. I know there is a famous programming quote that
> pertains to this process, but I can't find it right now

Maybe this is it?

A program should be light and agile, its subroutines connected like a strings
of pearls. The spirit and intent of the program should be retained throughout.
There should be neither too little nor too much, neither needless loops nor
useless variables, neither lack of structure nor overwhelming rigidity. -- The
Tao of Programming

~~~
epi0Bauqu
No, this comment on the blog is the closest so far to what I was talking
about:

rjbond3rd: "I'm mangling the quote but what I've heard is: 'Tackle a difficult
problem by redefining it as a series of solved problems.'"

~~~
garret
_One of the most useful mental habits I know I learned from Michael Rabin:
that the best way to solve a problem is often to redefine it._

<http://www.paulgraham.com/ideas.html>

------
10ren
The quote for #2

 _What's the simplest thing that could possibly work?_
[http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.htm...](http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html)

------
jackowayed
I can't think of a specific quote about breaking down programs into small
steps, but you could be thinking of something from
<http://paulgraham.com/progbot.html>

~~~
aheilbut
I don't know if this counts as a quote, but the term of art is "divide and
conquer"

~~~
epi0Bauqu
No, neither of those are it. I saw it on HN within the last two weeks, but I
couldn't find it in a reasonable amount of time.

------
edw519
BIG disclaimer: I have NO formal training.

1\. Tools. I generally shy away from tools. I just don't like using _anything_
that makes me more productive when I'm programming. I prefer to type out every
line of code, occasionally cutting and pasting from the same program or
something similar from the past, but not very often. I _want_ the writing of
code to be painstakingly slow and deliberate. Why? Because productivity is not
the objective. Becoming "one" with my project is. I may not start as fast as
others, but that doesn't matter. It's not how fast you start, it's how soon
you deliver a quality product. Like memorizing a speech, cranking out the code
by hand makes it "firmware" in my brain. It's not unusual for me to crank out
300 lines of code and then be able to reenter them on another machine from
memory. So when it comes time to debug, refactor, enhance, or rework, those
cycles go _very_ quickly; that code is already in my brain's RAM and it got
there the hard way.

2\. Simple Algorithms. Yes! I love this example:

    
    
      * EnterOrders 08/31/10 edw519
      *
      return();
    

I now have a working programming - Woo hoo! You say you want more features? No
problem. Let's start enhancing it.

3\. Debugging. I don't. I've seen 25 different debuggers and I hate them all.
Print() is my friend, especially beyond the right hand margin. Better yet,
write code that doesn't need to be debugged (See #1 & #2 above.) (Of course,
this is much harder with _someone else's_ code.)

4\. References. Don't need no stinkin' manual. I have become extremely adept
at about 4% of what's available to me, but that 4% accomplishes 98% of what I
want to do. (OK, I'll refer to a manual when I need something from the other
96%, but that doesn't happen too often.)

Nice post, Gabriel. Got my juices flowing. We could talk about all kinds of
other things too, like variable naming, how to iterate and branch, and never
typing the same line of code twice, but this was a nice starting subset.

~~~
vilya
I'm amazed and a bit saddened whenever I hear sentiments like this. These days
more than ever.

The thing is, every single bit of code you write depends on something else
that you DIDN'T write. Everything. No exceptions.

And the thing about stuff you didn't write is that you end up making
assumptions about it - often without even realising. Sometimes the assumption
is simply that the code works. Sometimes, some of your assumptions will be
wrong.

Debuggers help you check your assumptions. They're a very useful tool for this
- more so than many people who say "I prefer printf" realise.

I apologise if you're not in that category, but did you know that many
debuggers have a way to print a message (without stopping) whenever the
program hits a certain line? Just like printf, only it doesn't have to be
built in to your code ahead of time.

There are times when a debugger isn't the right tool for the job, but it's
always better to make an informed choice.

~~~
anamax
> I'm amazed and a bit saddened whenever I hear sentiments like this. These
> days more than ever.

The big advantage of printf as a debug technique is that it doesn't work
unless you understand what you're doing. If you plan to debug using printf,
you must write code that is easy to understand.

Great debuggers let you try to fix code that you don't understand. Worse yet,
they make it reasonable to write such code.

Since the person reading the code is never as smart as the person who wrote
the code, encouraging simple to understand code is extremely important.

~~~
Roboprog
A big disadvantage of printf() in C (or similar non-memory-managed languages)
is that printing values can disturb the "noise" on the stack that you were
trying to find. That is, if you had a bug due to an uninitialized local
variable or buffer overrun, the printf() call could "stabilize" things and
cause a bug to _stop_ manifesting.

Better to use a debugger, _if_ you can. Not that I haven't ever sprinkled
print's into the middle of a big mass of somebody else's code or framework
just to get the initial lay of the land :-)

~~~
vicaya
uh, the -g compiler flag to enable debugging will create much more disturbance
than a few printf ever could, debuggers are mostly useless for tracking down
race conditions as they change the timing completely. OTOH, I'd use a low
overhead logging package instead of printfs.

~~~
Roboprog
Good one: yes, race conditions are not going to manifest while manually slowly
stepping. You of course need to plan / read carefully for code which will be
vulnerable to such.

Regarding "-g", at the job a few years ago where we were using C for some in-
house jobs, we skipped using "-O" for the most part and simply deployed with
"-g" left on. Better safe than sorry for single-use software.

