3.2 The Modeling Language
The single most important asset of a DSM environment is the
domain-specific modeling language. To substantiate this claim, let us consider
the payback promised by the DSM approach. The labor of the domain experts who
create the DSM environment is the original investment on the DSM. The return of
investment, then, is a result of the increased productivity of the developers
working with the DSM environment. While the code generator and the domain
framework are important parts of the DSM environment, they still remain
reasonably invisible for the developer where as the role of the modeling
language is emphasized as the main instrument of the DSM. Thus, the better
modeling language we have the more we benefit from the DSM.
The first rule of thumb for creating a domain-specific
modeling language is to keep the language as independent as possible from the
target code. We know that it often appears originally easier to try to build the
modeling language as an extension on top of the existing code base or platform,
but this kind of visualization of the code world very seldom lead to a
significant rise in the level of abstraction and it definitely does not free the
developer to think according to the domain instead of the code. Thus, to achieve
the best possible level of abstraction for our modeling language, we need to
base it on the domain itself.
First, ask yourself what do you want to do with the
domain-specific modeling language. When you have set this mission statement for
yourself, you can proceed by asking how can you do what you want and what is
needed to do that. This analysis leads to the discovering of the first domain
concepts that are to be incorporated into the modeling language. For example,
our mission statement for the watch modeling language set the following goal: we
want to be able to model those static and behavioral elements that constitute a
digital wristwatch. Based on this statement, the further analysis soon
identified a watch model, display, logical watch and a watch application as the
elementary concepts of the watch architecture.
At this early stage of the modeling language definition,
one should focus on identification and definition of domain concepts. There are
several ways to do this and it is important to understand that usually none of
them alone can provide a complete coverage. Good results typically require
concurrent use of a number of various strategies. In any case, the key success
factor in finding the domain concepts is the domain knowledge possessed by the
domain experts.
A good way to identify the domain concepts is to study the
aggregation structures within the domain and product. The aforementioned
elementary watch concepts were discovered this way. Another method is to try to
find the commonality and variability among the products. For example, it is easy
to see that the different watch models still share the common concept of button
that would suggest button as a probable domain concept for the modeling
language. Similarly, we can see that the watch models differ from each other by
the number of buttons and features they include, which says something about the
configuration space requirement for the watch models.
It is also worthwhile to examine the existing
specifications to see if there are any repeating patterns that could be refined
further as a domain concept. And don’t forget the common wisdom or
folklore as a source for ideas – our decision to use the state machine as
the computational foundation for watch applications and logical watches was
based on the fact that it is a widely used solution in the area of embedded
systems in general.
The next step after the identification of domain concepts
is to assemble them as a modeling language. The language is defined with
MetaEdit+ as a metamodel that applies the domain concepts as the semantic
structures for the language. The detailed description of the metamodelling
process is out of the scope of this tutorial, so for more comprehensive
information about the metamodelling please refer to the Family Tree example in
the Evaluation tutorial and ‘MetaEdit Method Workbench: User’s
Guide’.
Two important aspects should be considered during the
creation of the modeling language: layering and reuse. Modeling language
development efforts typically start with a flat model structure that has all
concepts arranged on the same level without any serious attempts to reuse them.
However, as the complexity of the model increases while the number of elements
increases, the flat models very seldom are suitable for presenting hierarchical
and modularized software products. Thus, we need to be able to present our
models in layered fashion.

Figure 3-2. Watch model hierarchy
A partial illustration of
watch model hierarchy is presented in
Figure 3-2. The watch model hierarchy
consists of three layers. For the top-layer models we use a proprietary
WatchFamily diagram type to present the static high-level configuration of each
watch model. On the two subsequent layers we employ the WatchApplication diagram
type to present the dynamic variability within the logical watches and watch
applications. As any additional diagram type increases the complexity of the
modeling language, it is recommended to design diagram types recursive manner so
that they can be applied on more than just one layer. On the other hand, if the
semantics of two consequent layers are different, two different diagram types
are the recommended solution.
Another aspect that influences the layer structure is
reuse. The idea of reuse-based layering is to treat each model as a reusable
component for the models on the higher level. In this kind of solution, the
reusable element has a canonical definition that is stored somewhere and
referenced from where needed. In the watch example, the whole layering is
actually based on this principle. Each watch application is a true model
component and can be referenced from any logical watch. Similarly, each logical
watch can be attached to any concrete watch model.
Reuse can also happen regardless or in addition to the
layering. Typically we want also reuse the concepts within or between the
models. The concept of a display function is an example of reuse within a model.
Defined once in a WatchApplication diagram, each display function can be
referenced by any state within the same diagram. Reuse between the models is
needed when the same concept appears on several models. Examples of this kind of
concept within the watch example are the buttons. While it is possible to create
a new button concept for each state transition, it is much better idea to reuse
an existing one. It is not only faster to create button this way, but it also
makes it easier to propagate the possible future changes (like changing the name
of the button). This kind of reuse differs from those described above in the
sense that there is no canonical definition for the reusable element. It can be
considered as a floating concept that exists as long as it is instantiated
somewhere.
The last step during the initial development of a
domain-specific modeling language is the finalization of the language. Typically
this means the extension of the language with concepts that are required for
code generation, component interfaces, consistency checking and documentation.
In watch example, the inclusion of the watch domain framework code as included
components in WatchFamily diagram is an example of this kind of late addition.
With this solution we wanted to ensure that the framework code is always
available for the code generation. Otherwise, and probably a bit surprisingly,
no other code or documentation generation related additions or modifications to
the original modeling language were needed.