Clicky

Book Review: Domain-Specific Languages – Effective Modeling, Automation, and Reuse

Andrzej Wasowski and Thorsten Berger: Domain-Specific Languages – Effective Modeling, Automation, and Reuse

Springer, February 2023, 485 pp, ISBN: 978-3-031-23668-6. https://doi.org/10.1007/978-3-031-23669-3

Summary

Domain-Specific Languages – Effective Modeling, Automation, and Reuse by Andrzej Wasowski and Thorsten Berger (Springer) offers a comprehensive introduction to DSLs, combining perspectives from both the modelware (MDSE, meta-modelling) and grammarware (grammars, parsers) communities. The book systematically covers domain analysis, abstract and concrete syntax, static and dynamic semantics, code generation, and tool support, enriched with examples from robotics, machine learning, and embedded systems to show DSLs’ practical relevance in agile and low-code development. Aimed at advanced students and instructors, it blends solid theoretical foundations with exercises, teaching guidelines, and case studies, making it a valuable resource for both learning and teaching.

This review is written by Patrizio Pelliccione for FME’s Book Review Committee (BRC). The aim of the BRC is to provide to the formal methods community, and to the scientific community in general, high-quality reviews of books on topics of interest to the community.

Domain-Specific Languages – Effective Modeling, Automation, and Reuse
by Andrzej Wasowski and Thorsten Berger.

Review

The book titled “Domain-Specific Languages - Effective Modeling, Automation, and Reuse”, Andrzej Wasowski and Thorsten Berger, published by Springer, is a great textbook covering the Domain-Specific Language (DSL) topic.

The book introduces the DSL topic for two different communities, the modelware community, which advocates MDSE and meta-modeling, and the grammarware community, which is traditionally centered around grammars and parsers. It is indeed an added value of the book to have both the Model Driven Engineering (MDE) and the Programming Language (PL) points of view. Both communities focus on software development, but they look at the problem from two different angles. The modelware community focuses on object-oriented modelling and systems and software engineering techniques. The grammarware community focuses on grammar-oriented descriptions of structure and it is closer to the functional programming community. A grammar is not just intended as a parser specification but, more generally, as a “structural description in software systems”. The book elegantly presents concepts for both communities and this makes the explanation more interesting and clear. Hopefully, this point of contact will also foster further collaboration and discussion across the modelware and grammarware communities.

Content of the book

In the first two chapters, the book starts with an introduction and motivation to the DSL subject, the first more from the point of view of the modelware community, the second more from the point of view of the grammarware community. Then, Chapter 3 introduces the domain analysis and abstract syntax. It includes design and analysis guidelines for meta-models, shows examples and briefly presents several meta-modelling languages (meta-meta-models) with a focus on class diagrams. It provides examples of instances of meta models (called models) and explains how models, meta-models, and meta-meta-models relate in the theoretical framework known as the language-conformance hierarchy. Chapter 4 explains what is a concrete syntax, and details how to create a syntax that is easy to read and write for language users, and that is understandable and maintainable for language designers. It discusses in depth specification mechanisms, like context-free grammars and regular expressions, design guidelines for textual syntax, and quality assurance. It also provides guidelines on how to constrain syntax. Four chapters focus on how to provide semantics, i.e., expressing the meaning of models so that automated tools can use models correctly and properly. Chapters 5 and 6 focus on static semantics and static semantics with type systems, respectively. Static semantics aims at stating which models or programs written in the DSL are legal, and which, instead, are erroneous, e.g., do not make sense. Chapter 6 introduces the reader to the concepts of types and type systems. Moreover, it shows how to build a simple type system, and discuss when it is practical to use a type system instead of structural constraints. Dynamic semantics of programming languages or modelling languages concerns writing an interpreter or a compiler. Chapter 7 focuses mostly on compilers to translate models within or across languages. Chapter 8 focuses on interpreters for DSLs. Dynamic semantics is a powerful way of making DSLs useful in specific contexts. The book could have clarified better the concepts of semantic anchoring and translational semantics. It is worth noting that providing a dynamic semantics is especially useful when it directly leads to the creation of accompanying tools supporting the DSL. For instance, a DSL can be translated to another language (target language) with clear semantics (e.g., logic or programming language) via model or program transformations. The transformation gives semantics to the DSL, by anchoring it to a target language with its own precise semantics; in addition, the transformation enables the exploitation of the tools that take as input or manipulate the target language. Chapter 9 discusses code generation techniques, which, like the model and program transformation mechanisms presented in Chapter 7 and the DSL interpreters of Chapter 8, are instruments that facilitate the application of DSLs to various contexts. The book covers DSL-related topics in great depth and it conveys to the reader the importance of DSLs in today’s software development practice. Early in the book, the authors highlight how Model-Driven Software Engineering (MDSE), of which DSLs are a key ingredient, is often wrongly associated with plan-based software engineering, which suggests that heavy upfront investment and planning are necessary. The authors then explain how agile practices, such as incrementality, continuous integration, continuous delivery, and continuous deployment are perfectly applicable to DSL-based system development. Automation (e.g., automated testing, continuous integration and deployment) is key in agile approaches, and DSLs can be successfully exploited to automate software engineering tasks. This is also witnessed by the emergence of Low-Code Platforms and Non-Code Platforms, which allow users to generate applications through external graphical DSLs. Google’s AppSheet and Microsoft’s PowerApps are commercial examples of such platforms, while Eclipse’s OSBP is an open-source one. The book also provides numerous examples of the use of DSLs in various domains. In the robotic domain, they show DSLs to control robotic soccer players within the RoboCup competition or to control humanoid robots. Google, Microsoft, and Yahoo!, among others, exploited DSLs to cope with complex machine-learning and data-processing frameworks. DSLs are also used to automate software tasks, such as code generation, simulation, testing, test case generation, or early simulation of (executable) models in the engineering of embedded systems.

These examples illustrating possible uses of DSLs allow readers to evaluate whether a DSL could be of help in their work or provide the solution to outstanding problems.

The previous chapters focus on external DSLs, whose development follows a compiler-like pipeline architecture, with clearly separated design artifacts. Chapter 10 investigates the design and implementation of internal DSLs, which are implemented as libraries in a General-Purpose Language (GPL), such as Scala, Java, or C#. Internal DSLs can reuse the concrete syntax along with the basic static and execution semantics of the GPL. The last chapters focus on product line engineering with software product lines, feature modelling, and model and language variability. They are indeed interesting and relevant, but they less obviously fit with the rest of the book. However, as highlighted in the foreword by Ralf Lammel, “variability” in software development can be considered as one of the domains the book discusses, and variability approaches tend to use DSLs for configuration.

Audience of the Book

Concerning the audience, the book is clearly classroom- and learning-oriented, and it contains a large number of exercises, as we can find in mathematics textbooks, which greatly help the learning of the subject. This facilitates constructive learning since introduced concepts are always supported by examples, exercises, and lessons from industrial and open-source projects.

At the same time, the book highlights the research foundations and provides useful further-reading material. The authors explicitly state that they mainly target senior undergraduate and junior graduate students in Computer Science or Software Engineering, and we can certainly agree with this statement. The book requires some previous knowledge in object-oriented and functional programming, including testing, as well as, a basic understanding of propositional logic, quantifiers, sets, functions, relations, and basic data structures. No significant mathematical background is required.

The book also provides guidelines for teachers on how to teach with the book and with online material. Depending on the school, the program, and the teacher’s preferences, the authors also highlight potential subsets of chapters that can be used to define an ad hoc course. For instance, a classical DSL course of 7-10 weeks would require Chapters 1–10. Chapter 6 and Chapter 10 can also be skipped or just mentioned since they focus on static semantics with type systems and internal DSLs, respectively. Instead, a course aiming to just introduce internal DSLs should focus on Chapters 1–4. Finally, a course focusing on product-line engineering should focus on Chapters 1–3 and Chapters 11–13.

Author: Patrizio Pelliccione

Share