A select few professional domains in the modern world retain the luxury of having a somewhat predictable future. Software development is certainly not one of them. In-demand tech stacks change faster than the Canadian weather. In this context, being a software developer in 2018 is much like being an investor in the stock market. Every skill you decide to pick up is an investment of your time. And with every investment comes risk. If you spend your entire youth mastering MongoDB, you might find yourself out of luck when the next anti-Mongo successor captures the imagination of our ADHD-ridden zeitgeist.
One common approach to mitigating these risks is short-term speculation. You could just jump on the hottest new bandwagon and maximize your marginal output while you can. This strategy mandates that you develop no real relationship with what you learn. If something can't be covered in a 12-hour long online course that takes you from 0 to 'professional', it doesn't fit your game-plan. Another novel approach that I come across occasionally involves the following steps: become an absolute master at some archaic and/or esoteric framework/language/technology, find others who made the exact same decision as you, participate in an intellectual circle-jerk and look disdainfully upon anything mainstream. After all, once you know what 'monads' are, you can quite easily dismantle the egos of most interviewers asking you about the latest JS framework they discovered.
How can this be achieved? I am not sure but I have a read-worthy theory. About two years ago I read this book called 'Millionaire Teacher' by Andrew Hallam. Hallam introduced me to the concept of a 'Couch Potato Portfolio' which relies heavily on investing in 'index funds' - a class of funds that exposes your capital to an entire market rather than any particular stocks. It seems to be common financial wisdom that most couch potato investors will outperform most stock pickers (even the experts) given long enough time horizons (usually a few decades). This got me thinking...if all the tools and technologies in the software ecosystem could be considered as part of a 'skill market', what would be the index funds of this market?
What a juicy question! Perfect for a philosophical dialectic. In the following paragraphs I'll present to you my answer as a list, but I encourage you to add to (or subtract from) this list at your discretion. To identify the index funds, we must first identify the market index. In our case, that would encompass every programming language in use, every framework, every library, every programming paradigm...basically, anything that converts 1s and 0s to paycheques. While this index could be comparable to a global market index, not every index fund needs to track the global market index (for example, there are country-specific index funds). Here you need to make the practical decision of how narrow your scope can be. Personally, I don't think I will ever need to work directly with the C language or anything further down the stack (god forbid). Also, while I revere functional programming, I don't have any real experience with it and make the assumption that I am somewhat safe in OOP (object-oriented programming) territory for the foreseeable future. Keeping these caveats in mind, I was left with the challenge of identifying a set of skills that are:
Language Agnostic (personally, I am only concerned with high-level languages)
Platform Agnostic (by platform I mean web, mobile, blockchain, carrier pigeons etc.)
Hype Tolerant (this includes its ability to survive both during and after a period of hype)
Timeless (at least in the context of a developer's career)
After thinking long and hard about this problem, I narrowed it down to 3 skills, which I now consider to encompass the index funds of my technical career...
II. Distributed Systems
Humans love 'scale'. I would consider this a truism. If you are (or hope to become) a software developer, it is rather unlikely that you will spend your whole career working on software deployed on a single server. And the moment you cross this threshold, you will discover a whole class of mind-bending problems that make your code a lot less predictable. This is where an understanding of distributed systems can be invaluable. In my opinion, the ability to tame a distributed system is one of the key differences between a junior and a senior developer. Most problems in distributed systems are very hard to simulate unless you have a lot of disposable income or are just really good at building Raspberry Pi clusters.
While this subject is best learned on the job, it may be wise to supplement your real-world experience with some theoretical depth. There are two books I would highly recommend on this subject: 'Scalability Rules: 50 Principles for Scaling Web Sites' and 'Designing Data-Intensive Applications'. Both books presuppose that you have prior experience with building software. The former is a bit more focused on web applications while the latter on data systems. The beauty of this subject is that a lot of the theoretical depth in both books can be applied to all software domains. Personally, the second book is one of my all-time favorites and has helped me a great deal in my career.
III. Design Patterns
Design patterns are a questionable entry to this list. As per Wikipedia, 'a software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design'. While this sounds like a good fit for our list, there is an important caveat - object-oriented patterns do not translate well to functional languages and vice versa. These two paradigms are so fundamentally different that it is very hard to generalize patterns for both. While functional languages usually do not support mutable state, inheritance etc., object-oriented software relies on all of this but is often unable to play nice with functional staples like recursion.
Having said that, I decided to add design patterns to this list anyway for two reasons. Firstly, the patterns themselves may be fundamentally different for the two aforementioned paradigms, but the idea of thinking about your software in terms of design patterns is of critical importance. While a sound knowledge of algorithms and data structures will help you overcome the problems of logical complexity, they will not help much with code complexity. This is where the ability to identify use-cases for appropriate design patterns can help you write code that is cleaner, easier to maintain and universally comprehensible. Moreover, it helps you keep the big picture in mind when building software systems. Secondly, I personally find that learning object-oriented patterns is a broad enough net to cast. Not only that, the multiplier effect that learning these patterns have on your OOP abilities is well worth the compromise.
Since my knowledge of functional programming is very limited, I don't want to recommend any resource for learning functional design patterns. However, this Quora discussion seems to be an interesting place to start. As for object-oriented patterns, the ultimate go-to book might be 'Design Patterns: Elements of Reusable Object-Oriented Software' by the famous 'Gang of Four'. Last year, I asserted my own notes on the subject which can be found in a Github repository titled Python Design Patterns. Do note that even within OOP languages, not all patterns remain the same, but there is enough similarity that it is usually sufficient to learn the fundamental patterns in your favorite language and just use your common sense when implementing them in a different language.
While the three aforementioned skillsets scratched my dialectical itch, I want to emphasize that this is not a doctrine. I hope that you will not become dogmatic in your interpretations of an internet-dwelling stranger's eloquent ruminations. If you want to specialize in building embedded systems, my list would probably require a whole lot of tweaking to fit your needs. On the other hand, if you are just trying to get your foot in the door and time is of the essence, your short term questions about which language/framework/stack could get you a job in the coming months should definitely take precedence over such long term strategies (index funds aren't advisable if you need your capital tomorrow). Lastly and most importantly, if your career is just a byproduct of your passion and love for programming, I salute you and hope that you never need such lists. For the rest of us who are trying to survive wave after wave of celebrated disruption, I am simply prodding you to ask yourself this question - what are the index funds of your career?