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.
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.
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?
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.
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?
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.
The point is that the slow programmer won't do just exactly the same thing as the fast programmer. Speed can make a qualitative difference; it affects what you are willing to do, not just how long you take to do it.
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.
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.
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.
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.
I think he was referring to the students difficulty in "expressing" themselves in code. In the same fashion non-native speakers have a hard time expressing ideas in a foreign language.
For example, I know I want to ask for another beer but composing the sentence along with all the right grammars is hard for me in Spanish. Similarly, to a novice programmer she may know she wants a loop but writing out the correct syntax is simply difficult for her.
You're right this type of coding doesn't work well in maintenance. However, when exploring a problem, fast coding is phenomenal. Once I discovered I could write code quick enough to do experiments, and that the whole iteration took less time than reasoning out, planning, doing back of the napkin style calculations, and still maybe getting it wrong, I moved to exploratory programming. This is where fast coding shines. Further, a lot of infrastructure can be built up this way, helper functions, I/O frameworks, etc can get massaged into a good solution.
At the end, there is still refactoring, and maintenance (particularly by people not intimately familiar w/ the codebae) may need some more thought, but the initial build... fast is good.
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.
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.
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.
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. :-)
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.
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.
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.)
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 ...
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 . . .
"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).
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.
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.
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.
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.)
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.
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.
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.
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.
I have to disagree. I would say that anything that helps get to a testable solution faster helps make one a better coder. This could be by saving time having to look up syntax, but it could also literally be just typing twice as fast as somebody and being able to iterate through solutions twice as fast as the next guy.
I completely disagree. The number of problem domains where typing speed is the bottleneck is quite small, and they aren't the interesting problems.
As I spend more time in this business, it becomes clearer and clearer to me that the job of a (senior or above) developer is not to be a typist. It is to assist people in figuring out exactly what their needs are, in a precise sense. Typing the results into a computer is almost incidental.
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).
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.