The more experience I gain as a software developer, the more often I wonder why one or another technology was chosen as a backbone for a new project. Due to the fact that microservices architecture is quite popular nowadays, I’ve had a chance to get to know (in general terms and usually read-only mode) quite a few new to me programming languages. And while at the beginning I firmly believed that each technology chosen for one or another microservice contains in its foundation research and rational reasons, slowly I’ve come to a realization that in the most cases it’s not true.
Unfortunately, the decision making usually looks like this:
- We have to build a new safe, fault tolerant, encrypted and distributed file storage. Let’s think which technology we’re going to pick.
- At the moment we have only JS developers available.
- NodeJS it is.
Or here’s another kind of discussion:
- We just received an RFP to build an eCommerce mobile app. What’s our move?
- According to The Internet, Golang is hot right now.
- Ok, I’m writing this down to our proposal.
Usually, the two main underlying factors are available human resources and hype for a particular technology, which by the way, are closely linked entities. And it makes sense, let’s say your project involves concurrency and math at a big scale and Clojure looks like a good fit for this, but it’s going to be near impossible to find experienced engineers in reasonable terms who are willing to join your team.
As we’re mostly talking about general purpose programming languages, they are just tools, which can be used by developers to build whatever they want. It’s not critically important Java or Python is used for a blog app, they can be substituted with one another without any noticeable difference for an end user. You can even build your ML system using PHP exclusively, it’s only a question of efforts you’re willing to spend on it. And efforts of other people who’re going to support it later.
Sometimes it happens that some architectors and team leads have a spine to admit they made a mistake and also have available resources to fix it. Not to be unfounded, over the past few months I’ve been a part of a team rewriting a small web service from Golang to Ruby. Ruby happened to suit better for the tasks this web service aims to solve, despite all the popularity of Go and ready-to-commit Go-engineers, it was tough to work with branched and tangled business logic written in procedural Go-style with thousand-lines of repeatable if-else blocks. And at the same time performance isn’t an issue for this particular service, it’s a part of an internal corporate system, and is going to receive 20–50 RPM at max at rush hour.
Another example is former VP of the Platform Engineering group at Twitter Raffi Krikorian, stated he would not have chosen Scala in 2011 due to its learning curve. It’s a touchy subject, as in the one hand Scala and new architecture helped to gain a performance boost from 200–300 RPS per host to around 10,000–20,000 RPS per host, so it solved the assigned task well. In the other hand (I can only assume), it has become harder to understand and support twisted business logic rules and algorithms written in FP-like style.
Some might say that all the troubles in the support of entangled Scala/Clojure/Erlang/etc apps are just a question of insufficient engineers qualification and often there’s a space to improve the codebase and simplify the support by applying design patterns rationally. Or… maybe the language wasn’t the perfect fit, who knows.
Nowadays the range of available programming languages is wide as never and I’m going to make a quick overview of some of them with my amateurish and naive ideas about what each of them is good for.
A quick list of the languages I’m going to review: Elixir, Erlang, Ruby, Java, Python, Go, C#, C++, F#, JS, Kotlin, Rust, Julia, Scala, Clojure, PHP, Swift, Pony. These are the ones that happened to get my attention at some point over the past 7 years. I do not have any practical experience with most of them (hehe), but I follow the news and I’m just generally curious about programming trends. If you’ll notice any inaccuracies or have any suggestions/feedback please let me know here in comments or on twitter.
Erlang was originally designed for telephone system communication. Yet it can be applied anywhere where key features are concurrency, reliability, fault tolerance, and distribution. It can be a good choice for online games (e.g. MMORPG servers), databases (e.g. CouchDB, Cloudant), sports entertainment systems, online communication systems (e.g. WhatsApp), media distribution applications.
Downsides: poor GC performance, a steep learning curve, poor syntax (though it’s subjective criteria), feels like only a few rare developers are interested in it today. Here’s a detailed article about downsides from Tony Arcieri (2011, but still valid).
Elixir is built on a top of Erlang and is basically the same tool, but with better syntax and much more interest from the developers' community. The best use cases are the same as for Erlang, simply put: fast message send/receive between clustered servers.
Downsides are also the same as for Erlang, except for the syntax. Requires BEAM VM. A developer still needs to know Erlang and OTP, as it uses lots of Erlang libraries.
Good old Java is the most popular programming language worldwide. Not sure what language suits best for your application? Pick Java and most likely it’ll work well for you. Although it can fit almost anywhere, I would prefer Java for all cases where BigData is involved (e.g. Hadoop, Cassandra).
Downsides: it’s absolutely perfect, no downsides (jk). The language is too verbose, developers have to write too much code which slows down the development process. A relatively large memory footprint. Oracle plans to introduce a paid commercial use license for Java SE 8.
C# is an old Java rival and is similar even in terms of syntax. C# is a good choice if you’re developing an app for Windows and optionally if it involves integration with any other Microsoft products. And it plays well with game development, of course (e.g. Unity), as well as mobile development (Xamarin).
Downsides: the language is too verbose. Requires .NET platform (not sure if people are actually using Mono and if .Net Core is mature enough in the context of cross-platform development).
The language is built on top of Java and uses JVM, so can use dozens of ready Java packages. The syntax is cleaner than Java’s. I’d pick Scala to work with BigData. Also, Scala’s Akka toolkit worths attention, it’s designed for building concurrent, distributed, and resilient message-driven applications (basically, it works for any JVM based language, but obviously Scala developers have an advantage when checking source code).
Downsides: a noticeably long compilation time, a steep learning curve. A relatively small developers pool. Crippled multiple constructors being inline in the class body can freak people out.
This is a modern LISP. Works on JVM (not sure if CLR version is still supported). Powerful macros and metaprogramming. This a good tool for building non-trivial data analysis products, linters, and IDEs (e.g. LightTable).
Downsides: it uses too much parenthesis. Very poor readability, some people say Clojure is write-only language. A steep learning curve.
One more popular JVM-based language. Has a cleaner syntax than Java do. Conceptually wise it looks like a compromise between Java and Scala. Android platform officially supports Kotlin. Although initially this language was not conceived for mobile development exclusively, now basically it is. Currently, it’s a top peak for mobile development for Android.
Downsides: doesn’t bring any new concepts (which weren’t already introduced by Java or Scala), it’s more like a refreshment for bored Java developers.
Ruby declares developers happiness as its main purpose. Has a clean readable syntax and sane object model, which helps to achieve relatively rapid development. Since Rails onset, Ruby is perceived as a mainly web-focused tool. It’s a good choice for all non-trivial web applications and for fast prototyping, where high performance is not essential (e.g. Airbnb, GitHub).
Downsides: relatively slow, the most used implementation (MRI) is single-threaded, poor GC performance.
It’s a variation of ML, brought up by OCaml and bound to Microsoft. F# was created to bring functional programming to .NET. It’s usually considered a good choice for science programming and modeling (e.g. XBox Live analysis of game logs).
Downsides: a relatively small developers pool. F# has poor support for web programming out of the box. A small number of open source libraries. Requires .NET platform.
Two words: Machine Learning. Python has clean syntax and bindings for almost all main data science and machine learning libraries. The language is also widely taught in universities and is often used for scripting and web. Python is a top pick for recommendation systems, visual/sound recognition, data visualization, and scientific scripts (e.g. SciPy, NumPy).
Downsides: Python is relatively slow, memory consumption is high, it’s single-threaded. Also, the community is divided by an opposition between Python 2 and Python 3.
PHP is a programming language made specifically for the web. It has a lot of toolkits for creating and customizing blog/e-commerce applications in a few clicks (e.g. WordPress, Joomla, Drupal, Magento). PHP is a good choice for building trivial web applications like personal home pages (hehe) or online shops which require minimal customizations.
Downsides: relatively slow, single-threaded, requires C extensions to be installed globally to the PHP executable. It’s not trendy and gets very small interest from a community, though a developer pool is still relatively big.
Golang was originally created for efficient work with multi-core computers and concurrent programming. No VM, fast compilation, easy to learn. A lot of developers are generally interested to try it out. Go suits best for system and DevOps works. (e.g. Docker, Kubernetes).
Downsides: it is too imperative. Error handling concept is rather questionable. A relatively small amount of ready-to-use packages.
Rust is supposed to become a new C. It’s ambitious, but we’ll see how’s it going to turn out. Rust design allows to create programs that have the performance and control of a low-level language, but with the powerful abstractions of a high-level language. It is suitable for high-performance servers, operating system modules, command line utilities (e.g. several components of the Dropbox core file-storage system).
Downsides: a steep learning curve. Rust is very explicit and verbose, feels overwhelming for beginners. A relatively small developers pool and a small number of ready-to-use libraries.
Julia was originally designed to address the needs of high-performance numerical analysis and computational science. It’s fast and has a clean syntax. LISP-like macros and powerful metaprogramming facilities. Key features are distributed parallel execution, numerical accuracy, and diverse mathematical libraries. Julia is great for numerical analysis software and data science. It’s Python’s rival and hopes to overtake it one day in the machine learning field. (e.g. researchers use Julia on a NERSC supercomputer, MIT roboticists program robots in Julia). Looks promising.
Downsides: Julia arrays are 1-indexed. It has not a lot of libraries yet and a relatively small developers pool.
Downsides: the language isn’t stable yet and does not have backward-compatibility, meaning painful upgrades for each new version.
Downsides: although much work is being done in this direction, JS is still relatively slow.
C++ is old but still cool. It was very widely considered the standard language to use if a programmer wants to have a program that runs well. It’s fast and powerful. It’d pick C++when speed and memory consumption are essential, like graphics video games (e.g. UnrealEngine), graphics editors (e.g. Photoshop), CAD systems (e.g. AutoCAD).
Downsides: the language is verbose, complex, has manual memory management, and steep learning curve. A lot of people consider it a legacy programming language.
Pony is a fresh Erlang/Elixir competitor. The core idea is that the data does not necessarily have to be fully immutable to build a truly concurrent environment. It’s fast, safe, and requires relatively little memory. Pony is good for large event-driven applications.
Downsides: complexity. Ponylang is very new and immature. Not a lot of libraries are available yet, it has a small developers pool.
The conclusion is the mission I’ll leave to my reader.
Happy coding in 2019!