In particular, the following remarks from Gingold's essay complement the OP well: "My hard drive was full of failures. Twelve years after learning to program, I looked back on all my software: none of it was finished, and what was, wasn’t ambitious enough. The projects that started out ambitiously always seemed to fall back to earth, like failed rockets lacking the power to propel their own weight into orbit. Sure, there were interesting ideas in there, lots of wacky toys, and I had even attempted a few large projects, but none of them ever came together like the cool games and software I had always admired.
Sure, I had become a pretty good programmer, and learned to make cool stuff, but clearly none of it would ever amount to anything. I just didn’t have what it took.
I went to graduate school at Georgia Tech, and read some Chris Crawford. I learned that he had the same problem. But he didn’t think of it as failure. For him, this was an organic part of the development process. The failures filling his hard drive were actually “prototypes” that helped him decide which ideas were worth pursuing. For each good idea, there were a large number of stupid ones that didn’t work out. Failing, for this successful designer, was a way to find the good ideas. The revelation hit me like a ton of bricks. Maybe I had a chance after all... Master artists like Escher or Van Gogh don’t just sit down and crank out a finished piece. Artists create numerous sketches and studies before they undertake finished paintings, let alone masterpieces... All of my software failures, which I was now thinking about as prototypes, sketches, and studies, had taught me a thing or two about design and programming. If you want to learn to draw, you have to make a ton of bad drawings first. The difference between practice and failure is simply a matter of attitude."
These ideas are, of course, not new, but Gingold has thought about them deeply and distilled them sharply. The essay as a whole goes much further than the above excerpt, and is well worth reading.
Oh yeah. "The difference between practice and failure is simply a matter of attitude." Nothing is more true.
I recently pulled out some code from over 20 years ago, an experiment in mixing fuzzy logic and Conway's Life that... didn't exactly work out. But it had some intriguing results. Was it a "failure"? Not in the least: it produced results that were intriguing enough for me to remember two decades later, even though it never "came to anything" in the meantime.
That said, I do like the word "failure", and I'm happy to say, "My hard drive is full of failures!" It just sounds better than "practice" and it challenges anyone I say it to. What can they say in reply?
The world is full of little people desperately attempting to tear you down. When you say, "My hard drive is full of failures" they have nothing to come back with. They know you've actually done something, which is more than they have. So go forth and embrace your failures. They prove you're alive, and doing something interesting with your life.
My attitude is in part informed by this quote: "One word characterized the most strenuous of the efforts for the advancement of science that I have made perseveringly during fifty-five years; that word is FAILURE" -- Sir William Thomson. If Lord Kelvin can fail, so can I, damnit!
One of my favorite quotes: "Success is the process of going from failure to failure without loss of enthusiasm." I like it because it highlights that failure is a point event, while success is a process, a trajectory. So comparing the two is fallacious. It is possible for both to coexist.
I found the OP to be disquieting, and your link even more so. I haven't written that many distinct programs in my life, and I never did well in programming contests with tight time limits. I tend to agonize when I program, hitting a conceptual wall after every few hours that I'm unwilling to just hack my way through. Usually I go away for a day or month before coming back to continue for a few more hours, until I hit my next wall. I enjoy building a few familiar things over and over again -- the game of life, RSS readers, chessboard apps, more recently lisp interpreters -- but by and large I am bored by doing things that have been done before. I'm constantly trying to run before I can walk. Maybe this habit/cadence is fundamentally limiting my pace of improvement? After all, I started programming late in life, and I've only been programming 18 years or so (compared to the 12 at the start of the Gingold essay). Maybe I still have a lot to learn, and I should try to do more, faster? Focus less on truly hard problems and more on mastering skills?
But I think your link also helps me understand my strengths (and rationalize away my weaknesses :) All its examples are from games, which are by definition a short-lived genre of program with a constant churn of rewrite and reimplementation in a hit-driven business. I tend to obsess about system software, where code tends to accumulate slowly and huge swathes are never rewritten. In my domain it isn't being able to write software that's key, but being able to read other people's code. That's what I struggle with, and it's at least not obvious that these articles' approach helps with getting better at reading.
I return to the first paragraph of the OP: programming is too broad a field. I suspect we think of it as a field only because it's so incredibly young. It's quickly flowering into a foundational skill, on par with reading and writing (perhaps replacing 'rithmetic?) It's not a single domain, but all domains, each with its own subtly different emphasis on core skills, preferred paths of improvement, and likely failure modes. These articles aren't as comprehensive as I had first feared.
(I realize I'm not actually rebutting anything the articles said. Both are valuable and I'll continue to mull them. I'm just airing insecurity here.)
For me, that is my ~/git/scratch repo (formerly ~/hg/scratch).
I have a lot of experiments in there: different approaches to parsing; R/OCaml/Lua experiments; tests for interactions between Unix signals, processes, and threads; etc.
One thing I've also found useful is: whenever you see a neat code snippet on Hacker News or a blog, download the code, and write a shell script to build and demo it. You don't even have to understand it thoroughly the first time around. But when you come across something related in the future, your brain will remind you of it, and you will have a little shell script you forgot about to puzzle through :) It takes like 10 minutes each time.
I have 141 different subdirs; probably half are my own and half are demos I learned something from (or hopefully will in the future).
For many projects, I set up scripts for building (if necessary), running, deployment, etc. That way, when I return to it later I don't have to remember (or take the time to Google) the incantation to run some obscure framework that I haven't worked with in a few years. At the very least, I put some instructions in a readme.
I make a shell script to accompany all code; I basically think of it as an "executable README". A README or blog post often contains shell commands. So I just copy those into a script.
And more often than not I add my own tests and demos. Sometimes I write a main() program, if it's C. If it's JS, then add an HTML skeleton and a script that runs a web server to demo it (e.g. python -m SimleHTTPServer). If it's Python, install any deps necessary. And often you will want to run the same script with many parameters to fully demo it.
The idea is to basically prove to yourself that the code works, without necessarily having to understand everything about it. Then when you see it later, your brain knows you can go back to it. You won't feel lazy like "oh man I have to go back and find the web page I saw 3 months ago, download code, pore through instructions to figure out how to build it". That part is already done.
For example, here's a snippet I did when testing out cityhash. It's usually much messier/longer than this.
I think the assumption was that the code was not fully fleshed out and would require some form of glue code to provide an interface. Even fully fleshed out git repositories usually take a little setup of the environment / compile setting to get it running.
Can anyone recommend books to read on topics along the lines of this article. Basically, tips for programmers trying to bite off more than they can chew (but sort of have to, given the problem at hand)?
"To become the expert, you need more projects. They can be smaller, experimental, and even be isolated parts of a non-existent larger app."
This is so true. A lot of the 'experienced' people I've met in the industry with 10 or 15 years behind them have done nothing but their jobs in that time to practice their art, and their 'experience' is therefore of such low quality that an exceptionally good junior with a few hobby projects behind them can outclass them even in their own specialist area.
I've worked with guys that have done nothing other than Spring and Hibernate for nearly a decade and they know those platforms inside and out. There's just no way someone junior with a few hobby projects are running rings around those guys in their areas.
However, if you take something new, or something these guys haven't used, then yea.... rings could be run. Other than that, I don't think so.
I dunno, I've experienced this a lot, although to be fair, with much larger areas of expertise than a particular product. I was thinking more about 'graphics', 'AI' or at the language level like 'C' or 'Java'.
Although I agree with the conclusion (have several small projects in addition to a "big" one), I think the intro is off.
> It takes ten-thousand hours to master your field, so the story goes, except that programming is too broad of a field.
If you've put in ten-thousand hours into the field of programming, you'll not need to put in another ten-thousand if you switch from, say, a vector-drawing tool to a music composition software. Yeah, you might miss some stuff like everything related to audio - but picking up the concepts and one or two related APIs should be two or three orders of magnitude quicker than "I'm learning to program".
Learning new concepts and APIs is meta-skill, and one will become better at it the more different concepts and APIs one has used.
You'll also need domain knowledge, of course. Again, working with domain experts and users is a meta-skill that you may want to train (or you may depend on someone in your team to do most of that for you, e.g. a Product Owner).
So, if someone has "mastered programming", she should be able to be dropped into an unknown domain and have the skill to identify and pick up the parts she is missing in a fraction of the time it took to "master programming". Mastery of a skill means the switching costs between domains is significantly reduced, but not zero. Same is true for a carpenter: Building a ship is different from building a house or a bridge, yet a master of carpentry will be able to pick up the skill of building a ship more quickly than, say, a master of programming would.
Most fields are too broad to know "everything" about, that is not specific about programming.
Yes and no. Ideas solidify through code, and then form a solid basis for new ideas. If you never reduce an idea to code it becomes too hard to build one idea on top of another.
The difference here is that the code you wrote in the REPL dies with the REPL.
A REPL is more of a "scratchpad", to stay in the family of metaphors being used. Scratchpads and sketchbooks serve similar purposes, but the latter generally is used for things intended to have a bit more permanence and also to be capable of re-visiting.
In any case, I'm pretty sure the main point here is "you need to write a lot of varied code if you want to become an expert at software development".
I was thinking along the lines of SLIME, where your evaluated code is preserved by the editor. Sorry for being unclear. Been a long time since I used a raw REPL.
There's still a useful distinction to be made -- the "sketchbook" talked about is the collection of stuff you've done over some longer period of time that you can look through / look back on. It's not a description of a tool, although as you noted the language used in the last paragraph of the post is very similar to the language people use to describe the use of a REPL.
I'm a fellow emacs user, I use SLIME-like functionality practically every day. My "sketchbooks" are my ~/workspace folder and my github account. I have some older "sketchbooks" in the form of tarballs of my ~/workspace folders from old machines.
I thought that basically everyone who wrote software had similar collections of little projects, finished and un-finished, until about a year ago when it came up in discussion with a few other devs who didn't.
In particular, the following remarks from Gingold's essay complement the OP well: "My hard drive was full of failures. Twelve years after learning to program, I looked back on all my software: none of it was finished, and what was, wasn’t ambitious enough. The projects that started out ambitiously always seemed to fall back to earth, like failed rockets lacking the power to propel their own weight into orbit. Sure, there were interesting ideas in there, lots of wacky toys, and I had even attempted a few large projects, but none of them ever came together like the cool games and software I had always admired.
Sure, I had become a pretty good programmer, and learned to make cool stuff, but clearly none of it would ever amount to anything. I just didn’t have what it took.
I went to graduate school at Georgia Tech, and read some Chris Crawford. I learned that he had the same problem. But he didn’t think of it as failure. For him, this was an organic part of the development process. The failures filling his hard drive were actually “prototypes” that helped him decide which ideas were worth pursuing. For each good idea, there were a large number of stupid ones that didn’t work out. Failing, for this successful designer, was a way to find the good ideas. The revelation hit me like a ton of bricks. Maybe I had a chance after all... Master artists like Escher or Van Gogh don’t just sit down and crank out a finished piece. Artists create numerous sketches and studies before they undertake finished paintings, let alone masterpieces... All of my software failures, which I was now thinking about as prototypes, sketches, and studies, had taught me a thing or two about design and programming. If you want to learn to draw, you have to make a ton of bad drawings first. The difference between practice and failure is simply a matter of attitude."
These ideas are, of course, not new, but Gingold has thought about them deeply and distilled them sharply. The essay as a whole goes much further than the above excerpt, and is well worth reading.