Editor’s Note: In Part 2 in a series excerpted from their book “Domain Specific Modeling: Enabling full-code generation,” the authors use the example of mobile phone software design to illustrate the differences between domain specific modeling and model driven approaches.
To illustrate the use of general-purpose modeling and domain-specific modeling outlined in Part 1, let’s go through a small example. For this illustration, we use a domain that is well known since it is already in our pockets: a mobile phone and its applications.
Our task as a software developer for this example is to implement a conference registration application for a mobile phone. This small application needs to do just a few things: A user can register for a conference using text messages, choose among alternative payment methods, view program and speaker information, or browse the conference program via the web. These are the basic requirements for the application.
In addition to these requirements, software developers need also to master the underlying target environment and available platform services. When executing the application in a mobile phone or other similar handheld device, we normally need to know about the programming model to be followed, libraries and application program interfaces (APIs) available, as well as architectural rules that guide application development for a particular target environment.
We start the comparison by illustrating possible development processes, first based on a general-purpose modeling language and then based on a domain-specific modeling language. UML is a well known modeling language created to specify almost any software system. As it is intended to be universal and general-purpose according to its authors, James Rumbaugh it can be expected to fit our task of developing the conference registration application. The domain-specific language is obviously made for developing mobile applications.
UML usage scenario
Use of UML and other code-oriented approaches normally involves an initial modeling stage followed by manual coding to implement the application functionality. Design models either stay totally separate from the implementation or are used to produce parts of the code, such as the class skeletons.
The generated code is then modified and extended by filling in the missing parts that could not be generated from UML models. At the end of the development phase, most of the models made will be thrown away as they no longer specify what was actually developed while programming the application. The cost of updating these models is too high as there is no automation available.
Modeling Application Structure Let’s look at this scenario in more detail using our conference registration example. The common way to use UML for modeling starts with defining the use cases, as illustrated in Figure 2 . For each identified use case, we would specify in more detail its functionality, such as actions, pre- and postconditions, expected result, and possible exceptions.
We would most likely describe these use cases in text rather than in the diagram. After having specified the use cases, we could review them with a customer through a generated requirements document or, if the customer can understand the language, at least partly with the diagram.
Although use cases raise the level of abstraction away from the programming code, they do not enable automation via code generation. Use case models and their implementation stay separate. Having identified what the customer is looking for, we would move to the next phase of modeling: Define a static structure of the application with class diagrams, or alternatively start to specify the behavior using sequence diagrams or state diagrams. A class diagram in Figure 3 shows the structure of the application: some of the classes and their relationships.
While creating the class diagram, we would start to consider the application domain: what widgets are available and how they should be used, where to place menus, what is required to send text messages, and so forth. Unfortunately, UML will not help us at all since it does not know anything about mobile applications.
Our job as developers is to first find a solution using the domain concepts and then map the solution into the UML concepts. So instead of describing the phone application, we would describe classes, their attributes and operations, and various connections they may have. Even if our class diagram only targets analysis or is platform independent, it would not change the situation as we would still be using implementation concepts to describe our solution.
Adding Implementation Details to the Models In a later design phase, we need to extend the analysis model with implementation details. Here we would expect the coding concepts of the class diagram to be helpful as they map to implementation details, but in reality UML helps us very little during the application design.
We could draw whatever we like into the class diagram! It would be relatively easy, and likely too, to end up with a design that will never work, for example, because it breaks the architecture rules and programming model of the phone. To make the model properly, we need to study the phone framework, find out its services, learn its API, and study the architectural rules.
These would then be kept in mind while creating the models and entering their details. For instance, sending text messages requires that we use a SendSMS operation (Figure 3 ) and give it the right parameters: a mandatory phone number followed by a message header and message contents.
After finishing the class diagram, we could generate skeleton code and continue writing the code details, the largest part, manually. Alternatively, we could continue modeling and create other kinds of designs that cover those parts the class diagram did not specify. Perhaps even in parallel to static structures, we would also specify what the application does. Here we would start to think about the application behavior, such as menu actions, accessing the web, user navigation, and canceling during the actions.
Modeling Application Behavior In the UML world, we could apply state machines, collaboration diagrams, or perhaps sequence diagrams to address application behavior. With a sequence diagram, our designs could look something like Figure 4 .
When specifying the interaction between the objects, we would need to know in more detail the functionality offered by the device, the APIs to use, what they return, the expected programming model to be followed, and architectural rules to be obeyed. We simply can’t draw the sequence diagram without knowing what the phone can do! So for many of the details in a design model, we must first consult libraries and APIs.
Unfortunately, sequence diagrams would not be enough for specifying the application behavior as they don’t adequately capture details like alternative choices or decisions. We can apply other behavioral modeling languages, like activity diagrams or state diagrams, to specify these.
Figure 5 illustrates an activity diagram that shows how the application handles conference unregistration. This model is partly related to the code, for example, through services it calls, but not adequately so that it could be used for code generation. We could naturally fill more implementation details into the activity diagram and start using the activity modeling language as a programming language, but most developers switch to a programming language to make it more concise.
If we were to continue our example, the activity diagrams could be made to specify other functions as well, but to save space we have omitted them. We should also note that there is no explicit phase or time to stop the modeling effort. How can we know when the application is fully designed without any guidance as to what constitutes a full design?
If we had UML fever, we could continue the modeling effort and create further models. There are still nine other kinds of modeling languages. Should we use them and stop modeling here or should we have stopped earlier?
Since development is usually iterative in this model creation process, we most likely would also update the previously made class diagrams, sequence diagrams, activity diagrams, etc. If we wouldn’t do that our models would not be consistent. This inconsistency might be fine for sketching but not for model-driven development.
Implementing the Application The example models described earlier are clearly helpful for understanding and documenting the application. After all the modeling work, we could expect to get more out of the created models too. Generate code perhaps? Unfortunately a skeleton is the best we can generate here and then continue by modifying the generated code to implement the functionality and logic—the largest part of the application. To get the finished application, we would implement it by writing the application code.
At this point, our models and code start to be separate. During the programming, we will face aspects that were inadequately specified, false, or totally ignored while modeling. It is also likely that our design models did not recognize the architectural rules that the application must follow to execute.
After all, UML models did not know about the libraries, framework rules, and programming model for our mobile applications. As the changes made to the code during implementation are no longer in synch with the designs, we need to decide what to do with the models.
Should we take the time to update the models or ignore them and throw them away? Updating the models requires manual work as the semantics of the code is different than most of the concepts used in UML models. Even keeping part of the class diagram up-to-date in parallel with the code does not help much since it just describes the implementation code.DSM usage scenario
Next let’s contrast the above UML approachto DSM. Here the modeling language is naturally made for developingapplications for mobile phones. Figure 1.6 shows a model that describesthe conference registration application.
If you are familiarwith some phone applications, like a phone book or calendar, you mostlikely already understand what the application does. This model alsodescribes the application sufficiently unambiguously, that it can begenerated from this high-level specification. Take a look of themodeling in Figure 1.6 and then compare it to UML models that did notget even close to having something running.
Indomain-specific modeling we would start modeling by directly using thedomain concepts, such as Note, Pop-up, SMS, Form, and Query. These arespecific to the mobile phone’s services and its user-interface widgets.The same concepts are also language constructs.
They are not newor extra concepts as we must always apply these regardless of how themobile application is implemented. With this modeling language, we woulddevelop the conference registration application by adding elements tothe model and linking them together to follow the flow of navigation andapplication control.
The domain-specific modeling language alsoincludes domain rules that prevent us from making illegal designs. Forexample, after sending an SMS message, only one UI element or phoneservice can be triggered. The modeling language “knows” this rule andwon’t let us draw another flow from an SMS element.
If arelevant part of the design is still missing, for example, theapplication never reaches a certain widget, model checking reports warnus about incomplete parts. This means that we do not need to master thedetails of the software architecture and required programming model, andwe can focus instead on finding the solution using the phone concepts.
Ascan be seen from this DSM example, all the implementation concepts arehidden from the models and are not even necessary to know. This showsthat the level of abstraction in models is clearly higher. Once thedesign, or a relevant part of it, is done, we can generate and executethe conference registration application in a phone.
There is noneed to map the solution manually to implementation concepts in code orin UML models visualizing the code. Unlike with UML, in DSM we stoppedmodeling when the application was ready. If the application needs to bemodified, we do it in the model.
For the DSM case, we left thecode out of the scenario since it is not so relevant anymore. This is insharp contrast to the UML approach, where the modeling constructsoriginate from the code constructs. Naturally in DSM code is alsogenerated, but since the generator is defined by the developers of theDSM language and not by the developers of this particular mobileapplication, we won’t inspect the implementation in code here.
Comparing UML and DSM
Theabove example illustrates several key differences betweengeneral-purpose and Domain-Specific Modeling languages. Do thecomparison yourself and think about the following questions:
- Which of these two is a faster way to develop the application?
- Which leads to better quality?
- Which language guided the modeler in developing a working application
- Which specifications are easier to read and understand?
- Which requires less modeling work?
- Which approach detects errors earlier or even prevents them from happening?
- Which language is easier to introduce and learn?
Nodoubt, DSM performed better compared to UML or any other general-purpose language. For example, the time to develop the application usingDSM is a fraction of the time to create the UML diagrams and write thecode manually. DSM also prevents errors early on since the language doesnot allow illegal designs or designs that don’t follow the underlyingarchitectural rules.
The code produced is also free of mostkinds of careless mistakes, syntax, and logic errors since a moreexperienced developer has specified the code generator. We inspect theeffect of DSM development on productivity, product quality, and requireddeveloper expertise in more detail in the next chapter.
Oneexample obviously cannot cover the wide spectrum of possible developmentsituations and application domains. The mobile example is one ofthousands, if not hundreds of thousands, of different applicationdomains.
In principle, different DSM solutions can be used inall of them since every development project needs to find a solution inthe problem domain and map it into an implementation in the solutiondomain. All development projects have faced the same challenge.
Thebenefits of DSM are readily available when the DSM solution—thelanguage and generator—is available. Usually that is not the case as weneed to develop the DSM solution first.
Juha-Pekka Tolvanen has been involved in domain-specific languages, code generators and related tools since 1991. He works for MetaCase and has acted as a consultant world-wide for modeling language and codegenerator development. Juha-Pekka holds a Ph.D. in computer sciencefrom the University of Jyväskylä, Finland.
Steven Kelly is chief technical officer of Metacase and cofounder of the DSM Forum. He is architect and lead developer of MetaEdit+, Metacase’s DSM tool.
Used with permission from Wiley-IEEE Computer Society Press, Copyright 2014, this article was excerpted from Domain-Specific Modeling: Enabling Full Code Generation , by Steven Kelly and Juha-Pekka Tolvanen.