Declarative vs. procedural configuration style

Author: Timo Laitinen
Date: 2004-10-02

Contents

1. Different configuration styles
2. Procedural configuration style
3. Declarative configuration style
4. Example: Refactoring code from procedural to configuration style
4. 1. Original JIC file
4. 2. Step 1: Move values from actions
4. 3. Step 2: Remove action attributes that set properties
4. 4. Step 3: The use of variable PARENT is implicit in action attributes
4. 5. Step 4: Move values from contructors to child elements
4. 6. Step 5: Move the values into CDATA sections
4. 7. Step 6: Use attributes class and parameters instead of instance
4. 8. Step 7: String-valued CDATA elements don't need a constructor
4. 9. Step 8: Take advantage of element types

1. Different configuration styles

JIC Language makes it possible to write the configuration in more than one way. This chapter tries to describe two different styles for writing JIC code: declarative and procedural configuration styles.

Real-world configurations will probably mix both styles. However, the understanding of these two approaches makes the JIC Language easier to understand.

2. Procedural configuration style

Producedural configuration style is simpler than the declarative one. It is based on the use of attributes action and instance, which form a sort of core of the JIC Language. The attributes are described in more detail later.

An example of a procedural styled configuration:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame('This is a JFrame')">
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="PARENT.add(this)"  instance="new javax.swing.JLabel('This is a JLabel')"/>
    <opaque  action="PARENT.setOpaque(true)"/>
    <background  action="PARENT.setBackground(this)"  instance="new java.awt.Color(200,90,90)"/>
  </contentPane>
  <size  action="PARENT.setSize(this)"  instance="new java.awt.Dimension(300,300)"/>
</jframe>

The example creates a javax.swing.JFrame with a javax.swing.JLabel inside it. Few of the properties of the content-pane are set (background and opaque).

Attributes action and instance contain simple Java commands. It is relatively easy for a Java programmer to understand what is "happening" when the configuration is processed although he/she would have only a little knowledge of the JIC Language.

On the other hand, the configuration is more difficult to understand for a non-Java programmer. Most of the information is in Java commands, including data values (numbers, Strings and booleans). The configuration is not as structured as in the declarative style - Java expressions are not XML and are difficult to manipulate with XSLT, for example.

However, procedural configuration style is easy to learn. And it is not always important to write the configuration in a structured way.

3. Declarative configuration style

Declarative configuration style builds upon the procedural style. It is based on the semantics of the core attributes action and instance, but takes also advantage of other JIC Language features that make the configuration more declarative and structured.

Declarative style tries to minimize the existence of Java expressions. All of the shortcuts available in JIC Language that make the Java commands simpler are used. All actual data values such as numbers, String and booleans are put in CDATA sections.

Here is the same JFrame-example rewritten with the declarative configuration style:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  class="javax.swing.JFrame"  parameters="title">
  <title>This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  class="javax.swing.JLabel"  parameters="text">
      <text>This is a JLabel</text>
      <opaque  type="boolean">false</opaque>
    </label>
    <opaque  type="boolean">true</opaque>
    <background  type="color">200,90,90</background>
  </contentPane>
  <size  class="java.awt.Dimension"  parameters="w,h">
    <w  type="int">300</w>
    <h  type="int">300</h>
  </size>
</jframe>

4. Example: Refactoring code from procedural to configuration style

This chapter shows step-by-step the operations needed for refactoring the procedural-style version of the JFrame example above into the declarative-style version.

This example also demonstrates the different features of JICE.

4. 1. Original JIC file

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame('This is a JFrame')">
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="PARENT.add(this)"  instance="new javax.swing.JLabel('This is a JLabel')"/>
    <opaque  action="PARENT.setOpaque(true)"/>
    <background  action="PARENT.setBackground(this)"  instance="new java.awt.Color(200,90,90)"/>
  </contentPane>
  <size  action="PARENT.setSize(this)"  instance="new java.awt.Dimension(300,300)"/>
</jframe>

4. 2. Step 1: Move values from actions

First we normalize the action attributes by replacing all data values with variables.

This change applies only to the element <opaque>.

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame('This is a JFrame')">
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="PARENT.add(this)"  instance="new javax.swing.JLabel('This is a JLabel')"/>
    <opaque  action="PARENT.setOpaque(this)"  instance="true"/>
    <background  action="PARENT.setBackground(this)"  instance="new java.awt.Color(200,90,90)"/>
  </contentPane>
  <size  action="PARENT.setSize(this)"  instance="new java.awt.Dimension(300,300)"/>
</jframe>

4. 3. Step 2: Remove action attributes that set properties

The element type bean is the default element type. It uses all additional inner value elements for setting properties. We can therefore remove all action attributes that only set the properties of their parent i.e. attributes of form PARENT.setXXXX(this), where XXXX equals to the name of the element. This applies to the action attributes of elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame('This is a JFrame')">
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="PARENT.add(this)"  instance="new javax.swing.JLabel('This is a JLabel')"/>
    <opaque  instance="true"/>
    <background  instance="new java.awt.Color(200,90,90)"/>
  </contentPane>
  <size  instance="new java.awt.Dimension(300,300)"/>
</jframe>

4. 4. Step 3: The use of variable PARENT is implicit in action attributes

We can remove the variable PARENT from the action attributes, because a method call in the action will always point to the PARENT by default. This applies to the elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame('This is a JFrame')">
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  instance="new javax.swing.JLabel('This is a JLabel')"/>
    <opaque  instance="true"/>
    <background  instance="new java.awt.Color(200,90,90)"/>
  </contentPane>
  <size  instance="new java.awt.Dimension(300,300)"/>
</jframe>

NOTE: we can't remove the PARENT from the constructor of the element <contentPane>.

4. 5. Step 4: Move values from contructors to child elements

After handling the actions, we can refactor the constructors next.

Replace the values in the Java expressions with variables that point to child elements. This way the values are given a name and it becomes more clear what the values mean. For example, now we know that the text given to the constructor of JFrame specifies the title.

This change applies to constructors of elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame(title)">
  <title  instance="'This is a JFrame'"/>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  instance="new javax.swing.JLabel(text)">
      <text  instance="'This is a JLabel'"/>
    </label>
    <opaque  instance="true"/>
    <background  instance="new java.awt.Color(red,green,blue)">
      <red  instance="200"/>
      <green  instance="90"/>
      <blue  instance="90"/>
    </background>
  </contentPane>
  <size  instance="new java.awt.Dimension(width, height)">
    <width  instance="300"/>
    <height  instance="300"/>
  </size>
</jframe>

4. 6. Step 5: Move the values into CDATA sections

Move all the actual data values from constructors to CDATA sections:

This change applies to the elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  instance="new javax.swing.JFrame(title)">
  <title  instance="CDATA">This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  instance="new javax.swing.JLabel(text)">
      <text  instance="CDATA">This is a JLabel</text>
    </label>
    <opaque  instance="java.lang.Boolean.valueOf(CDATA)">true</opaque>
    <background  instance="new java.awt.Color(red,green,blue)">
      <red  instance="java.lang.Integer.valueOf(CDATA)">200</red>
      <green  instance="java.lang.Integer.valueOf(CDATA)">90</green>
      <blue  instance="java.lang.Integer.valueOf(CDATA)">90</blue>
    </background>
  </contentPane>
  <size  instance="new java.awt.Dimension(width, height)">
    <width  instance="java.lang.Integer.valueOf(CDATA)">300</width>
    <height  instance="java.lang.Integer.valueOf(CDATA)">300</height>
  </size>
</jframe>

4. 7. Step 6: Use attributes class and parameters instead of instance

All constructors that are new operations can be written with attributes class and parameters instead of attribute instance. This applies to the elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  class="javax.swing.JFrame"  parameters="title">
  <title  instance="CDATA">This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  class="javax.swing.JLabel"  parameters="text">
      <text  instance="CDATA">This is a JLabel</text>
    </label>
    <opaque  instance="java.lang.Boolean.valueOf(CDATA)">true</opaque>
    <background  instance="new java.awt.Color(red,green,blue)">
      <red  instance="java.lang.Integer.valueOf(CDATA)">200</red>
      <green  instance="java.lang.Integer.valueOf(CDATA)">90</green>
      <blue  instance="java.lang.Integer.valueOf(CDATA)">90</blue>
    </background>
  </contentPane>
  <size  class="java.awt.Dimension"  parameters="width,height">
    <width  instance="java.lang.Integer.valueOf(CDATA)">300</width>
    <height  instance="java.lang.Integer.valueOf(CDATA)">300</height>
  </size>
</jframe>

4. 8. Step 7: String-valued CDATA elements don't need a constructor

A String-valued element that has CDATA don't need an explicit constructor, so we can remove all instance="CDATA" constructors. This applies to the elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  class="javax.swing.JFrame"  parameters="title">
  <title>This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  class="javax.swing.JLabel"  parameters="text">
      <text>This is a JLabel</text>
    </label>
    <opaque  instance="java.lang.Boolean.valueOf(CDATA)">true</opaque>
    <background  instance="new java.awt.Color(red,green,blue)">
      <red  instance="java.lang.Integer.valueOf(CDATA)">200</red>
      <green  instance="java.lang.Integer.valueOf(CDATA)">90</green>
      <blue  instance="java.lang.Integer.valueOf(CDATA)">90</blue>
    </background>
  </contentPane>
  <size  class="java.awt.Dimension"  parameters="width,height">
    <width  instance="java.lang.Integer.valueOf(CDATA)">300</width>
    <height  instance="java.lang.Integer.valueOf(CDATA)">300</height>
  </size>
</jframe>

4. 9. Step 8: Take advantage of element types

First, we use the element types int and boolean for removing the quite long instance attributes. This applies to the elements:

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  class="javax.swing.JFrame"  parameters="title">
  <title>This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  class="javax.swing.JLabel"  parameters="text">
      <text>This is a JLabel</text>
    </label>
    <opaque  type="boolean">true</opaque>
    <background  instance="new java.awt.Color(r,g,b)">
      <red  type="int">200</red>
      <green  type="int">90</green>
      <blue  type="int">90</blue>
    </background>
  </contentPane>
  <size  class="java.awt.Dimension"  parameters="width,height">
    <width  type="int">300</width>
    <height  type="int">300</height>
  </size>
</jframe>

Next, we use the element type color for making the creation of the <color> more shorter. (the declativity of the examples decreases as a result, though..)

<?xml version="1.0" encoding="UTF-8"?>
<jframe xmlns="http://www.jicengine.org/jic/1.0"  action="this.show()"  class="javax.swing.JFrame"  parameters="title">
  <title>This is a JFrame</title>
  <contentPane  instance="PARENT.getContentPane()">
    <label  action="add(this)"  class="javax.swing.JLabel"  parameters="text">
      <text>This is a JLabel</text>
    </label>
    <opaque  type="boolean">true</opaque>
    <background  type="color">200,90,90</background>
  </contentPane>
  <size  class="java.awt.Dimension"  parameters="width,height">
    <width  type="int">300</width>
    <height  type="int">300</height>
  </size>
</jframe>