METACASE
Domain-specific
modelling
Domain-Specific Modelling raises the level of abstraction beyond programming
by specifying the solution directly using domain concepts. The final products
are generated from these high-level specifications. This automation is
possible because both the language and generators need fit the requirements
of only one company and domain. This article describes Domain-Specific
Modelling and explains how such languages and generators can be implemented.
Introduction
Domain-Specific Modelling aims to align code and problem domain more closely.
This search for better alignment started decades ago when programming
languages evolved from assembler towards a higher level of abstraction.
Newer programming languages, however, have made relatively modest improvements
to support problem domain abstraction. Java and C# differ very little
from C++.
Domain-Specific
Modelling (DSM) provides a solution for continuing to raise the level
of abstraction beyond coding. Ideally, DSM offers the same concepts and
follows the same rules as the problem domain. Every domain is different,
though. Every domain contains its own specific abstractions, concepts
and correctness constraints. Let us take some examples. If we are developing
a portal for insurance product comparison and purchase, why not use the
insurance terminology directly in the design language? Language concepts
like ‘Risk’, ‘Bonus’ and ‘Damage’
capture facts about insurances better than Java classes do. An insurance-specific
language can also guarantee that the products modelled are valid: insurance
without a premium is not a good product, so such a product should be impossible
to design. Similarly, if we are developing mobile applications for a device,
why not have the concepts of the UI and mobile services directly in the
design language? It is far more natural to think about application logic
with ‘List’, ‘SMS send’, ‘View’ etc.
than with C code. Likewise, while developing voice communication systems,
microcontroller concepts like ‘Menu’, ‘Prompt’,
and ‘Voice entry’ are closer to the problem domain than Assembler
mnemonics.
This article
describes DSM and how it can offer design abstractions closer to the given
problem domain. DSM is not only about making designs. In many cases, when
applied on top of a platform or framework, the final products can be automatically
generated from these high-level specifications. In all of the examples
above, for instance, a domain-specific generator reads the models and
produces the full code. The generation of complete code is possible because
both the language and generators need fit only one problem domain and
its implementation space. Problem domains that are especially well-suited
to DSM are product family development, platform-based development and
product configuration.
Domain-specific
modelling solution
In DSM, the model elements represent things in the domain world, not the
code world. The modelling language follows the domain abstractions and
semantics, allowing modellers to perceive themselves as working directly
with domain concepts. The rules of the domain can be included into the
language as constraints, ideally making it impossible to specify illegal
or unwanted design models. The close alignment of language and problem
domain offers several benefits. Many of these are common to other ways
of moving towards higher levels of abstraction: improved productivity,
better hiding of complexity, and better system quality.
Generally,
a higher level of abstraction leads to better productivity. This means
not only the time and resources to make the designs in the first place,
but the also the maintenance resources. Requirements changes usually come
via the problem domain not the implementation domain, so making such changes
in a modelling language that uses domain terms is easier. In addition,
in some domains, non-programmers can make complete specifications –
and run generators to produce the code.
Keeping specifications
at a significantly higher level of abstraction than traditional source
code or e.g. class diagrams means less specification work. As the language
need fit only a specific domain, usually inside only one company, the
DSM can be very lightweight. It does not include techniques or constructs
that add unnecessary work for developers.
DSM reduces
the need of learning new semantics. Problem domain concepts are typically
already known and used, well-defined semantics exist and are considered
"natural" as they are formed internally. Because domain-specific
semantics must be mastered anyway, why not give them first class status?
Developers do not need to learn additional semantics (e.g. UML) and map
back and forth between domain and UML semantics. This unnecessary mapping
takes time and resources, is error-prone, and is carried out by all designers
– some doing it better, but often all differently.
DSM leads
to a better quality system, mainly because of two reasons. First, DSM
can include correctness rules of the domain making it difficult, and often
impossible, to draw illegal or unwanted specifications. This is also a
far cheaper way to eliminate bugs: the earlier the better. Second, generators
provide mapping to a lower abstraction level, normally code, and the generated
result does not need to be edited afterwards. This has been the cornerstone
of other successful shifts made with programming languages. Ever seen
anybody manually edit Assembler and try to keep their C++ code in synch
with it? In UML for instance, code visualization has led to round-trip
problems: if you are code-focused, models merely visualize static class
structures. If you are modelling-oriented, a lot of effort goes into rewriting
generated code and keeping all the other models than class diagrams up-to-date.
Having the same information in two places, code and models, is a recipe
for trouble.
Finally,
specifications made with domain terms are normally easier to read, understand,
remember, validate and communicate with. These clear benefits are illustrated
using an example.
Example
Every domain is different, and so every DSM example is different. We use
here a domain that is well known and already in our pocket: mobile phone
applications. The specific implementation target is the public smartphone
platform Series 60 [Nok03] and its application framework [Nok04]. This
framework enables the development and deployment of enterprise applications
in mobile phones. Accordingly, in this domain, the development process
involves applying the terms and rules of mobile enterprise applications
built on Series 60. The DSM language applies these directly as modelling
concepts as illustrated in Figure 1.

Figure
1. Conference registration application
The design
model is directly based on domain concepts, such as Note, Pop-up, SMS,
Form, and Query. These are specific to mobile phone services and its user-interface
widgets. If you are familiar with some phone applications, like phone
book or calendar, you most likely already understood what the above application
makes. A user can register for a conference using SMS messages, choose
a payment method, view program and speaker data or browse the conference
program via the web.
As can be
seen from the model, all the implementation concepts are hidden (and are
not even necessary to know at this stage). Developers can focus on finding
the solution using the domain concepts. As the descriptions capture all
the required static and behavioural aspects of the application, it is
possible to generate the application fully from the models. The generated
code uses the services provides by the Series 60 and its framework. After
design, there is no need to map the solution to implementation concepts
in code or in UML models visualizing the code.
The modelling
language also includes domain rules, preventing developers making illegal
designs. For example, in Series 60, it is typical that after sending an
SMS message, only one UI element or phone service can be triggered. Accordingly,
the DSM allows only one flow from an SMS element. This means that application
developers do not need to master the details of the Series 60 architecture
and programming model. If you understand the phone UI and services it
can provide, you can develop applications.
How to
implement DSM
To get the DSM benefits of improved productivity, quality and complexity
hiding, we need a domain-specific language and generators. In the past,
you would also have needed to implement the supporting tool set. This
was one of the main reasons holding DSM back: after all, implementing
CASE tools is hardly a core competence for most organizations.
Today, the work needed is reduced to just defining the language and generators,
since open metamodel-based tools for modelling and code generation are
available. The typical architecture of such metaCASE tools is illustrated
in Figure 2 [Poh00].

Figure
2. Architecture of a DSM environment
These metaCASE
tools have a dual nature. The left side represents the parts needed to
create the environment – a task that is carried out by method developers.
The right side illustrates the use of the environment by engineers developing
products. We will use Series 60 application modelling language as an example
to explain DSM definition.
Defining
the modelling language for a domain
Defining a modelling language involves three aspects: the domain concepts,
the notation used to represent these in graphical models, and the rules
that guide the modelling process. Defining a complete language is considered
a difficult task: this is certainly true if you want to build a language
for everyone. The task eases considerably if you make it only for one
problem domain in one company.
The key issue
for finding domain concepts is the expertise provided by a domain expert
or a small team of them. Typically, the expert is an experienced developer
who has already developed several products in this domain. He may have
developed the architecture behind the products, or been responsible for
forming the component library. He can easily identify the domain concepts
from its terminology, existing system descriptions, and component services.
In our phone
application example, the domain concepts come from the UI elements (e.g.
Form, Popup), menu and button structure (user definable keys, menu) and
underlying services (e.g. SMS, web browsing). By allocating these concepts
to the modelling language and refining them further, we can create the
conceptual part of the modelling language. The goal here is to make the
chosen concepts map accurately to the domain semantics.
However,
pure domain concepts alone do not make a modelling language: we need the
domain knowledge of how they can be put together. For this domain, we
choose application flow as the basic model of computation. This describes
how the domain concepts interact during the application execution (see
Figure 1 for an example). We introduce the concepts of Start and Stop
and directed flows – with and without conditions. Conditions are
used when the user selects one of several possible choices, for example
via a list or a menu. We also add concepts for Library code, making it
possible to link in third party extensions and call them with parameters.
Next, these
basic concepts are enriched with the domain rules. Typically, the rules
constrain the use of the language by defining what kinds of connections
between concepts are possible. They can specify how certain concepts can
be reused and how models can be organized. In our phone example, rules
define which UI elements may have their own menus, which have user defined
buttons, and how different phone services may be called during the application
execution.
These rules
together with the concepts are codified and formalized with a metamodel.
A metamodel describes the modelling language, similarly to the way a model
describes a system [Bri96]. The metamodel is instantiated by the metaCASE
tool, resulting in a domain-specific modelling tool that contains the
concepts and rules of the modelling language.
To provide
the notation part of the modelling language, we define symbols to be the
graphical representations of the modelling concepts. As our example domain
is user interface related, we can base many of its symbols on the appearance
of the phone widgets themselves.
Defining
the domain framework
The domain framework provides the interface between the generated code
and the underlying platform. In some cases, no extra framework code is
needed: generated code can directly call the platform components and their
services are enough. Often, though, it is good to define some extra framework
utility code or components to make code generation easier. Such components
may already exist from earlier development efforts and products, and just
need a little tweaking.
In our example,
the Series 60 enterprise application framework already offers a good set
of services, at a higher level than base Series 60. The domain framework
thus adds only two functions: a dispatcher to execute the flow of application
logic, and view management for multi-view applications.
Developing
the code generator
Finally, we want to close the gap between the model and code world by
defining the code generator. The generator specifies how information is
extracted from the models and transformed into code. The code will be
linked with the framework and compile to a finished executable without
any additional manual effort (see Bat00). The generated code is thus simply
an intermediate by-product on the way to the finished product, like .o
files in C compilation.
The key issue
in building a code generator is how the models concepts are mapped to
code. The domain framework and component library can make this task easier
by raising the level of abstraction on the code side. In the simplest
cases, each modelling symbol produces certain fixed code, including the
values entered into the symbol as arguments. The generator can also generate
different code depending on the values in the symbol, the relationships
it has with other symbols, or other information in the model.
A simple
example of a generator definition for a Note dialog is presented in Figure
3. The Note opens a dialog with information, like "SET Registration:
Welcome" in Figure 1. Lines 1 and 6 are simply the structure for
a generator. Line 2 creates the function definition signature and line
3 a comment. Function naming is based on an internal name that the generator
can produce if the developer does not want to give each symbol its own
function name.
1
report '_Note'
2 'def '; subreport; '_Internal name'; run; '():'; newline;
3 '# Note '; :Text; newline;
4 ' appuifw.note(u"'; :Text; '", '''; :Note
type; ''')'; newline;
5 subreport; '_next element'; run;
6 endreport |
Figure
3. Code generator for Note dialog
Line 4 produces
the call for the platform service. It uses the model data (underlined
here for clarity), like the value for the Text property of the Note UI
element (in this case, "SET Registration: Welcome"). Similarly,
the modeler chose the ‘Note type’ value in the model from
a list of available notification types, like ‘info’ (here)
or ‘confirmation’ (used in "Registration made" in
Figure 1). The generated line 4 is thus (with model data underlined):
| appuifw.note(u"Conference
Registration: Welcome ", 'info') |
Since the
code generator automates the mapping from model to implementation, every
developer makes the Note dialog call similarly: the way the experienced
developer has defined it. Finally, line 5 calls another generator definition
to follow the application flow to the next phone service or UI element.
This generator, named _next element, is also used by other UI elements
similar to Notifications.
The generation
is not limited to just calling services available from components. The
components can also call back to generated code, or generated code can
inherit abstract functionality from available code and implement the concrete
functionality using design data. The generator can also produce code that
the application framework requires but is tedious to design. This minimizes
the modelling work and can also hide complexity. In our phone case, for
instance, pressing the Cancel button in a dialog need not normally be
modelled, as the generator can produce default code that backtracks to
the previous element.
Using
DSM
Domain-Specific Modelling allows faster development, based on models of
the product rather than on models of the code. Our case of phone application
development gives one example. Industrial experiences of DSM show major
improvements in productivity, lower development costs and better quality.
For example, Nokia [Kel00] states that in this way it now develops mobile
phones up to 10 times faster, and Lucent [Wei99] that it improves their
productivity by 3-10 times depending on the product. The key factors contributing
to this are:
• The
problem is solved only once at a high level of abstraction and the final
code is generated straight from this solution.
• The focus of developers shifts from the code to the design, the
problem itself. Complexity and implementation details can be hidden, and
already familiar terminology is emphasized.
• Consistency of products and lower error-rates are achieved thanks
to the better uniformity of the development environment and reduced switching
between the levels of design and implementation.
• The domain knowledge is made explicit for the development team,
being captured in the modelling language and its tool support.
Implementation
of DSM is not an extra investment if you consider the whole cycle from
design to working code. Rather, it saves development resources: Traditionally
all developers work with the problem domain concepts and map them to the
implementation concepts manually. And among developers, there are big
differences. Some do it better, but many not so well. So let the experienced
developers define the concepts and mapping once, and others need not do
it again. If an expert specifies the code generator, it produces applications
with better quality than could be achieved by normal developers by hand.
References
• Batory, D., Chen, G., Robertson, E., Wang, T., (2000) Design Wizards
and Visual Programming Environments for GenVoca Generators, IEEE Transactions
on Software Engineering, Vol. 26, No. 5.
• Brinkkemper, S., Lyytinen, K., Welke, R., (1996) Method Engineering
- Principles of method construction and tool support, Chapman & Hall
• Kelly, S., Tolvanen, J.-P., (2000) Visual domain-specific modelling:
Benefits and experiences of using metaCASE tools, International workshop
on Model Engineering, ECOOP 2000, (ed. J. Bezivin, J. Ernst)
• Nokia, (2003) Series 60 SDK documentation, version 2.0, http://www.forum.nokia.com/
• Nokia, (2004) Python for Series 60: API reference, version 1.0,
http://www.forum.nokia.com/
• Pohjonen, R., Kelly, S., (2000) Domain-Specific Modelling, Dr.
Dobb’s Journal, August.
• Weiss, D., Lai, C. T. R., (1999) Software Product-line Engineering,
Addison Wesley Longman.
|