Developing custom software for a specific target domain is a challenging task.
In this context, domain-specific languages (DSLs) receive a constantly growing
attention in recent years. A domain-specific language (DSL) is a
tailor-made language that does only provide abstractions suitable for one
particular problem domain.
DSLs have gained popularity in the area of model-driven development (MDD), especially through the
advance of so-called language workbenches. The basic idea
of DSLs, however, already has a long history. Language workbenches take the well known
language-oriented programming approach and use IDE tooling to make it a
viable approach. Examples of language workbenches are MDD tools
such as XText, Microsoft's DSL toolkit, MetaCase, Microsoft's OSLO, and MPS.
In contrast to simple language-oriented programming approaches, focusing
mainly on parser development and related activities, language workbenches
support all aspects of DSL design and development, including for
example the transformation of DSL code to a platform or the development of
language editors for the DSL. In addition to language workbenches, some other
DSL toolkits exist that support many aspects of DSL design and development.
For example, DSLs in dynamic languages are typically developed as embedded DSLs
that can use the existing tooling and platforms of the dynamic language.
Frag aims at supporting DSL development by combining the best of both worlds and a few
other unique concepts.
With the DSL toolkits becoming more mature, DSLs are not only used in niches anymore,
but receive widespread adoption. For many architects, DSLs are an interesting approach
that can potentially be used in projects where domain knowledge is hard to capture.
DSLs can help here, as they come with the promise to enable involving domain experts
more closely in the software design activities.
Architecture can be seen as a set of design decisions rather than (only) a set of
components and connectors. In this view, the architect needs to understand which
architectural decisions are influenced by the choice of an approach or a technology.
The above named toolkits require architects to make important architectural decisions
about the DSLs in a project early on - when the DSL toolkit is chosen. Example
decisions are: the decision for an embedded or external DSL approach, the possible
integration with a host language, the options for syntax extensions, the options
for the use of an explicit language model, the usability options with regard to
custom error messages, the language integration options, and the choice between
generation, transformation, and interpretation for defining the DSL's execution
semantics. Often significant changes or even a complete reimplementation of the DSL in
another technology would be necessary to change some of these architectural decisions
later on, once a DSL implementation has been completed.
In our experiences, it is often necessary to focus in early stages of DSL projects on
getting the domain abstractions right. Work collaboratively conducted by the domain
experts and the software designers is needed, and approaches, such as rapid application
development, tinkering with DSL ideas, and agile methods with many iterative feedback
cycles, are highly useful in DSL-based design and development. The dilemma is: On the
one hand, toolkit-specific decisions, should be deferred till the domain
abstractions and requirements are sufficiently understood, but, on the other hand,
tinkering with the DSL requires some realistic DSL toolkit that preselects many
options for the decisions listed above.
Of course, it is possible to solve this dilemma by developing a throw-away prototype
that is replaced by another technology, once a first sufficient understanding of the
domain has been reached. In contrast, Frag's approach follows the idea to provide
a DSL language toolkit that supports incrementally evolving a DSL and still allows
DSL designers to change fundamental decisions later on.
In the following sections, we present Frag as a toolkit for DSL-based design and
development. In Frag, we (optionally) base DSLs on an explicit language model
for the DSL - similar to models in model-driven DSL approaches. We also combine the
external DSL and the embedded DSL approaches in a unique way: For each language model,
Frag provides an intuitive embedded DSL syntax. In addition, one or more external
DSLs can be added and mapped to Frag, using a flexible rule-based parsing approach
that aims at supporting tinkering with syntax ideas. Each DSL artifact is provided
as a modular entity that can be selected/deselected at any stage of a DSL project.
All specifications of DSLs in Frag are provided using DSLs that are embedded in
Frag (which is itself embedded in Java; hence every Frag DSL can be used in Java
applications). Such embedded DSLs are provided for specifying language models,
constraints, parser specifications, and mapping specifications. That is, the
Frag approach for specifying DSLs follows the DSL approach itself.
DSLs can be defined for technical users, such as software developers or architects,
as well as non-technical users, such as business analysts. In either case, the DSL
should make the domain-knowledge explicit, and help the DSL users to accomplish
their work tasks. In general, we can distinguish two different styles of DSLs:
An embedded DSL (also called internal DSL) is an extension to an
existing programming language and uses the syntactic elements of the underlying language, hosting the DSL.
An external DSL is defined in a different format than the intended host language(s) and
can use all kinds of syntactical elements.
From a language user's point of view, the DSL consists of language elements. The core definition of
these language elements is provided by the language model that specifies the concepts of the DSL's target domain.
For instance, if the target domain is SOA, then elements such as service, process, and business object are part
of the language model. If the target domain is core banking, then elements such as account, bond, and customer
are part of the language model. The MDD paradigm advocates to specify the language model (sometimes called
DSL metamodel) explicitly using a modeling language such as UML or EMF. Other implementation options for DSLs, such
XML-parser-based DSLs, DSLs based on scripting languages or dynamic languages, or DSLs based on parser generators,
do not imply an explicit language model - it is often implemented and hidden in the DSL implementation source code.
In order to use the DSL, we must define its semantics, too. For many DSLs, static semantics are defined
through constraints on the language model, as well as program code defining the execution semantics of the DSL.
Both, language model and static semantics of the DSL are called the abstract syntax of the DSL.
The architect must decide how static semantics are implemented: Besides constraint languages offered
by some of the model-driven toolkits, expressing them in transformations, in custom code, or not at all
are options.
In addition to the abstract syntax, each DSL needs a concrete syntax, offered to the user of the DSL.
Each DSL can have multiple concrete syntaxes. We can distinguish textual syntaxes, graphical syntaxes, form-based
syntaxes, and so on. The architect must decide for the kinds of concrete syntaxes that are supported by the DSL.
Frag mainly focuses on textual concrete syntaxes.
Transformations are defined to transform DSL code written in a concrete syntax to another model representation
or to code that can be executed on a specific platform. In general, a transformation is a directive that
defines how one (model) format is to be transformed to another (model) format. In different approaches,
the transformations are realized in different ways: In the model-driven approaches, a generator performs the transformations.
In scripting and dynamic languages, the concrete syntax code is mapped to directives of the interpreter.
A parser generator creates a parser that triggers instructions in a programming language.
In all approaches, a programming language executes the DSL code and is used as the target of the transformations.
This programming language is called the host language.