promotor: prof.dr. M.G.J. van den Brand (TU/e)
copromotor: dr.ir. T. Verhoeff (TU/e)
Technische Universiteit Eindhoven
Date: 7 November 2017, 16.00
The history of software engineering is one of continuously raising the abstraction level in programming languages. The abstraction level has been raising towards using concepts from the problem space into the programming languages themselves. The ideal situation would be to have programming languages and associated interactive development environments that allow a domain expert to create software applications by instructing the computer using concepts from her own domain. This situation would also require a different software development process, with at least two main role players: language engineers that develop and maintain the domain-specific languages (DSLs), and domain experts that use these domain-specific languages by creating models in them.
This is advocated by new methodologies, such as model-driven development (MDD) and language-oriented programming (LOP). Although MDD and LOP have different focuses (MDD focuses on the models, and LOP focuses on the programming languages), they both use domain-specific languages to achieve their visions. A big leap in easing the creation of DSLs occurred with the introduction of language workbenches; nonetheless, developing non-trivial DSLs is still a daunting task. As already hinted by the discussion in this paragraph, we have concentrated on the part of easing the development of DSLs in this thesis. We have done so by employing modularity and reuse in the creation of domain-specific languages. We have taken the path of modularity and reuse because DSLs, and especially DSLs from the same domain, have common fragments, or DSL units. One example is the use of arithmetic expressions, which is common among many DSLs. This DSL could live in a separate DSL unit for arithmetic expressions. Then, language engineers should be able to seamlessly integrate the arithmetic expressions DSL unit into their own DSL.
There are two main parts to the development of a DSL, the metamodel and the associated processing units. We consider the metamodel to be the core of a DSL because this is where the main concepts and the relations among them are made explicit; moreover, the processing units (interpreters, code generators, editors, etc.) are querying and navigating this metamodel. Getting the metamodel right is essential for both the expressivity of the DSL and the ease of developing the processing units. Thus, much of the development of a DSL relies on the metamodel.
This thesis contributes to the community of DSL development with mechanisms and meta-tools focused on modularity and reuse in the creation of domain-specific languages. We have approached modularity and reuse in the creation of domain-specific languages starting from the core, the metamodels, and finishing with the processing units. These mechanisms are also accompanied by a prototype meta-tool, MetaMod.
First, we investigated reasons and requirements for modularity and reuse in the creation of domain-specific languages. To this end, we went over advantages and disadvantages of modularity and reuse in other fields, and especially in software engineering. Advantages such as increased productivity and ease of updating, or disadvantages such as more upfront deliberation, are to be expected when carrying over modularity and reuse in the creation of DSLs. Besides these, LOP itself offers a reason for modularity, because in LOP, one needs to combine different DSLs in the creation of a software application. As for requirements, given that DSLs are, in the end, software applications, we have paraphrased criteria for the extensibility of software to criteria for modularity and reuse of DSLs, with slight modifications.
Second, we looked at how to organize metamodels of the DSLs to facilitate modularity and reuse of DSLs. We did that through the design of a new meta-metamodel for MetaMod. This meta-metamodel introduced the following elements for modularity and reuse of DSLs: groups with group reuse, and concept and relation sharing, that allow decomposing and reusing metamodels; fragment abstractions and applications, that allow factoring out common metamodel structures with placeholders; and a subtype relationship that allows reuse of relations. This mix of elements allows the creation of modular and reusable metamodels.
Third, we addressed how to organize processing units of the DSLs and the operations in the processing units to facilitate modularity and reuse of DSLs. For that, we took advantage of the organization in the metamodels by leveraging two hierarchies from the metamodel (the subtype hierarchy and the group hierarchy) in the type system of the processing units. Moreover, we organized the processing units around groups and aspects. What further facilitated modularity and reuse, was the reuse of operations in agreement with the reuse of groups and aspects, and the introduction of multiple dynamic dispatch on the concept types, group types and raw Java types. All these features allow the reuse and adaptation of operations from reused DSL units into reusing DSL units.
Fourth, we investigated the reuse of operations in spite of structural differences among domain-specific languages. That is because, although logically similar, the metamodels of two DSLs can be significantly different; nonetheless, it is of great value to allow the reuseof operations defined for one DSL in the other DSL. For this, we created two mechanisms, the mechanism of reuse mappings and that of delegated operations. The mechanism of reuse mappings is based on expressing queries from the base DSL in terms of queries in the reusing DSL, so that operations from the base DSL can be reused in the reusing DSL. On the other hand, the mechanism of delegated operations is based on creating a model transformation from the metamodel of the reusing DSL to the metamodel of the base DSL, and defining the signature of the operations from the base DSL in the reusing DSL. The latter mechanism is an improvement over the former because it imposes less constraints on the form of the metamodels of the base DSL and reusing DSL.
Fifth, we addressed mechanisms that can be applied to models, irrespective of the DSL. At this point, we used the multilevel nature of MPS, that allows to use mechanisms developed for the metamodel in the models as well. That is, the groups (with group reuse, and relation and concept sharing), and the fragment abstraction and application can be used in the models as well. These mechanisms are available for any model, irrespective of the DSL to which they conform.
Last, we have evaluated our approach, starting with the development of the meta-tools of MetaMod. We have then created DSLs ranging from small sizes to big sizes, and from imperative-flavoured to declarative-flavoured. Most notably, we have re-implemented a considerable part of a non-trivial expression language built in Jetbrains MPS. This gave us confidence that the meta-tools and the ideas behind them are powerful enough to tackle real-life problems. Moreover, it has also allowed us to make a more direct comparison with a seasoned language workbench. As a result of the comparison, we have discovered that MetaMod leads to more conceptually cohesive DSLs because it avoids the introduction of some implementation-oriented concepts. Moreover, the modularity of MetaMod allowed us to create smaller-sized DSL units, that are reusable in separation, but that are part of the overall expression language DSL.
We think that the ideas that we have introduced in this thesis get us a step closer to the accomplishment of the visions of MDE and LOP, and that they will speed up the development of domain-specific languages.