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