A common recommendation in our profession is to learn a new language each year. This advice can truly be sold only to people starting out in software development, rather than practiced hands. Unless you're a language junkie, this is advice that cannot be followed because languages take more than a year to learn well (that is, far beyond simple exposure and noodling with small projects).
- The People Problem: Cyber Threats Aren't Just a Technology Challenge
- Coding to standards and quality: supply-chain application development
- Intrusion Prevention Systems: What to Look for in a Solution
- Asset Management For Electronics Industry
A language doesn't really begin to expose its strengths and weaknesses until you write programs of several thousand lines. That's the point where you recognize that a feature that looked appealing is now an encumbrance and another feature that seemed pointless is truly valuable. This insight is equally true of the principal tools in the language's ecosystem, most especially the debugger and the build tools. The former is particularly important, because errors are expressed in radically disjoint ways in different languages.
There is another stage beyond this level, which is writing idiomatically in the language, rather than taking our native coding style into the new world. This last step is particularly difficult. I'm speaking here conceptually, rather than syntactically. Each language uniquely expresses fundamental concepts that it favors. For example, Go, which we've discussed extensively during the last 12 months, does not use object orientation in the usual way, rather it favors composability. Composability requires a whole different approach to building programs from objects. It forces newbies to rethink how OO works and how to represent programs as objects. If you stop short of learning composability in Go, and simply learn the syntactic equivalents of operations you already know, then you've lost most of the benefit of the "learn a new language" dictum. This is where the real value accrues. Build some multi-KLOC programs using composability and there is no doubt you will write different code when you return to C++ or Java.
This underscores a key point: To maximize the value of learning a new language, it's important to choose one that is significantly different from the ones you know: for example, learning a functional language if your natural home is OO; learning OO if your natural home is imperative; and so on.
After choosing a language that sparks your interest, it's important to avoid the path of least resistance, which goes something like this: Buying a tutorial. Going through the first 150 pages and learning the syntax plus a few handy concepts. Putting the book down and starting to work on a small sample project. And then looking up items on an ad hoc basis when you need them later. The slip is in not finishing the tutorial. As a result, you pick up only the simple things that you need immediately and lose all the advanced topics.
Have you really learned Java if you've not explored reflection, serialization, or, say, class loaders? I submit you probably haven't. And unfortunately for many of us (me included), we learn the subset that is predominantly needed by daily work. Why learn reflection if I don't need reflection in my work? The answer is clear: If you don't know reflection, you will never spot the opportunities where it will best solve a problem. (I don't want to stray too far off topic, but this is the benefit of reading other people's code. Good developers use the entire palette of features of a language, so reading their code illuminates instances where an elegant solution is possible via a little advanced feature you might not have known about.)
The bottom line is that learning a new language is both a long effort and a deeply rewarding one. I don't believe that a language can be mastered at the rate of one a year, so I view the recommendation to do this as pie-in-the-sky silliness, rather than a worthy goal. A much better path, in my view, is to learn several rather different languages well. And then cultivate and maintain the central ones you need by making sure you stay up with advances in the language and reading the code of other, better developers.