
Lessons from teaching CS 1: Code fast - mbrubeck
http://imprompt.us/2009/code-fast/
======
edw519
OP's title is a little too abridged for me. "Code fast" could mean too many
different things. Many programmers whose code I maintain look like they
adhered to the school of "Don't think, code fast."

I would prefer: "Code something small fast."

What's "something small"? It could be a just the core of what you propose with
no features or embellishments. It could be a subset of the problem at hand. It
could be one case of a general problem. It could even be a guess.

The point is that if it's small enough, you can code it fast and test it right
away. If it's just right, you can build upon it. If not, you can quickly amend
it and retest.

Many huge applications have started out as a tiny core with less than 50 lines
of code, probably written by one person in less than an hour. I suspect that's
the idea OP was getting at.

~~~
pmb
What I was getting at was that increased speed in coding has nonlinear effects
n your time-to-solution and that students should code sooner --- before they
have the solution in hand --- rather than waiting until they think they know
the right answer.

Coding for classes should be done quickly and exploratively. But because
students either can't code fast or won't code before they have the whole
solution mapped out, this (measurably better) solution technique is
unavailable to them.

~~~
jules
> nonlinear effects

Can you explain this? If you are a slow programmer and just did exactly the
same as the fast programmer, just slower, how can that be a nonlinear
slowdown?

~~~
Kliment
At some point trying something else is slower than figuring it out "dry" on
paper and coding a pre-thought solution. Thus the nonlinearity. If trying is
faster, you can try before you know exactly what you are trying,and figure it
out as you try.

~~~
jules
So the slowdown is less than linear then. If you do it the stupid way and
still try it out it's linear. So if trying it out on paper is faster...

~~~
pmb
Something is wrong with your logic, both because I can't follow it and because
it contradicts all the "anecdata" I have collected during my career.

~~~
jules
The logic is simple. Suppose that a fast programmer can do some task in time
t. We have a slow programmer who programs twice as slowly. In the worst case
all of time t spent by the fast programmer was spent programming which is what
the slow guy is slow at. In that case our slow programmer will take 2t, a
linear amount of time. If the slow programmer had an alternative strategy he
would only use it if it reduced the time to complete the task. Therefore the
time is linear at worst.

Note that even if the slow guy is 1000 times slower it's still linear.

Please explain why the logic isn't right. Could it be that the logic is right
but that slow programmers tend to do things on paper first, which is not the
best strategy?

~~~
pmb
Because slow programmers don't program first. They program last, and do "big
design up front" on paper. This is because the cost of a bad idea is hours
wasted, and despite the logical coherence of various "expected value"
arguments, students are loathe to risk having wasted multiple hours doing the
wrong thing. Because humans' internal risk functions and utility evaluation
functions are not linear and bayesian, people who code slowly also code
differently, and those differences further slow them down with the goal of
having less wasted time. In an effort to reduce their variance, they
unknowingly increase their time-to-solution.

~~~
jules
That sounds right. I still do that when I'm working with a new programming
language/library that I can't yet use well...

------
kscaldef
I find myself disagreeing on two fronts here:

First, in the context of CS1, in my experience, the assignments just aren't
long enough that speed writing code matters. 20-50 lines of C just isn't that
much typing.

Second, in the world of real work, the hard problems rarely boil down to how
fast you can get the thoughts out of your head, through the keyboard, and into
the computer. I often spend hours or even days pouring over existing code and
in the end change a single line of code. If I just started typing right away,
I might fix the immediate problem faster, but there's a strong chance I'd end
up with a larger diff that makes the code base worse and possibly introduces
new bugs and corner cases.

I may be misinterpreting the author; perhaps by "code" he is referring to the
full analysis, design, and implementation process, in which case I suppose it
is inarguable that a good developer should do this fast (or faster than a poor
developer). To a degree he seems to be saying, "start prototyping right away",
which is also valuable at times. But still, in either case, what seems odd is
the idea that CS1 students ought to already have the skills of an experienced
developer. Of course they don't; they're beginning students and the job of the
teacher is to guide them to these skills. Perhaps what would be truly helpful
here is suggestions of how to improve the curriculum or pedagogy to help
students gain these abilities more quickly.

~~~
mbrubeck
Reading the post again, it seems to me it isn't about raw speed in producing a
finished product; it's about the ability to explore a problem space by writing
small throw-away trials, _before_ you know how the result should look.
Physical speed is just one part of this; I'd say it's really about fluency. Do
you use code as a medium for thought and expression, or do you have a separate
step where you translate your ideas into code from some other form?

This is a real distinction I see even in experienced developers, and in that
case I think it's more a matter of habit and practice, rather than skill. Some
of my co-workers have an ingrained habit of sitting down at a REPL and trying
out several ways of doing things, whenever they're thinking about a problem.
Others have apparently never tried this way of working, even though they are
probably quite capable of it.

~~~
pmb
Yes! That is the kind of speed and skill to which I was referring. The ability
to use code as a medium for thought and exploration rather than just viewing
it as a final product.

~~~
prewett
Maybe I'm one of the slow coders, but for sizable problems, I find that
thinking about the problem on paper speeds things up greatly: I don't waste a
bunch of time re-writing my half-written class as I discover it's not what I
want. (Not writing in C++ helps) I'm thinking of things that require a few
classes here, rather than a large algorithm.

------
rdtsc
This is like asking an un-experienced driver to drive fast. Or an un-
exprerience scuba diver to go deeper.

I remember that I didn't code fast in my CS1 classes. The reason was because
it was scary. The compiler and all syntax errors seemed cryptic.

Now one of the goals of the class should be to make students not afraid of
trying things out. To get there they have to understand the tools and the
basics.

Having a good langauge + compiler/interpreter definetly helps. For example,
Python's REPL is a way to try things fast. Especially when used with something
like ipython, where you can explore an object's methods as you type.

C/C++ and gcc is not so great in this respect. You get a segementation fault,
and the next thing you do is pepper code with print statements or fire up gdb.
Now they have another problem to solve -- how to use gdb. Very useful, but
perhaps not for someone in CS1, unless CS1 as a filter and its purpose is to
scare everyone away.

~~~
btilly
One intermediate solution is to ask people to code everything out in pseudo-
code. Think about what it would do. Then when they are happy about it comment
it all out, and below each line of pseudo-code write real code doing the same
thing.

This lets you do exploratory programming, and also generates verbose comments
for the TA to look at.

(This strategy is discussed in _Code Complete_.)

~~~
pmb
That's true. But it (generally) doesn't let you discard your wrong ideas
quickly, which is where the approach I was trying to describe gets most of its
benefit. What you describe is much more akin to a waterfall model with a bunch
of pseudocode and design up front but without an automated tool (the computer)
actually able to run your program and tell you if it is going well.

~~~
btilly
That depends on which wrong ideas you're thinking about.

Actually writing down pseudo-code is good at flushing out hidden assumptions,
points of confusion, etc. I've found that tracing through pseudo-code can help
identify bottlenecks and design flaws. And it is all much cheaper than a real
program. So you get to discard a lot of wrong ideas quickly.

However coding up a test program and being able to run through cases quickly
on a computer catches slightly different classes of mistakes. You might not
catch a logic error in your code, but you are more likely to figure out how an
external API works.

I think that both skills are valuable, and both let you discard wrong ideas
quickly. They just catch different kinds of wrong ideas. :-)

------
dgabriel
I keep a sandbox for myself open at all times, particularly when I'm working
on a large project. I whip out a solution for a micro case, test it, refine
it, _then_ implement it. I hate it when people check in their not quite fully-
baked solutions, and let QA test their proof-of-concept for them.

------
theBobMcCormick
After reading the article, it seems like the point isn't so much about coding
fast or slow, but that there's a great deal of benefit to being able and
willing to do some exploratory coding to try out aspects of your solution
before committing to a particular solution approach.

IMHO, this is why fans of "dynamic languages" (an ill defined term, I realize)
tend to be so highly enthusiastic about them. For many people, programming in
a language like Python, Ruby, etc. is their first real exposure to
exploratory, incremental coding.

And those languages _are_ very well suited for that kind of approach, though
clearly exploratory coding can be done in pretty much any language.

~~~
weaksauce
I think DVCS can also help here because you have context switches fast using
many throwaway topic branches and you can discard a branch that did not work
out the way you like. Only pushing the one that worked up after you cleaned up
the history a bit. I would guess that a majority of coders that have to work
with svn in a corporate environment do not like to go off on branches that may
or may not work out for fear of messing up the blessed repository. (that and
branching was not the easiest thing to do in subversion.)

------
bad_user
I don't like these kind of articles ... yes, such advices are good and doing
incremental / exploratory development is something to reflect upon.

BUT ... personally I need clear examples / scenarios / studies. Maybe a school
assignment where the progress of two or three students is tracked with a
comparison ... which had the best solution, which did it in the least amount
of time, which experimented and failed the most, etc ...

Otherwise it just feels like noise.

------
tom_b
I've been thinking some about the idea of coding fast, or coming up to speed
on new languages quickly.

From that viewpoint, I'm wondering about what the minimal set of language
features you need to have committed to memory to enable you to code fast.
These are the pieces of code that without which you can't make even a passing
claim of competency in a language. I'm thinking about the crib sheet of
functions/definitions/language features you have to have ready to go in your
toolbox so you can code fast. It's the stuff you'd want candidates to
demonstrate knowledge of in an interview as well and be able to apply at least
in conversation to a new problem.

I'm interested in figuring this out for a multitude of reasons, not least of
which is retention of knowledge related. Years ago, I hacked in C for
performance reasons in the domain I was working in Lots of pointer junk,
tiling of data (interleaving of row and column data to blow up memory
bottlenecks), and a healthy dose of bit twiddling to make it all work nicely.
I realized not too long ago that most of these skills had faded due to lack of
use.

I'm playing some with spaced repetition software for memory training (think
SuperMemo and Mnemosyne) and thinking about plugging in those pieces of
programming languages that you have to be ready to throw out to code fast in a
language. I'm just testing for now, but I think I might even try throwing
something like the question/answer pieces from The Little Lisper in there for
fun. Kind of a daily brain teaser.

Since I spend most of my time at work hacking SQL, it's pretty easy for me to
stay fresh and also identify the minimum set of concepts and ideas you need to
even think you can write halfway decent SQL: SELECT,INSERT,UPDATE,DELETE,JOINS
- all types, ansi sql functions - including analytic functions, nulls,
subqueries, boolean logic,etc. It's a non-trivial set of stuff to have in your
head so you can think correctly about problems.

To make it even more fun, you need to have a meta-sense of when to apply what
tools and languages? When do you want a RDBMS versus rolling out hadoop? What
data do you want to send to your web app so your users can muck around with it
- which means understanding enough Javascript to be able to provide them with
some intuitive tools to munge data there.

I'm pushing towards the idea of internalizing not only the specifics of a
language, but the idea of what programming language and tool fits a problem
best at any given time.

Software folks get all the best toys to think about . . .

~~~
sophacles
"I'm pushing towards the idea of internalizing not only the specifics of a
language, but the idea of what programming language and tool fits a problem
best at any given time."

I've found that anytime something seems crufty, or perhaps like I'm twisting
too many rules, or just plain inelegant, I think "there has to be a better way
to do this" and its off to the google/documentation/greybeards. If you don't
get that feeling yet (it will come) any time something seems hard, explore
other people's solutions -- that is more than one, and compare/contrast them
on a detailed level. Eventually you'll either start just understanding what
the best tool is, or more likely, intuitively knowing that you don't know a
good solution and that its time to search. (It's a big field, knowing when you
don't know is a good place to be).

~~~
tom_b
Yeah, I have a lot of "there has to be a better way to do this" thoughts . . .

One of the aspects of software development I'm really interested in is finding
drills and ideas that more rapidly build the intuitive response you can trust.
The tools of the craft, so to speak.

There is some type of balance to be found in this space, some combination of
declarative knowledge (memorization and simple application of different
programming languages) and procedural knowledge (experience building up the
greater piece of software from that low-level mix).

Thanks for the crufty test idea - nicely sums up what I'm talking about.

------
F_J_H
Seems to be another variation of "he who has the fastest iteration times
wins".

Edit: As well as fail quickly, fail cheaply.

------
jcw
I think what the author means is that students have trouble breaking down
large problems into small ones, and quickly testing out solutions to these
small problems. As a student, I notice that people I know have some difficulty
doing this.

------
pmb
It's not just prom teaching CS1, it's also from teaching algorithms and OS and
every other course I've taught. A willingness and ability to code fast and
fail fast is universally applicable and useful.

~~~
mbrubeck
Hi, Peter! I'd fix my Hacker News headline but the edit link has expired.
(Changing the title it to emphasize _exploration_ rather than _speed_ would
have been nice too, since it seems like a lot of people are arguing against
points you didn't make.)

~~~
pmb
Hi Matt! No worries. Thanks for posting this to HN! It's always nice to feel
like I am not just shouting into the void, but it feels too self-promoting and
vaguely spammy to post my own stuff. So I've been very glad that people (both
here and on Facebook - I must figure out how to unify comments) have found
this interesting.

------
mikemainguy
I agree... personally I think you should not be allowed to code unless you can
type somewhere around 60-70 wpm. It is only with extreme mental effort that I
can watch someone hunt-and-peck out 5 lines of code fiddling with their mouse
and looking for the "n" key or the ";".

There should be a minimal period of time between when the code appears in your
head and you see it expressed on a screen. If you can't type that fast, write
it down, if you can't write it down, use a voice recorder.

I'm serious, if you only type 20 wpm, you are like an soccer player who can't
run. Sure, running isn't the objective of soccer, but it sure as hell is an
important skill to be proficient.

~~~
LucaDuval
He's not talking about fast typing. He is saying that is a big effort for his
students to try out an idea because they have to struggle to find the correct
syntax and keywords to express it.

~~~
pmb
Also that they refuse to experiment by trying out ideas which may or may not
work. Instead, they bang their heads and don't type a lick until they have
found what they regard as "the" solution. Which is often not even "a"
solution, but because they haven't been coding their ideas as they go, they
have no way of finding that out until they slowly and painfully implement
their idea and it doesn't work.

------
pasbesoin
What this (title) makes me think of is having and environment/tools that don't
get in your way. Not so much a large step (e.g. a significant compile), but
the small actions you're constantly taking.

A UI (editor, file manager, etc) that doesn't hesitate while it composes menus
or context. "Intellisense" (whatever your flavor, if any) and references that
are immediate.

When I work on a slower system, such small pauses accumulate into a "mental
stutter" that changes the level of my overall performance. It isn't that I
don't think -- a lot -- but that when I manage to form something in my head, I
want to get it down with a minimum of of interference and distraction. Those
pauses can be the "thousand cuts" of the death of that inspiration.

Perhaps that's one reason I still prefer to design on paper. There's nothing
between me and my ideas except the speed of the pencil, and my ability to flip
between pages (that have strong visual landmarks).

