

Tactics, tactics, tactics - dlowe
http://dlowe-wfh.blogspot.com/2007/06/tactics-tactics-tactics.html

======
tptacek
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.

~~~
jerf
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.

------
pauldirac137
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).

------
Dove
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.

~~~
dlowe
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.

~~~
Dove
Ah! Then I agree, practice is essential.

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.

------
rmorrison
If anybody is interested in honing their Chess Tactics skills, I highly
recommend: <http://chess.emrald.net/>

It's quick and easy to setup an account, and presents you chess puzzles based
on your skill level.

------
kevinskii
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.

------
jderick
I find most the real problems I encounter in my programming job have little to
do with code at all.

------
th1b
Apart from a few minor nits (bad analogies) this is one of the very few
articles I've read on "programming" that I didn't feel stupider after reading.

Reading code this way is the only way to get better after you clear the
initial learning curve.

------
c00p3r
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.

~~~
dlowe
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 :)

