
Design Principles for Internal Domain-Specific Languages: A Pattern Catalog Illustrated by Ruby Sebastian Günther, School of Computer Science, University of Magdeburg and Thomas Cleenewerck, Software Language Engineering Lab, Vrije Universiteit Brussel Some programming languages, especially dynamic programming languages, offer suitable mechanisms for the construction of internal domain-specific languages (DSL). Internal DSLs inherit the facilities of their host language such as the availability of libraries, frameworks, tool support, and other DSLs. When developing an internal DSL, there are two challenges. First, to cope with the host language’s syntactic and semantic restrictions. Careful and thoughtful extensions and modifications of the host language are crucial to overcome these restrictions without reverting to poor language design. Second, to support several design principles that are genuine for a DSL. Although there is an extensive body of knowledge about DSL design principles and desirable quality properties, it remains difficult to apply them, or to reason about whether a particular DSL exhibits specific desirable principles. Our objective is to put the two perspectives together. We research the most important design principles of a DSL and show how different patterns can be used to support these principles. This allows us to produce an extensive pattern catalog which is the foundation of principled approach for designing internal DSLs. The patterns can be used to assess the design quality of a DSL and structure its implementation. In particular, we show a complex DSL example illustrating each principle and the corresponding patterns. While we stick to Ruby for the explanation and application of the patterns, we also name known uses in Python, Scala, and Smalltalk. Patterns are explained with their context, problem, forces, solution, and consequences. We also explain the patterns with the classical structure of intent, motivation, forces, implementation and their consequences. Finally we reflect upon the pattern utilization by discussing their strengths and weaknesses. Categories and Subject Descriptors: D.3.3 [Programming Languages]: Language Constructs and Features—Patterns General Terms: Design Additional Key Words and Phrases: design principles, domain-specific languages, dynamic programming languages 1. INTRODUCTION Domain-specific languages are programming languages or executable specification languages that offer, through appropriate notations and abstractions, expressive power tailored for a specific problem domain or application area [Van Deursen et al. 2000; Hudak 1998]. At the implementation level, two different types of DSLs can be identified. Specially crafted external DSLs require their own parsers, interpreter or compilers, while internal DSLs are built on top of an existing programming language (called the host language), allowing them to reuse the host language’s infrastructure including IDEs and compilers [Mernik et al. 2005]. DSL are a common practice in software engineering as several examples show [Arnold et al. 1995; Groote et al. 1995; Thibault et al. 1997; Latry et al. 2007; Munnelly and Clarke 2008]. The wide spectrum of domains, internal DSLs, and external DSLs, is threatening to deteriorate the original meaning of the term DSL. The term is applied often and without to much consideration what the properties of a Author’s address: Sebastian Günther, Universitätsplatz 2, D-39106 Magdeburg, Germany, email: [email protected]; Thomas Cleenewerck, Vrije Universiteit Brussel, Faculty of Sciences, DINF - SOFT, Pleinlaan 2, B-1050 Brussels, Belgium, email: [email protected] Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee pro- vided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full cita- tion on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permis- sion. A preliminary version of this paper was presented in a writers’ workshop at the 17th Conference on Pattern Languages of Programs (PLoP). PLoP’10, October 16-18, Reno, Nevada, USA. Copyright 2010 is held by the author(s). ACM 978-1-4503-0107-7 PLoP’10, October 16-18, Reno, Nevada, USA. Copyright 2010 is held by the author(s). ACM 978-1-4503-0107-7 DSL are. Analyzing the relevant literature [Mernik et al. 2005; Tanter 2008; Ladd and Ramming 1994; Weinberg 1971; Coplien 1999], however, reveals that there are several design and implementation principles of DSLs such as abstraction to make domain concepts explicit programming language constructs, absorption to integrate implicit and common domain knowledge in the DSL, or compression to yield a concise domain notation. While these principles are general enough to provide guidelines for the design and implementation of a DSL, it is rather hard to explain whether an implemented DSL supports or embodies these principles. It is also difficult to plan the implementation upfront without a sophisticated language that allows expressing design decisions with respect to the principles. Hence the question: how to achieve this? We argue that the careful selection and application of patterns help here. Patterns support the DSL implementation by embodying these principles. By providing a deep understanding of the design principles together with a pattern catalog, we facilitate the planning and implementation of DSLs that exhibit the design principles. This paper’s contribution is a rich pattern catalog that helps to approach DSL design based on a set of design principles. Through using the patterns that adhere to the design principles, the design quality of a DSL can be assessed. To the best of our knowledge, this particular combination of principles and patterns has not been elaborated in other literature yet. For feasibility of this first-hand analysis, the paper focuses upon selected principles and illustrates the application of patterns grouped into form (alternative syntactic forms for the expressions), modification (small changes to the language, like the provision of aliases), and support. The patterns are illustrated using the Ruby programming language and two internal DSL designed within this language. However, the patterns are available in other programming languages too, which we show for Python, Scala, and Smalltalk by pointing to known uses. The paper is intended for novice as well as experienced DSL engineers. For experienced DSL engineers our work consolidates the design qualities of their DSLs enabling them to learn and improve their DSL designs. Novice DSL designers can use the principled pattern approach as a reference work to create internal DSLs. We structure the paper as follows. Section 2 explains the used pattern structure and grouping. In Section 3, the design principles are explained. Sections 4 to 6 list the patterns with their intent, motivation, forces, structure, consequences, and additional known uses outside the herein presented examples. Section 7 revisits the design principles and, using a larger DSL examples, shows how the patterns are used in combination to design a DSL with respect to the principle. Section 8 discusses our experiences in using combinations of patterns and their influence on all principles. Section 9 explains the related work and finally Section 10 summarizes this paper. We apply following formats: keywords, design principles, and PATTERNS. 2. PATTERN STRUCTURE AND COMMON EXAMPLE 2.1 Pattern Structure The pattern explanation has a structure that is close to the initial introduction of patterns [Gamma et al. 1997] and recent publications [Guerra et al. 2009; Correia et al. ; Zdun and Strembeck 2009]. The following structure is used to explain each pattern: — Context: Explains the coarse situation in which the pattern is applied. — Problem: A question expressing the central concern the pattern addresses. — Design Impact: Explains which principles are realized by applying this pattern and explains the particular achieved result. — Instructions: Explanation what language mechanisms are used to provide a solution. — Example: Based on the common examples, a detailed utilization of the pattern using the Ruby programming language is given. Source code examples and sometimes diagrams provide further illustration (see Figure 1 for used symbols). Design Principles for Internal Domain-Specific Languages:A Pattern Catalog Illustrated by Ruby — Page 2 «Module» Modules; changed modules are depic- ted as Module’ Class Classes; changed classes are depicted -#local_variable as Class’, and changed methods are -class_variable depicted as method’ Object Objects; changed objects are depicted as Object’ Class/instance relationship Class/subclass relationship Module/inclusion relationship Represents the border between two program status define_method :method do Executed code attached to the ... respective object using a dashed line end Method or symbol pointer X Blocked method or symbol pointer Fig. 1: Symbols used to explain the pattern’s structure. — Implementation Impact: Explains how this pattern’s utilization impacts the DSL implementation or the DSL itself. — Known Uses: List of applications that use this particular pattern, given for Ruby [Flanagan and Matsumoto 2008; Thomas et al. 2009], Python [Lutz 2009; Summerfield 2010], Scala [Odersky et al. 2008; Wampler and Payne 2009], and Smalltalk [Sharp 1997; Black et al. 2009a; 2009b]. The analyzed DSLs are listed in the next
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages35 Page
-
File Size-