Statestep

Embedding Code in a Model

In what follows, a decision table example is used. There would be no real difference if the model from which code was being generated was a state machine. The programming language used for the examples is Java.

Sometimes you might want to say something like, "If rule One or rule Three applies then call this function, if rule Four applies then execute this piece of code, ..." Of course, it is possible to do this by generating code from the model and adding the necessary code separately. For example, you might have rules like

Rule With Comment

Using the applyRules() method in the code generated using the standard Java template, you could then write code like this:

...
Rule rule = Rules.applyRules(Event.$decide,
   combination, null);
if (rule == Rule.decide$A)
   windsurf()
else if (rule == Rule.decide$B)
   hillwalk()
else if ...
...

The disadvantage of this approach is that the model and the code are disconnected. For example, if you make a mistake and call windsurf() instead of hillwalk() for rule B, the error won't be seen unless you're inspecting the model at the same time as the code. Also, whenever you add a new rule or change an existing rule in the Statestep model, you'll need to change the code as well.

A better alternative is to specify the outcome within the model (that is, other than as a comment) and then write the code so that it depends only on the outcome, not on the rule. Thus, the rule above might become

Rule With Outcome

and the code you write would change to

...
Rules.applyRules(Event.$decide, combination,
   null);
$Activity act = combination.get$Activity();
if (act == $Activity.$windsurf)
   windsurf()
else if (act == $Activity.$hillwalk)
   hillwalk()
else if ...
...

If your model is a finite state machine (rather than a simple decision table as in this case) then you will probably be writing some code like this anyway. However, this approach may sometimes be awkward or insufficient. For example, it may not be possible to create a nice mapping between variable values and the code to be executed — perhaps because suitably descriptive variable value names would become unreasonably long, or maybe there are some rules for which one method should be called and others where you want to invoke four or five different methods.

For such cases, you can add executable code to a rule by embedding it within a comment in the rule's formula field. For example:

Rule With Embedded Code

Here, we're saying that the method hillwalk() should be called whenever rule B applies. Note that special comments containing program code ("hillwalk();") must somehow be distinguished from ordinary comments ("go hillwalking"). The convention used here is to treat any comment line starting with "#:" as source code.

Now all that's needed is a way to have this code extracted and copied whenever code is generated from the model. A little extra code added to the code generation template does the trick. For Java code generation, you can add the file RuleCode.java.ftl to the other FTL files in the template package. When you process the template with FMPP, the resulting RuleCode.java will contain code like:

public class RuleCode
{
   public static void execute(Rule rule)
   {
      if (rule == Rule.decide$A)
      {
          windsurf();
      }
      else if (rule == Rule.decide$B)
      {
          hillwalk();
      }
      ...

This is similar to the code we saw first, except that this time it's been automatically extracted from the model. In your own code you now need only call the execute() method:

...
Rule rule = Rules.applyRules(Event.$decide, 
   combination, null);
RuleCode.execute(rule);
...

This approach works well for code generation but it does mean "contaminating" the Statestep model with the source code of a particular programming language, that is, with low level implementation details. If your model is also to serve as a specification, you might want to consider using a script to strip out any embedded source code before passing a HTML version of the model to reviewers.

Variations

Variations on this idea are possible. For example, the embedded code might be identified in a different way (or perhaps all comments can be assumed to be code) or the template might be changed to take the contents of any comments in a rule formula and echo them as strings to the output.

Another possibility is to implement Rules.ExtraLogic and so allow code embedded in a rule to change the values of variables in the next state or to veto the rule. You can do this by taking the same template code and simply changing the lines:

public class RuleCode
{
   private RuleCode() { }

   public static void execute(Rule rule)
   {
<@code_for_rules/>
   }

to

public class RuleCode implements Rules.ExtraLogic
{
   public boolean confirmRule(Rule rule,
      Combination current, Combination next)
   {
<@code_for_rules/>
      return true;
   }

In your own Java code, you would then pass an instance of this class to Rules.applyRules(), for example:

...
Rules.ExtraLogic logic = new RuleCode();
Rules.applyRules(Event.$decide, comb, logic);
...

You might then have rules with code like this:

Rule with embedded decision code

or with code which can veto the rule - that is, which helps to determine whether or not the rule applies:

Rules with embedded vetoing code

Note that Statestep reports a conflict between these two rules. That's because Statestep ignores comments and so the two rules appear to specify different outcomes in the same cases. The preceding rule, which is equivalent to the two rules above, avoids this problem.

Questions, comments? info3@statestep.com