Disclaimer: This is not an article to teach you a quick hack on how to learn multiple programming languages, but an analysis on its advantages. Soz!
My point is that you may already fit the basic definition of knowing more than one programming language.
For the purpose of this article, I want to extend this definition a little bit to focus on not just knowing but actively seeking to solve problems with more than one programming language.
This is what it's commonly known as being "Programming Language Agnostic".
The idea behind it is that as Software Engineers we are meant to solve the problems we encounter using the best tool for the job. It makes sense if you think about it. Why would you limit yourself to only a few available options?
Before I carry on to explain why this approach is better in my opinion, I want to make a few clarifications:
- There are plenty of scenarios in which expertise and knowing the intrinsic details of a particular technology is the best approach. If you want to build a career as a consultant and target a very specific market for example, it makes sense for you to not look around much.
- Not everyone has the flexibility to choose the programming language they want to work with a lot of times. There are real infrastructure or cost limitations that may prevent you from doing so.
Now, for the rest of you out there, here's the approach I'm talking about.
With the growth in popularity of microservice architectures and cloud hosting, it's easier than ever to have hybrid infrastructures, which allows you to pick different tools to solve the problems at hand.
I'm not entirely sure how many people out there take advantage of this flexibility, but my wild guess would be that most don't fully consider the possibilities of this setup.
What is the solution going to look like if you only know one or two programming languages? As the saying goes "If you only have a hammer, everything looks like a nail".
Let's see how a potential problem solving session might look like in a scenario when we're open minded about picking the best tool for the job, independently of how familiar or comfortable we feel with it.
Suppose you want to build an algorithmic trading application. This app will need to:
- Gather data from different financial APIs in real time.
- Parse, process and store this data.
- Retrieve this data to apply backtesting strategies.
- Run your strategy in real time and trigger alerts for your users to trade.
NOTE: This is just an educational example. The solutions suggested are for illustration purposes and may not be the most optimal.
If you want to have a monolithic application, there's less flexibility around the tools you can use, but if you decide to work in a microservices environment, approaching the problem gives you a lot of options and freedom.
If you are a Python developer for example, or Python is your preferred programming language, you can potentially build this whole application in a Python stack.
Similarly if you're a Java developer, a Ruby developer, a Golang developer etc. You get the point.
But approaching the problem without thinking about the language will let you pick the best one that fits the criteria.
In our little language agnostic world, our problem of gathering the data becomes one that requires a lot of concurrency.
If you hit the APIs sequentially, this will be incredibly slow. So you'll need a tool that's really good at concurrency and parallelism but also allows you to deal with HTTP requests and data manipulation easily.
Perhaps you've heard of Elixir. It is known that this language was built thinking about powerful concurrency, so it makes sense for us to consider it. This is not the only one of course, so keep your options open.
Now, we can perhaps build a small application with Elixir, that leverages the concurrency and hits the APIs with a high number of threads and collects that data for us at regular intervals.
At the same time we're collecting the data, we can either store it right away, or send it down a pipeline for someone else to process it. This will depend on how scalable you want to be.
For now, let's say we send this data down a pipeline using something like Apache Kafka as soon as we've retrieved it. This will reduce the efforts of the API crawler and delegate the storing of the data to someone else.
This is the most passive option of all. You do not need anything with great real time performance, but a language or tool that's really good at data manipulation.
Perhaps Python is a great option here? You can use it to a great extent to read large amounts of data and apply mathematical models and test different strategies with it. Depending on the amount of data you have you can even throw in tools like Apache Spark in the mix to help you out.
Here's where you need a language that is very good with IO operations. You want to be as real time as you can to let your users make the best decisions.
If you design your infrastructure the right way, you can perhaps even read the events from your Kafka queue straight away and send it to the users connecting 2 completely different technologies via the Kafka events queue.
As you can see, at a higher level we can already start including many different programming languages in the mix to build the best possible solution.
You may be wondering now that building that whole stack will require a team of developers, with expertise in different areas and each one specialised in each of those technologies.
But the reality is far from it.
To be able to build hybrid infrastructures like these, you only need to know about the capabilities of a language very well. Of course, you'll have to learn the actual specifics of the language at some point, but for starters the capabilities are more than enough. You can get by with building your solution if you know what's possible and then replace parts conveniently later.
I am particularly bad at remembering things for example, but I routinely work and build apps on top of at least 3 or 4 very different programming languages almost daily. What allows me to do so is a combination of
- Knowing what the language is capable of.
- Always having the documentation at hand. I don't have to remember the exact syntax and methods libraries as long as I can look it up.
- Best practice guides.
- Good understanding of the basic paradigm of the language, is it OO or functional? How far can I push it? How performant is it? At what point does it start to break?
Just like Scott Adams, creator of Dilbert says, you don't have to be a world class expert on any particular one skill, but a combination of many average skills can turn you into someone awesome.
Same applies for programming languages, you don't have to be an expert in one or all of them. For the average Software Engineer, being fairly good in a few will give you far more leverage to build great applications that you imagine.
After you've picked the programming language that best suits your solution, you need to start thinking about implementation.
If you've never used the language you picked, it's better to start by testing a few of the principles you want to exploit first. Interactive shells are great for this purpose and most languages have them.
Another thing to consider is the way you build your application, how far into the future can you see? Even though you've made (or think you've made) the right choice, it won't necessarily continue to be the right choice as time passes.
Perhaps you picked Ruby as your general purpose language because you only needed to get a small amount of data processed and needed a solution fast and simple. This fits your purpose very well, but if you start seeing heavy growth in traffic and Ruby starts getting memory problems, then it's time to consider a replacement to better fit the new scenario.
This will depend on how you've built your system. The best way is to have services (or micro-services) as isolated as possible with a common interface between them.
For example, if you use an HTTP API to exchange JSON messages, or a Kafka queue, you should design your service in a way that the data coming in and going out doesn't get influenced by the programming language underneath.
This way, if your service needs replacing with a completely different programming language, you can basically plug and play without disrupting other dependencies.
Even though you may make an effort of reducing dependencies between your services, you can get away with the better approach of abstracting communication instead, and finding a common efficient way to exchange messages that doesn't depend on the underlying language.
There's no one single solution to every problem, and there's no need to use a single programming language to find that solution.
Learning more than one language gives you the tools to think about possibilities you didn't consider previously.
Limitations of a technology are no longer a limitation. This way, you start looking at programming languages as great tools with pros and shortcomings.
There's almost always going to be a preferred language, particularly for general purpose applications, and that's fine as long as you know when it's ok to use it and its shortcomings, and more importantly, you're willing to pick a better one when it's appropriate to do so.
For more topics, check my profile or visit rarias.dev.