A stack of techical books

"There's No Silver Bullet"

We believe in methods that amplify learning, communication and collaborative teamwork. Methods that help us do our job better and faster.

In this section our experts share their insights and experience.

Articles

Reaktor Twitter

Choosing a Programming Language

Java has for long been one of the most common programming languages used in information system implementation. However, it is usually a good idea to use many different tools in the implementation of a complex system.

In this article, I present a group of modern programming languages as alternatives to Java. I will also explain why it makes sense to not commit to one programming language for the entire implementation of the system, and for what purposes the alternative languages are best suited for.

Choose the programming language best suited for the purpose

Programming language design is about finding a balance between general usability and special needs: A general purpose programming language can be applied to a wide range of problems, but implementing the solution is easier if the language is designed for that particular problem. The more complex the problem is, the more significant the suitability of the programming language for the problem becomes.

The length of the program code significantly affects the quality of a program. A short program is often easier to understand, implement, and expand, and it has fewer errors.

Program length, on the other hand, is affected by the abstraction level of the programming language, which defines how computer details are presented to the user of the language in a simplified way.

Generally, low abstraction level languages give more control to the programmer but require more programming than high abstraction level languages. On the other hand, programming languages allow programmable abstractions that model the problem that needs to be solved. The more flexible the language, the more extensive models of parts of the solution can be made.

Clear abstractions with functional programming

As programs become more and more complex, they require an even higher abstraction level in order to model solutions in a reasonable amount of code. The functional programming paradigm has been found to be a good way to write clearly structured code. Programs are then composed by combining small independent parts – functions. Because the side effects of functions are limited and functions can be combined in multiple ways, functions are reusable.1

Except for Java, most modern programming languages either fully or partly support the functional programming paradigm. In this respect, Java has not kept up with other programming languages.

However, the Java Virtual Machine (JVM), built to execute compiled Java byte code, and the Java ecosystem with its many libraries are still highly valued. The runtime environment of many new programming languages is based on the JVM: It is not worth re-inventing a virtual machine that works well. In addition, this enables the use of Java libraries from the new language.

Examples of modern programming languages

The most significant feature of Scala is the way it combines functional programming and object-oriented programming. Scala's highly developed type system checks the structure of the program during compilation. In addition, Scala includes versatile tools for developing a DSL (Domain Specific Language) that is tailored for a specific problem domain. When using a DSL, the abstraction level is very close to writing in natural languages.

Scala is suitable for the same purposes as Java, such as performance-critical systems. Experienced Java programmers find it easy to start programming in Scala, because the advanced features of the language do not need to be used immediately. Scala is built on the JVM, and calling Java libraries from Scala code and vice versa is easy.

Clojure is also a functional language that runs on the JVM. However, Clojure is a dialect of Lisp, which essentially defines the features of the language: It has a simple, list based syntax, which represents the whole program. Repeated code structures are abstracted with a versatile macro system, which translates the list structure of the program during compilation.

Clojure offers mechanisms for supporting several different concurrent programming styles. Clojure does not have a separate compilation phase to run the program, but while reading the source code, the Clojure interpreter compiles it to a byte code that the JVM understands. Because of its Lisp ancestry, Clojure is a highly expressive and flexible language, but using it efficiently requires a lot of studying. Like Scala, Clojure code can also use Java libraries, and vice versa.

Ruby has picked its object-oriented model from the Smalltalk language and functional features from Lisp. Developing DSLs inside the program is easy with Ruby's dynamic type system. In addition to web applications, Ruby is also well suited for Unix programming, due to its system call layer and extensive collection of libraries. As a program written with Ruby is not compiled, the development and test cycle during implementation is very quick. On the other hand, the runtime performance of a Ruby program is worse than the performance of a similar program written with a compiled language. There are many different implementations of the runtime, and one of them, JRuby, is based on the JVM.

Erlang is designed for fault tolerant distributed systems with high requirements for parallel execution. In terms of syntax structure, Erlang is a simple functional language, which like Scala and Clojure also avoids side effects. But Erlang's real stake is in its light process model and message passing paradigm. Erlang also offers process monitoring and distribution included in the implementation of its virtual machine. In addition, Erlang's standard library OTP (Open Telecom Platform) includes several solutions to the needs of distributed systems. Erlang is well suited for background components of complicated systems, to take care of message passing or persistence, for example.

Our last example here is JavaScript. My reasons for including it in this article are most peculiar: JavaScript is the only programming language widely supported by web browsers. As web browsers evolve and become faster and faster, the programming of web applications is also moving from servers into the browser. The application is then divided into a front end and a back end that are connected by an interface. The front end is programmed with JavaScript to be run on the browser, and the back end, which is the server, is programmed independently of the front end.

JavaScript is a functional programming language with C language syntax familiar from Java, and a prototype-based object model. JavaScript, CSS and HTML provide an open alternative to closed tools for developing web application user interfaces. They are based on standards and support test automation.

Use the right tools for the different parts of the system

All of the programming languages described above can be considered modern, even though only Scala and Clojure are new. The active communities around the languages are further developing the languages, and as functional programming has become more popular, the languages have also gained new supporters.

A carpenter uses many different tools to complete his work, because one tool is not good for all tasks. This is how it should be in software development, too. A modern information system is often so complicated that one language is not suitable for implementing all parts of the system. Each part should be implemented with a language that is most suitable for it.2 An appropriate language solves problems more naturally and with less code than a less suited language. In the end, the quality of the code written affects the quality of the entire information system.

Tuomas Kareinen closeup

Tuomas Kareinen, Software Developer

Tuomas is a pragmatic programmer and an active open source developer. He has contributed to several projects within the Ruby community.


  1. The functional programming paradigm
    In the functional programming paradigm, composable higher order functions and immutability enable the modularity of the code. The code then gains referential transparency, meaning that a specific function with a specific input always returns the same value regardless of the state of the program.
  2. Polyglot programming
    Using several programming languages in implementing one system is called polyglot programming. Even though it has been possible to apply polyglot programming in integrations between systems, for example, implementing each part of a system with the language that is best suited for it has become possible only as languages using a common runtime environment (such as the JVM) have emerged.