Strong disagree with this analogy. A junior developer studying yacc is not the equivalent of a junior chess player learning the Ruy Lopez.
In order to learn strategy from specific chess openings, you have to study them in context. Memorizing the Sicilian defense lines doesn't teach you much unless you can study it comparatively with all the other openings and learn how that game developed --- and at that point, you're just using the one opening as a forcing function to learn chess strategy seriously.
But that's not what happens when a junior dev learns yacc. Simply by learning to make yacc do things, the developer is given a vocabulary to express parsing and compilation ideas, in somewhat the same sense as a REPL gives you a tool to learn lisp. Sure, you could stop after learning yacc syntax and adapting the RPN calculator example from the yacc book... but nobody does that.
I think it's exactly the opposite to what this guy wrote. People who can express ideas using yacc are to be preferred to people who can talk about LALR parsing but can't show real practical work. The dev who wrote an AST generator with yacc has had to learn how to juggle a parse tree, how to traverse graphs, and what the stages of evaluating a language are. The chess player who learns Ruy Lopez gains no comparable automatic understanding of chess.
And, for what it's worth: yacc and MP arith --- could you have come up with two worse examples of "shallow" programming technologies? If you're for-reals parsing or dealing with problems that need bignums, you're already a million miles past the people who know only how to copy buffers into file descriptors or marshal queries for database engines.
I know chess and programming are commonly analogized, but I've always thought it was a terrible analogy. Chess is a very, very closed game; for all the big numbers you can generate by talking about how many permutations there are, it's still a very small game. Programming is a very, very big game, as it routinely invokes the full mathematical chaos you can only get from the realm of the Turing-complete and invokes arbitrary combinations of humanity/politics and other disciplines. (There are many games just as big, but none bigger.) I find analogies that try to cross the chasm from one to the other are inevitably strained; that's an awfully lot to ask of an analogy.
I think I agree that yacc wasn't a great example for my purposes, but hang on. My point isn't that learning specific technologies isn't valuable, it's just that it is... specific. Even something as general as graph traversal is still not as ubiquitous as lines and pages of code. There may be more generalizable knowledge in learning yacc than there is in learning the Ruy Lopez, but either way, it's not as general as tactics.
Your fourth paragraph is a bit alarming to me, because I agree completely, and I hate to think that I wrote the opposite. I am most emphatically NOT trying to suggest that abstract knowledge is more valuable than practical work. What I do suggest is that being able to reason about code in general is more valuable than expertise with any one specific technology. Consider two coders who have both written AST generators with yacc: can they talk about the low-level, tactical design decisions they made in their code, and the implications of those decisions, and alternatives that they considered?
He is right that you want to study 'tactics' -- ways of making code good. More generally, methods of expression, their benefits and drawbacks.
He is wrong that you want to study it by critiquing code and devising your own improvements. This would be analagous to creating chess puzzles for yourself and then solving them -- it is a very slow way to discover things you don't know.
There's a whole world full of brilliant ideas out there; far more hacks than anyone has the insight to devise in a lifetime. Learning specific technologies is a necessary evil; read something like A Simple Guide to LaTeX if you think you'll need to use it in the near future. Otherwise ignore it. But read Programming Pearls to get better forever. Read some nice OSS code. Read a book that talks about, not how to use a particular language, but how to use a particular language well. Find some language smart people love, in a paradigm you don't understand, and really embrace what makes it expressive. Not by yourself; engage the community. Read their books. Read their code. These things quickly make you better forever.
Your point about studying code & improving it in isolation is good. The weakest part of the analogy, in my opinion, is that in tactical chess puzzles there's actually a right answer.
On the other hand, if you have a chess puzzle but not its answer, you can still practice recognizing the tactical situation (hung pieces, checks, forks, pins, etc.) That's closer to what I was suggesting, and I still think it's useful: learning the jargon first, and then reading code and taking the time to describe it in terms of that jargon. The purpose isn't to "discover things you don't know", it's to concretely drill and internalize things you do know.
Sometimes you'll think something -- a particular brace style, a naming convention, a commenting convention, a design choice -- will make code better. But when you try it, it doesn't help comprehension or maintainence.
There is no substitute for honestly taking the time to make some code the best you know how, and then being stuck maintaining it for a fussy customer for several months. If you never had the time to do it right, you can deceive yourself about how good it might have been. But if you know you did your best, you have nothing to blame the inevitable mess on but your own abilities.
This is an interesting read. I've gotten a lot of mileage out of learning new and unfamiliar languages (note that "new" rarely means "unfamiliar" since most languages just rehash old concepts). When you have a completely different toolkit to express problems, it forces you to think more, and this makes you into a more flexible programmer. To pursue the game analogy, it's as if learning Go would make you a better chess player. That may be too much of a stretch, but I know of many chess players who have learned Shogi (Japanese chess) to improve their mental flexibility (and also because it's fun; Shogi is an awesome game, better than chess IMO). Back to programming: if you can think about a problem in several different ways (imperative, OO, functional, logic programming) you will have absorbed a lot of "tactics" without realizing it, since every paradigm has its own design patterns. The stuff about good naming conventions etc. is easy. Larger-scale design notions like loose coupling are harder, but when you work in a language like e.g. Haskell where there is no mutable state (except in specially-wrapped subworlds like the IO and ST monads) you get loose coupling forced on you.
I think this is one reason why a book like SICP (http://mitpress.mit.edu/sicp) is so helpful; you have to learn a new language (Scheme) and then learn unfamiliar design patterns applied to larger and larger-scale problems, and along the way you pick up a lot of generally-applicable software engineering knowledge that transcends Scheme.
Another really useful trick is to have to maintain/fix someone else's badly-written code. Nothing teaches good design better than having to fix bad design.
Note, though, that some of what the author calls "tactics" (like loose coupling) actually span the range between tactics and "strategy". Writing pure (referentially-transparent) functions that can't do anything other than transform their inputs deterministically into their outputs is loose coupling on a small scale (tactics). Writing classes which are not highly dependent on specific other classes for their functionality is loose coupling on a large scale (strategy).
Reviewing code with an eye for improvement it is certainly one good way to advance our skills as programmers, but I don't agree that it would be the most effective use of our spare time. The problem is that we would always end up looking at it through the prism of our present knowledge. For example, you could probably write a better XML parser if you were familiar with things like XPath than you could if you only knew how to iterate through all of the nodes.
Instead we should spend our work time critiquing our code, and our free time learning the things that both interest us and have some practical application (reading sites like HN is a good way of gauging this). Some of this learning will naturally involve studying others' code.
Too much blah-blah-blah. There are two completely different cognitive tasks - ability to read a foreign language, and ability to speak. Improving your ability to read doesn't affect your ability to speak. You should train both of them separately.
The ability to read other people's code doesn't help you when you must write your own. You can read, say, tens articles and blog-posts per day, but it doesn't affect your ability to write one. OK, in the long run it does, but only after long practice of writing.
Resume: Reading a book or watching an online-course without doing a home-work or exercises is a waste of a time, because writing (composing) is a completely different cognitive task.
I don't suggest just reading code, I suggest reading code
critically, with an eye to how it can be improved.
You're right that casually reading 10 blog posts doesn't help one's writing. But reading them carefully and critically, trying to concretely identify how the author has crafted the language to support their goals? I believe this absolutely can improve one's writing; indeed, I think it's an important part of improving.
Yes, of course, you still have to knuckle down and do a lot of writing at some point, too :)
In order to learn strategy from specific chess openings, you have to study them in context. Memorizing the Sicilian defense lines doesn't teach you much unless you can study it comparatively with all the other openings and learn how that game developed --- and at that point, you're just using the one opening as a forcing function to learn chess strategy seriously.
But that's not what happens when a junior dev learns yacc. Simply by learning to make yacc do things, the developer is given a vocabulary to express parsing and compilation ideas, in somewhat the same sense as a REPL gives you a tool to learn lisp. Sure, you could stop after learning yacc syntax and adapting the RPN calculator example from the yacc book... but nobody does that.
I think it's exactly the opposite to what this guy wrote. People who can express ideas using yacc are to be preferred to people who can talk about LALR parsing but can't show real practical work. The dev who wrote an AST generator with yacc has had to learn how to juggle a parse tree, how to traverse graphs, and what the stages of evaluating a language are. The chess player who learns Ruy Lopez gains no comparable automatic understanding of chess.
And, for what it's worth: yacc and MP arith --- could you have come up with two worse examples of "shallow" programming technologies? If you're for-reals parsing or dealing with problems that need bignums, you're already a million miles past the people who know only how to copy buffers into file descriptors or marshal queries for database engines.