RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Domain-specific Modeling: Making Code Generation Complete : Page 4

Domain-specific modeling is most successful when the models let you generate complete working code, without the need for post-generation code modifications or additions. The examples and guidelines in this article show you how.

Example 3: Generating Python for Mobile Phones
Navigating models based on connections is just one possible way of translating models to code. To illustrate other ways generators can work here's a case that generates SmartPhone applications by producing function definitions for individual model elements. Here the underlying phone platform, Symbian/S60 and its Python framework, provides a set of APIs and expects a specific programming model for the user interface. To enable model-based generation, a specification language and generator follows the programming model and APIs. Figure 3 shows a sample design.

The modeling concepts in Figure 3 are based directly on the services and widgets that S60 phones offer for application development. Modelers describe the behavioral logic of the application mostly based on the widgets' behavior and on the actions provided by the actual product. If you are familiar with some phone applications, like phone book or calendar, you can probably understand what the application does by studying the model.

Figure 3. Conference Application: The figure shows the design for a conference application intended to run on a Symbian/S60 phone.
From the design in Figure 3, the generator produces function-based code that the target device or an emulator can compile and execute. The generator itself is structured into modules, one generator module for each modeling concept. For example, one generator module takes care of lists, another handles confirmation dialogs etc. Because several concepts require generation of similar code, such as flow of control to the next concept, parts of the generator definitions are made into subroutines used in several places. The generator includes some framework code for dispatching and for multi-view management (different tabs in the pane). Here's some sample Python code generated from the design in Figure 3.

   01  import appuifw
   02  import messaging
   04  # This app provides conference registration by SMS.
   33  def List3_5396():
   34  # List Check Credit card Invoice 
   35     global Payment
   36     choices3_5396 = [u"Check", u"Credit card", u"Invoice"]
   37     Payment = appuifw.selection_list(choices3_5396)
   38     if Payment == None:
   39        return Query3_1481
   40     else:
   41        return SendSMS3_677
   85  def SendSMS3_677():
   86  # Sending SMS Conference_registration
   87  # Use of global variables
   88     global PersonName
   89     global Payment
   90     string = u"Conference_registration "\
   91           +unicode(str(PersonName))+",  "\
   92           +unicode(str(Payment))
   93     messaging.sms_send("4912345678", string)
   94     return Note3_2227
   101  def Stop3_983():
   102  # This applications stops here
   103     return appuifw.app.set_exit
   107  f = Note3_2543
   108  while True:
   109     f = f()
The generator starts by outputting module import statements (lines 1—2) based on the services used. First, the overall application UI framework, and then—because the model contains SMS actions (yellow envelope symbols)—the messaging module. The comment following the import statements is simply taken from the documentation entry specified in the design. Next, the code defines each service and widget as its own function. Rather than producing functions in an arbitrary order, the generator produces functions arranged by type, for example, all list functions followed by SMS/text message functions etc.

Lines 33—41 describe the code for the payment method selection that uses a list widget. After defining the function name and comment, the code declares a global Payment variable. Line 36 shows the list values as Unicode in a local variable, and line 37 calls the List widget provided by the framework. The code handles sending SMS messages (lines 85—94) in a similar way to the List widget. Line 93 calls the imported SMS module's sms_send function. The generator takes the parameters to the function (recipient number, message keyword and content) from the model, and handles forming the right message syntax. These messages are clearly defined, always using the same pattern.

The end of each function includes code to call the next function based on user input. For sending an SMS, the generator simply follows the application flow (line 94), but for list selections, the situation is little more complex. Depending on the user's selection from the list, different alternatives can exist. While in this case the code always takes a single path forward regardless of the value chosen from the list, there is the implicit possibility of a cancel operation (pressing the Cancel or Back button). The generator automatically creates operation-cancelling code to return execution to the previous widget (lines 38—39), or if a choice was made, moves on to send the SMS (lines 40—41). Having the DSM implicitly handle Cancel or exception actions is just one extra way to make describing applications simpler. In other words, the modeler doesn't need to do anything in most cases, only specifying behavior that differs from the default (such as the diagonal Cancel relationship to the end state from the first menu).

In the final function, the generator creates application exit code based on the application's end state (see lines 101—103). Finally, a dispatcher starts the application by calling the first function (line 107). This function, like all the others, returns the next function to call, and lines 108—109 handle calling the next function after each function has finished. Handling the calls this way, rather than having each function itself call the next function, provides a kind of tail recursion to reduce stack depth when moving from one function to the next.

This case highlights an interesting benefit of DSM; the modeling language is totally independent of the generated programming language. As Symbian phones also support C++ and Java, you can change the generator without changing the designs to generate an identically behaving application in a different target language.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date