There are several thousand programming languages in the world. Even though many of them are incredibly unpopular, very specific, or have been created a long time ago, they still exist, and new languages continue to appear. It seems that there is no reason to believe that the number of languages will ever begin to decrease and that ultimately one universal programming language will emerge. The vast number of programming languages can frighten, but this very diversity allows us to move to a new level of multilingual project implementation. The article presents the idea of multilingual projects, which will enable developers not only to navigate in a variety of languages but also to see the benefits of their joint use.
The Emergence of New Programming Languages and Frameworks
There is no programming language created so far that would equally well solve all the problems of software systems. A large number of languages already exist, and new ones continue to appear. Obsolete languages are still in use to write programs, and they continue to work, which means that they need specialists to support and develop existing applications. You may not need to rely on obsolete or not widely spread languages, but, for example, if you suddenly decide to get a programmer job at Boeing, you will have to learn a language that was quite progressive for its time and is not very common today, i.e., the Ada.
Today programming languages may be classified this way:
- Old ones: Fortran, Cobol, PL\I, Basic, Pascal, Ada, Lisp, …
- New and future: Go, Swift, Hack, Rust, Kotlin, Scala, …
- Niche: D, Clojure, OCaml, Haskell, …
- Need to get rid of the archaic heritage of the “old” languages
- Inconsistency of existing programming languages with new tasks and increased requirements
- Insufficiency of the abstraction level in existing languages for the tasks complexity level
- Desire to maintain control over the evolution of language
- For teaching or testing the theory of languages in practice
- Marketing (Visual J#)
- The enthusiasm of individual developers
However, language cannot exist on its own. Language needs an active community that uses the language, popularizes it, participates in its development. Under modern conditions, a language without the possibility of integration with existing libraries has no future. Indeed, no one will write algorithms that are already written and time-tested in other languages in a new language from scratch, no matter how good it originally was. The new language should at least support calling library functions written in C language format.
With the advent of such software platforms as JVM and CLR, the task of integrating code libraries in various languages was solved at a qualitatively new level. The code written on the platform automatically becomes integrated into a common multilingual environment. The platform provided not only integration at the execution stage, but also portability, both hardware and software, to various operating systems. Debugging and writing multilingual projects has become possible in a single development environment. The latter circumstance led to a new vision of using different languages in one project, i.e., the creation of multilingual projects.
Structuring Multilingual Applications
Ola Bini pyramid
Projects using several programming languages open up new possibilities for designing software systems. In such systems, each language is selected to achieve the best result for a particular task or fragment of the system. The synergistic effect of this approach is achieved by using the advantages of the language in those sections for which the selected language will be most effective and compensating for shortcomings where it is best to use another language.
System architect and developer Ola Bini is interested in programming languages. In his article “Fractal Programming,” Ola Bini discusses how, in his opinion, it is possible to arrange projects based on the use of several programming languages. To understand what languages and in what combination can be used in multilingual projects, Bini suggested considering the application structure by layers. In his conditional division, Bini identifies three layers and considers them in the form of an inverted pyramid.
A stable layer is at the inverted top of the pyramid. Applications of this layer meet the highest requirements for performance, stability, and absence of errors. Writing programs in such languages are the most time-consuming and expensive. That is why the pyramid is inverted — after all, software of this level is doomed to remain in the minority. However, the cost of creating such software is fully justified if you need high performance or support for a significant code base scale. The first is achieved by eliminating the overhead of interpretation at the execution stage, and the second is removed by static typing, which provides a guaranteed external interface.
The dynamic layer contains programming languages designed to create software quickly. The life cycle of such software can be concise: from several hours to several months. Such software can also change frequently. This may be a demonstration of the prototype or a new version of the user interface for the sale promotion. Such software can be of high enough quality to fulfill its function, on the one hand, and be flexible enough so that the complexity of its creation is lower than in languages from a stable level, on the other. The optional type declaration in such languages leads to a significantly smaller amount of code, as well as the possibility of its reuse in cases where it is necessary to work with different types in the same way. This allows writing code quickly and efficiently. The absence of compilation also increases the development speed, as it eliminates unnecessary loss of assembly time and will enable us to upload the changed code to the deployment environment quickly. Besides, dynamic execution allows you to change the code “on the go.”
And finally, the top layer is the most unstable, with a low level of responsibility. The languages of this layer impose low requirements on the level of programmer’s knowledge and thereby provide a large army of developers. The main purpose of this layer is fast software delivery. This layer includes lightweight languages without type control for building front-end type software and the so-called DSLs (Domain-Specific Languages) for creating application software. These are the languages of the leading edge, as close as possible to their consumers to such extent that even the knowledge of a non-programmer can be quite enough to make own website or even build their databases for personal accounting. The most significant volume of software is developed in this layer, and the widest part of the Bini pyramid corresponds to it.
Distribution of programming languages by typification level
ThoughtWorks systems architect and ideological mastermind Neal Ford suggested dividing languages based on typification: strong-weak, static-dynamic. This division allows you to understand how you can correlate languages across the layers of the Bini application.
With this division, languages with strong static typing belong to the stable layer. As noted above, software created in such languages can meet very stringent quality requirements. Such software includes compilers, device drivers, firmware, billing systems, server software, highly loaded services, computer games.
The dynamic layer includes dynamically strongly typed languages. A distinctive feature of the languages from this layer is the high speed of creating high-quality applications. Software from this layer: automation, administration and test generation scripts, web development (back-end), prototyping.
The last top layer includes subject-oriented languages with dynamically weak typing. These are the languages used to create application software: accounting systems, scripts with a simplified syntax for programming formulas or built-in equipment, DevOps, business rule modeling, and integration. They are characterized by a lack of type control, implicit casts, and dynamically typing determination.
Functional division (future of programming languages)
The division of programming languages concerning typification is not the only one. Recently, the tendency to increase support for the functional style in programming languages has firmly strengthened — and this is another aspect that is decisive in the development of languages. The basis of the functional style is the rejection of a changeable state and the use of functions as the first-class objects.
In developing his multilingual programming theory, Neil Ford put forward the idea that the stable languages will evolve towards increasing support for a functional style in the Bini layers classification. A functional programming style is already in fashion, and although accounting programs are not yet written in Haskell, many languages are beginning to support operations with higher-order functions. Such concepts as “declarative,” “pure functions,” “currying” is slowly starting to come to the vocabulary of an increasing number of programmers.
Successes in the field of creating multi-core architectures, to a large extent, facilitate the dissemination of functional programming ideas. Improving the efficiency of using cores directly depends on the implementation of a parallel application running. Imperative languages became widespread in the era of single-core processors, and under the new conditions, they ceased to be effective. The fact is that parallel computing is complicated to program in imperative style and, at the same time, very are organically and simply solved in functional languages. Also, functional languages have a high level of abstraction, which makes it possible to solve complex problems.
In the future, according to Ford, typing will no longer play such a big role, but the purity of the functional paradigm implementation will be decisive. Typing will remain, but it will be the prerogative of the programmer.
Ford also pays attention to the spread of DSL creation support utilizing the language itself. In languages such as Scala and Clojure, built-in support for creating own DSLs allows you to easily and compactly formalize important subject area concepts. According to Ford, the languages of the future, in addition to multi-paradigm, will also support DSL in all layers.
Multi-paradigm programming languages
Modern programming languages follow the path of supporting multi-paradigm. Languages that historically support the paradigm of procedural and OO programming are beginning to introduce elements of functional style paradigm support. On the contrary, functional languages are expanding their capabilities by introducing support for the OO paradigm.
Such development has both its pros and cons. If functional style support is, as a rule, an extension of the language’s features, then adding a paradigm to the OO functional language is an improvement in integration with other languages with the OO paradigm. Compare: Scala is an advanced Java language with elements of functional style, and Clojure is a purely functional language with support for the OO paradigm for compatibility with Java.
Multiparadigmality increases the power of the language, but it can also cause problems. Thus, when one project is developed by different teams using different paradigms, then there is a risk of developing incompatible libraries. The development in the OO paradigm stimulates the use of structures, and development in the functional paradigm stimulates composition and higher-order functions. Mixing paradigms can result in significantly different algorithms that cannot work without mutual adaptation, which means introducing additional complexity to the project. The development teams have already experienced similar problems when switching from Java to Ruby or from C to C++.
1C Programming Language as DSL
1C is the programming language embedded in the 1C:Enterprise platform. 1C is an excellent example of implementing an external DSL. These are the main DSL features: first of all, it is a specialized language for solving the problems of its subject area:
- makes it possible to describe the solution in terms of the subject area at the design stage;
- the level of language abstraction allows subject area experts to understand algorithms;
- applications using such a language are concise and allow optimization and validation of work with the subject model at the platform level
A lot of applications in a wide variety of usage scenarios have already been written in 1C:Enterprise language and these are not only accounting tasks. The language itself has built-in objects for working with files even at the byte level. All of this can be represented as written in a general language. Martin Fowler himself, who introduced the concept of DSL, noted in his work that sometimes it is challenging to attribute the capabilities of a language to DSL, and there is a fine line where the language goes beyond just one subject area and can already be considered as a general-purpose language. But let’s have a look at what the 1C:Enterprise platform language is.
The main limitation of 1C:Enterprise language is that algorithms can only be run in implemented platform events. The definition of the function called by the event is also predetermined by the platform and cannot be arbitrary. The platform also does not have the concept of a “library,” that is, code with its visibility scope. 1C:Enterprise language syntax and semantics are as simple as possible. All the main features of the language are implemented through the built-in platform objects. It is assumed that the main application functionality is implemented employing visual design in the Designer mode. You can change the typical platform behavior in 1C:Enterprise language in the event handler code.
1C:Enterprise language has many limitations that are not common for general-purpose languages. You cannot build an effective web server in this language or implement an interface that is not supported by the platform (try changing the highlight color of the current row of the table field). On the other hand, everything necessary for solving applied problems is maximally implemented in platform objects that are accessible from the language. The object semantics is defined at the platform level, and this ensures their support: data integrity, calculation of totals, access rights, presentation in the interface, etc.
According to the Bini pyramid, the layers of languages represent a fractal structure. In 1C language, this can be defined as a sequence of layers:
- subject area solution implementation
- implementation of basic functions in the subsystems library
- 1C:Enterprise language, query language, built-in objects
So we observe the effect of self-similarity of the Bini fractal pyramid at the level of the basic DSL language built into the 1C platform.
The conclusion about its possible development follows from the definition of 1C language as DSL. The language itself has not changed much, starting with version 1C7. All that changes in the platform are the composition of built-in objects and functions. And, which is most likely, this will continue: new objects will appear on the platform that will both provide new features and simplify existing solutions in 1C:Enterprise language. For example, objects have appeared that can be used to work with the storage history recently; however, a similar implementation, although less effective, has already been created earlier in 1C:Enterprise language as part of the basic standard library.
Selecting Programming Languages
The effective design of modern IT systems requires solving a variety of tasks. The days when the choice of a single language determined the features that completely covered the needs of creating such systems are gone.
In this situation, it is not enough for a programmer to know only one programming language. When working on a project in one language today, you may have to write code in another language chosen to solve the related problems in the next or the same project. So what languages does it make sense to know or learn first? There is no simple answer to this question. However, there is something in common in all languages, and there are differences. Knowledge of the common things will save new language entry time and concentrate just on the differences.
The syntax is common to all languages, and the difference is mainly in semantics. Thus, any language may have structural syntactic structures, conditions, calls, data structures, classes, etc. Despite the apparent similarity of syntactic structures, the presence of semantic differences can cause incorrect algorithms, operation interpretation, and errors.
The same syntax structure “TMyClass MyObject” in C++ will mean constructing an object, and an uninitialized object of type null in Java/C#. In the 1st case, you can continue working with the object, and in the 2nd attempt to use an uninitialized object will cause an application to crash.
In the general case, a programmer who is interested in their professional development needs to have knowledge of computer sciences, various paradigms, and be aware of the latest trends in language development. We can recommend learning several languages from different application layers (see Bini Layers) or one layer — in the amount of 3–4 languages. Below are the options for selecting languages based on purposes.
Selecting programming languages for education
Research in IEEE Spectrum magazine or TIOBE data on the popularity of languages may help you navigate around programming languages:
Selecting programming languages for work
Selecting programming languages for the projectThe choice of language in the project depends on many factors; here are some of the questions that can help determine the language:
- What is the language learning curve?
- How effective are existing frameworks?
- How developed is the language community?
- How quickly can you find the right developers?
- How easily can a language integrate into a multilingual environment?
The practice has shown the failure of finding a single universal programming language. New languages will continue to appear. Each new language will find a compromise between development speed, productivity, and reliability in its way. Also, a wide variety of subject areas guarantees an inexhaustible need for subject-oriented languages, as the most adequately describing its tasks. The JVM and CLR platforms, created to solve the portability problem, and to unify programming models subsequently, will only contribute to the emergence of new languages.
Multilingual projects will find their use in complex applications. Such projects within one JVM or CLR platform will include algorithms written in different languages. However, these will be single applications with shared data at the bytecode level.
Universal languages will continue to evolve towards multi-paradigm. Historically, such languages began operating in the procedural paradigm, then in OO, and now the functional paradigm is gaining popularity. The functional style will gradually become the main one, and imperative style will become an auxiliary one. Important applications will be written in functional languages, the scope of imperative languages will remain for input/output tasks, irreversible operations, and the development of interactive user interfaces.
Along with multi-paradigm, languages will begin to support the creation of DSL. External DSLs will remain as the languages closest to the subject area. These languages will have the lowest entry threshold and will be available even to non-programmers.
Professional programmers need to come to terms with the need to know several programming languages. On the one hand, knowledge of several languages can significantly increase the mental load on the programmer, on the other hand, all languages have similar syntactic structures, and semantics and the standard language library are a significant difficulty in mastering languages.
The technologies created to solve one problem are often the key to qualitatively new solutions in other tasks. Thus, the JVM, CLR environment was created to solve the problem of portability and unification of programming models (the latter was initially laid down in the CLR for two languages: C# and VB). Later it turned out that the existence of such environments allows, in principle, changing the attitude towards software development. If earlier one language has the development priority, and the problematic aspects of the language were solved at environment components and libraries delivery or even language extension level, now the opportunity has appeared to combine solutions in different programming languages in one project taking advantage of each of them for a specific kind of task. Summing up, we can argue that the idea of creating one universal language at this stage of development did not live up to expectations, and the IT world is moving towards multilingual programming.
The article was originally published at: https://medium.com/1c-developer/selecting-programming-languages-depending-on-the-task-c20fa4bb1b5f