Przejdź do głównej zawartości

A reflection on the future of programming languages

I started my first job as a programmer in 2000, a year before I got Master's degree in Computer Science. At that time, a recurring question that was asked by students and graduates was:

Which language should I learn in order to be successful on the market?

It seems like this question is universal and has always been asked, in some cases inquiring about a programming language, another time on a library or a framework.

So, will learning Java pay off better than C++? Does it even make sense to learn C these days? Or will mastering the Java Servlet Pages position one better on the market than learning PHP?

The simple and provocative answer is: it does not matter.

The longer answer is really the rest of this post, so if you are interested, read on.

An interesting phenomenon in the history of software is that many great libraries and products have been created by individuals or, at most, tiny groups of people. Consider these examples - if any of the products seems unfamiliar, read about it on Wikipedia.

Chipmunk                 ---------          Scott Lembcke
jQuery Form Plugin       ---------          Mike Alsup
Clojure                  ---------          Rich Hickey
FileZilla                ---------          Tim Kosse
Python                   ---------          Guido van Rossum
web2py                   ---------          Massimo Di Pierro
PHP                      ---------          Rasmus Lerdorf
Emacs                    ---------          Richard Stallman and Guy Steele
Gtk                      ---------          Spencer Kimball and Peter Mattis
JUnit                    ---------          Erich Gamma and Kent Beck

We all use these daily to test, develop and deliver software. Sometimes they become part of our products. They have not initially been written by an large team or open source community and that fact is not without meaning in terms of programming language that the authors used. This statement is going to be a bit speculative on my part, but I imagine the authors have not had terrible doubts in terms of which language to choose and why. Working alone or with just two colleagues they could decide on the language based on their own preference. It was only later that developers from open source community joined these projects, also based on their preference of language and domain.

Now, speaking between us, the humble programmers, we have to face the fact that very few of us (< 90%) will be next Rossums and next Becks. We will use the excellent works of others and integrate them into a working products using languages that happen to have bindings to these libraries. Therefore, the choice of the language, in a particular situation, will depend very strongly on the availability of library bindings and then secondly on current fashion, our legacy code base and other factors. This means we must be able to write clean code in at least a handful of languages for which there is really good library choice. We have to acccept this variety and work towards mastering our coding skills, rather than towards mastering one given language.

If there is a very good, stable library already available, written, say, in C, there will likely be at least a couple of bindings created for languages other than C. Re-writing this 10-year old library from scratch in "pure X language" would most often be impractical and too costly to undertake. The library itself may well outlive some languages and the new ones that will pop up in the future will create their own bindings for it. It may even outlive the language it is itself written in, in the sense that the library is widely used, although the language disappeared from the mainstream long ago.

Of course it is not completely true that the widely used libraries are never created from scratch in more than one language. Take SNMP for example - we have at least two different implementations (not bindings), namely net-snmp written in C and snmp4j - in Java. For that matter, Java has demonstrated something that I strongly doubt we will ever witness again - the proliferation of pure Java libraries for almost everything we already had had C/C++ libraries in place. But today, these Java libraries are also being used from within newer languages like Scala or Clojure. These new languages also create their bindings, taking advantage of the JVM, instead of re-implementing all Java heritage from scratch.

With all that said, I think we should not treat the discussions like "Is Scala better than Java" or "Why C++ is not truly object oriented language" too seriously. Some languages are definitely more expressive than others and some support given programming paradigms better than others, but from the point of view of delivering what the customer needs quickly, these features are less important than the availability of libraries and frameworks.

We can hear from time to time the statement that our software industry is young, compared to other industries like automotive, for example. That's true and this is a very important observation, in my opinion. I believe in the next few tens of years, as the industry matures, some of the well-established libraries will settle for good, just like tools and techniques used to produce cars had settled in automotive industry. If we are tasked with developing some new functionality, we will know there are, let's say, two libraries and four languages that we can use exactly for that purpose. And we will use them. For a majority of customer requirements, the library choices will be as obvious, as today is mounting an ABS module in a car in order to provide the required safety level during braking.


Popularne posty z tego bloga

Unit Testing code with IO file operations (in Python)

We may often come across a piece of code that was written without Unit Tests at all. In addition, the piece of code may be dealing with IO like file writing and reading, which makes it more difficult to Unit Test it when we are trying to refactor and modify. Let's suppose the code in question looks like this:

def writeInitialsToFile(filename, name, surname):
    initials = name[0] + '.' + surname[0] + '.'
    with open(filename, 'w') as file:

def readInitials(filename):
    initials = None
    with open(filename, 'r') as file:
        initials = file.readline()
    return initials

A straightforward and bad idea would be to write a couple of Unit Tests that make use of a real file and simply test the reading and writing. Is therea a better way to test this code?

First of all, we need a way to replace the real file with something else. For both reading and writing we will now have a couple of functions, one that expects a stream fo…

Piotr's Less Obvious Advice on Google Mock: State maintenance

Google Mock provides several ways to maintain state inside mock objects. One way of implementing state maintenance is with SaveArg. Consider the following example.

We have a class Configurator, which allows a caller to set and get values of a parameter:

class Configurator

    virtual ~Configurator() {}

    virtual void setParamX(int n) = 0;
    virtual int getParamX() = 0;

And we have a class Client that calls Configurator's methods and it also has a method incParamXBy, that can be used to increase the current value of paramX by a certain value.

class Client

    Client(Configurator & cfg);
    virtual ~Client() {}

    void setParamX(int n);
    void incParamXBy(int n);
    int getParamX();


    Configurator & _cfg;

incParamXBy internally calls setParamX and getParamX on Configurator:

void Client::incParamXBy(int n)
    _cfg.setParamX(_cfg.getParamX() + n);

Let's assume that the initial value of paramX is A and that we want to increase paramX by…

Piotr's Less Obvious Advice on Google Mock: Returning new objects from a mock

Google Mock provides a way to return newly created objects from a mock method. Suppose we have a  Generator class that is supposed to generate new objects when createNewRecord method is called:

class Generator
    virtual ~Generator() {}
    virtual Record * createNewRecord() = 0;

...and suppose we want to mock this class:

class MockGenerator : public Generator
    MOCK_METHOD0(createNewRecord, Record * ());

Suppose the caller class Client has run method defined as follows:

void Client::run()
    for(int i = 0; i < 3; i++)
        rec_tab[i] = gen.createNewRecord();

We want the mock to return a pointer to a new object each time createNewRecord is called. This is how we can express this in the test code:

TEST(ClientTest, CanRun)
    MockGenerator gen;
    Client c(gen);

    EXPECT_CALL(gen, createNewRecord())
                 //this is equivalent of returning new Record(1,2,3)