As calls for increased software development productivity continue to mount across industry sectors, companies are constantly searching for effective ways to satisfy this demand. A proven approach to improving productivity and quality is to increase the use of automation. In software development this means using code generators and languages at a higher level than traditional programming languages such as C or Assembler. Domain-specific modelling (DSM) focuses on the use of visual models as primary artefacts in the development process. DSM raises the level of abstraction beyond programming by specifying the solution directly using domain concepts. Final products are then generated from these high-level specifications.
Let's start by looking at two examples of DSM: interaction in user interfaces and control logic. Figure 1 shows an example of designing the UI for an embedded device, an automotive infotainment system. The model is based on a language that addresses the elements of display, interaction and user navigation. The modelling concepts are therefore directly related to the infotainment system, rather than to the implementation language used in programming. From this high-level model code for running the UI part of the infotainment system is generated. In fact, several generators can be supplied; for example, one for early prototyping, another for producing production code in C, and one for enabling model debugging when executing the generated code.
Figure 2 shows an example describing control logic: how voice commands are formed when controlling a home automation system. To develop such a voice menu system engineers need to specify operations such as playing back segments of speech, waiting for use input, timing out, cycling through options and linking them together. The domain-specific language applies these same concepts directly as language constructs. This allows the developer to specify the system in terms of familiar and high-level constructs: the kind of language found in requirements documents rather than in programming languages. Again, from these high-level models the tool can generate production quality code for the target 8-bit microcontroller.
As the examples show, DSM language allows developers to use concepts that directly mirror real-world ideas, while capturing all the necessary information needed to develop software applications or systems fully and completely. In the examples the symbols in the domain-specific models map to things in the respective problem domains – the world in which the application is to be used. Once these high-level models are created, code can then be automatically generated from them using customised code generators. Code can be produced in any programming language or for any development paradigm. Existing platforms, libraries, components and legacy code can all be effectively utilised during the generation process.
While DSM does not expect that all code is generated from the models, it does take the position that generated code should be good enough that it does not need to be changed manually later. The generated code is functional and efficient: the generator is specified by the lead developer in the domain, not the tool vendor. The code will therefore be exactly what the lead developer would teach his developers to write – and the generator will follow those instructions exactly and reliably, so quality and consistency also improve.
DSM can achieve these improvements because it narrows down the design space or domain, often to a single range of products for a single company. There are different modelling languages for specifying different kinds of medical devices, but within a family of them the language can be the same. For example, a DSM language for pacemakers will have different concepts from one for insulin pumps, but the concepts for insulin pumps and another drug delivery system could well be similar. This domain-specificity is at the heart of DSM and is the source of its dramatic productivity improvements.
Does the theory work in practice? Let's look at three cases of embedded software development. Polar made a study in which six engineers implemented features for a heart rate monitoring device using DSM. The engineers measured the productivity improvement to be 750% compared to manual practices.
Panasonic ran a similar comparison but implemented the same features with traditional coding and DSM. The productivity with DSM was about 500% higher than manual coding, measured over the whole lifecycle from design to running production code. Finally, in large-scale use at Nokia, mobile phone developers found a 1,000% productivity increase: development time for a typical feature reduced from two weeks to one day.
Productivity is not the only benefit. For critical applications such as military equipment or medical devices the quality matters more. US Air Force studies have shown that with a domain-specific language and generator there were 50% fewer errors than in applications developed with traditional manual practices.
The domain-specific language itself contributes to the improved quality, by disallowing the creation of structures that are illegal or lead to poor performance. Preventing errors at this early stage is also cheaper than only finding them during testing. EADS found the quality of the DSM-generated code for its TETRA terminals was clearly better, because the modelling language eliminated errors right from the design stage.
Implementing a DSM solution
For the best fit to the domain, the DSM language and generator are typically defined within a single company. The expert developer(s) defines a domain-specific language containing the chosen domain's concepts and rules, and specifies the mapping from that to code in a domain-specific code generator. In effect, all he is saying is 'this is how I look at the world of our products, and this is how I write code for them.'
Best practice for language and generator implementations is to build them incrementally: first build a little of the language, model a little, define generators, make some changes to the language, model some more and so on. This makes language creation agile and has a major influence on how quickly you can build the language. Giving the language to candidate users early gets them involved and ensures you get feedback early. Your understanding of a domain will almost always, even if you are an expert in it, improve while you define a language for it. Even after you take your language into use, your understanding of your domain will improve through modelling or from getting feedback from others that model with the language you defined. Partly you will understand the domain better, and partly you will see possible improvements for your language.
The process for implementing DSM can be divided into four steps:
Identifying domain abstractions and concepts and how they work together
Specifying the language concepts and their rules in a tool (metamodel)
Creating the visual representation of the language (notation)
Defining the generators for code, model checking, documentation and so on.
1. Abstractions. The most important part is finding the right abstractions. Although it often feels easier to have low-level language concepts (such as mapping a class diagram to a class structure), it is better to map concepts to the problem domain and thus raise the abstraction level. This way, you can help prevent errors early in the design phase, minimise specification work, and at the same time make the language more suitable for true generation purposes. Describing things in problem domain terms instead of implementation concepts is also good future-proofing. We should not think of models as visualising code. Instead, we can describe systems with higher-level abstractions than current programming languages offer, just as it was better to move to C rather than trying to visualise Assembler code.
2. Language constructs. Obviously, you want your developers to follow the abstractions, obey architectural rules and reuse model components when appropriate. Putting these abstractions and rules right in the language saves developers from having to refer constantly to in-house 'design guidelines' documents – which are probably out of date anyway. As a language designer, you decide between guidance and freedom. During this phase, you specify the modelling concepts, their properties and the rules that constrain the use of the language and enforce model correctness. You will generally map the major domain concepts to modelling language objects, while others will be captured as object properties, connections, sub-models or links to models in other languages.
3. Notation. Next, you need a visual representation of the language, usually a diagram, but sometimes a matrix, table or plain text. The pictures in this article illustrate representations of different graphical modelling languages where the symbols and icons inside the pictures represent different language concepts. Good DSM tools allow you to define your own notation as it makes models much easier to create, read and maintain.
4. Generators. Ultimately, you want to transform your models into code for interpretation or compilation into an executable. Building a generator is about defining how model concepts are mapped to code or other output. In the simplest case, each modelling symbol produces certain fixed code that includes as arguments the values entered into the symbol by the modeller. Generators also take relationships with other symbols or other model information into account.
The first of these steps happens largely in the expert developer's head, but the other steps are significantly helped by good tool support. Ideally, a single integrated tool will support all three steps, and also provide the editors for developers to model in. This makes the process of language and generator developer WYSIWYG: the expert developer can instantly see the results of his actions in the models and in the generated code.
Mature tools will even automatically update existing models as the language definition is updated. Using a tool like this, an experienced developer can create a DSM language and generator for his domain from scratch in two to three weeks. Other developers can then design with the resulting DSM language, and use the generator to produce actual products from their models.
Where to apply
While the key benefits of DSM – improved productivity and quality – are desirable in just about every organisation, as a development approach DSM is not a panacea. When building applications for the first time in a new domain, it is illogical to assume that one is going to be able automate the process at the beginning. The organisation must be familiar with what it is doing before it starts to automate development practices.
Consequently, companies that work on short-term projects, unaware of the general requirements of the next customer, are unlikely to achieve much success with DSM. But for those organisations that make a range of similar products – a product line or family – or build applications on top of a common library or framework, the benefits of DSM are nothing short of astounding.