Lessons from teaching CS 1: Code fast
imprompt.us
imprompt.us
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.
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?
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?
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.
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.
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.
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.
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.
This lets you do exploratory programming, and also generates verbose comments for the TA to look at.
(This strategy is discussed in Code Complete.)
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. :-)
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.
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.
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'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).
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.
Edit: As well as fail quickly, fail cheaply.
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.
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.
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).