HomeNews and blogs hub

Programming language evolution and sustainable software

Bookmark this page Bookmarked

Programming language evolution and sustainable software

Author(s)
Dominic Orchard

Dominic Orchard

SSI fellow

Posted on 6 June 2016

Estimated read time: 5 min
Sections in this article
Share on blog/article:
Twitter LinkedIn

Programming language evolution and sustainable software

Posted by s.aragon on 6 June 2016 - 2:34pm

By Dominic Orchard, Research Associate, Digital Technology Group and Cambridge Programming Research Group, Computer Laboratory, University of Cambridge and Software Sustainability Institute Fellow.

Much like natural languages, programming languages evolve over time: a new feature is added, an existing feature is removed or modified, ambiguous parts of a specification are made clear, and so on. These evolutionary changes may be due to external factors such as new hardware, new theory or foundational research, trends or fashions in languages, and applications; internal factors such as deficiencies in a language, problems with existing features; or feedback from a community of users.

While the aim of evolution is to provide more effective languages, evolutionary changes frequently undermine the long-term sustainability of software. A change to the semantics of an existing language feature, or the removal of a feature altogether, is likely to modify the behaviour of some existing programs; other existing programs may not be compilable anymore. Therefore, an unmaintained piece of code might become increasingly unstable and unusable. Language evolution is one of the main contributors to "bit rot"— the gradual degradation of code usability over time.

What can developers do to mitigate these inevitable changes? How do language designers evaluate the impact of evolution? What can designers do to aid developers? These questions were the focus of the Programming Language Evolution (PLE) series of workshops hosted at European Conference on Object-Oriented Programming (ECOOP) in 2014 (5th to 10th July) and 2015 (28th July to 1st August).

Every year, the workshop brings language designers and developers together to address challenges with language evolution and to report on recent research.  In 2014, Martin Odersky, the creator of the Scala language, gave a keynote on "The Evolution of Scala." In 2015, Bjarne Stroustrup, the creator of C++, gave a keynote on "What, if anything, have we learned from C++?" taking a retrospective look at the history of C++.  The 2015 edition of the workshop was supported by the Software Sustainability Institute, whose aim and long-term values of software used in research are closely linked to those of the PLE community.

So what can developers do now to mitigate potential problems caused by language evolution? These are my top three tips:

1) Use refactoring tools

Non-purely additive changes to a language will probably cause software maintenance issues. One way to mitigate these changes is via refactoring tools which allow software to "co-evolve" alongside a language. Refactorings might replace deprecated features or mapping code for new programming idioms, sometimes embedded into IDEs or provided as external tools. For Fortran, there are some tools to remove deprecated language features that are known to be error-prone (see Photran, CamFort).

2) Leverage verification techniques

By providing a suite of tests for your code, the intended behaviour of the program can be captured and compared. These tests can expose semantic changes introduced by language evolution and guide how to fix the software accordingly. Extensive unit tests can help to localise the error, while integration tests (over a wider scale) might capture more subtle changes hidden on a smaller scale.

Similarly, specification systems and automated verification tools, if available for your language, allow you to capture the intended program behaviour and check whether it behaves in a certain way.  Automated verification techniques can take less effort than writing tests by hand, once the technique/tool has been learned. As a middle ground, automated test generation systems like Quickcheck may be available for your language.

3) Dependency management

Evolutionary problems are amplified in the presence of library dependencies. To mitigate these issues, you should specify which versions of libraries, languages, and compilers were used to develop and test the software via some build systems, where one can include language and library versions; documentation should also be provided. All of this allows future users/developers to replicate the original software context and work upwards in language and library versions to find the source of any evolutionary impact. Container systems (like Docker) can also be used to capture the entire development context for future replication.

Language evolution will always be a problem, especially in new languages that tend to change more rapidly, but with care and following the above three techniques, a lot of the difficulties can be effectively managed.  Research continues (e.g. SLE) into how language designers can understand and evaluate the potential impact of language changes, how effective and correct refactoring tools can be built, and into new automated verification techniques to aid correctness and software maintenance.

Image: Genealogical Tree of Programming Languages by JohnManuel - JMK CC BY SA 2.5.

.

Share on blog/article:
Twitter LinkedIn