Declarative and imperative programming [was RE: Deploying (accessible) XForms today?]

Erik,

> But here is where Ian Hickson is right: at some point, you 
> will write something like this:
> 
> <xf:action ev:event="xforms-value-changed">
>    <xf:setvalue ref="my/node/a">Hello</xf:setvalue>
>    <xf:send submission="my-submission"/>
>    <xf:setvalue ref="my/node/b" 
> value="instance('some-instance')/node-b"/>
>    <xf:toggle case="ok-case"/>
> </xf:action>
> 
> The above clearly *is* scripting. It doesn't use Javascript 
> as far as the developer is concerned, and it uses a level of 
> semantics above what you usually do with Javascript, but it's 
> imperative scripting
> nonetheless: it gives the XForms engine instructions that 
> must be executed in a sequential order.

It most definitely is *not*...:)

I have to disagree with both you and Hixie here. (I also looked at Hixie's
arguments over a year ago in an article called "The 'XForms Myth' Myth" [1],
if anyone is interested, and there is an interesting reply from Hixie on
there, too.)

The reason I would say it's not like scripting is because of what you are
not seeing in those four lines. To work this through, let's say that the
snippet you showed was some new XML programming language called 'xf'. In
this code you have set a value, submitted some data, set another value, and
then toggled some part of the display; we agree that this certainly seems
all very imperative.

However, let's add a bit more functionality. For example, we would like to
say that if the value in 'my/node/b' is not an integer, an error message
should be rendered. We'll continue to develop our new language ('xf'), but
in our 'imperative mindset' and, after much debate on the lists and
consultation, we decide to add an xf:if test, and an XPath function that
tests the value of a node against some datatype:

  <xf:setvalue ref="my/node/b" 
    value="instance('some-instance')/node-b"/>

  <xf:if expr="valid(my/node/b, 'xs:integer')">
    <xf:message>
      I need an integer...give me an integer!
    </xf:message>
  </xf:if>

It all looks fine, and when you're dealing with small bits of code like this
it seems pretty logical for a language designer to say "we need to add a
feature so that we can do a test and then do something with the result of
that test".

But of course, you know as well as I do that this is not at all 'fine'. It's
labour-intensive, unmanageable, and will produce 'spaghetti' code just like
JavaScript does...except it will do it in XML!

(As an aside, there is a common misconception that XML = declarative; this
mistake comes up, for example in discussions about languages like XAML,
which are assumed to be declarative just because they are XML-based.)

So, how did the XForms designers approach this question? Well, as everyone
now knows they took the declarative or 'functional' approach [2], but they
also made sure that they looked for what you might call patterns. In our
example, a traditional programming approach would be to say, "although the
use case is to test the type of a node before showing an error message, I'm
going to add a feature that allows *anything* to be tested, and *any action*
to be carried out after that test". In this case the 'traditional' approach
certainly appears to give lots of power, but in reality it gives too much.

The XForms approach does thing differently, and says that if there is a
common 'pattern'--in this case it's along the lines of "if some value fails
to be validated show an error message"--then we should provide support for
that pattern, rather than trying to generalise it too much.

The result is firstly, that XForms provides the author with a nice simple
way of saying that 'my/node/b' must be an integer:

  <xf:bind nodeset="my/node/b" type="xs:integer" />

And secondly, XForms provides the author with a nice easy way to indicate
that some message should be displayed if the value is not an integer:

  <xf:input ref="my/node/b">
    <xf:label>Node B:</xf:label>
    <xf:alert>
      I need an integer...give me an integer!
    </xf:alert>
  </xf:input>

With the bind statement, the author:

 * doesn't have to remember to check the type of this
   node everywhere that the node might have changed;

 * and if they want to change the type--say, to double
   or float--they don't have to search their code for
   all occurrences of statements that check the type;

 * and if they do make the change, by putting the
   'declaration' in just one place they don't run the
   risk of discovering later on that they didn't
   change every occurrence.

In other words, accuracy is increased and maintenance time and bugs are
reduced.

That's the beauty of bind, but with the input and alert combination, the
XForms design really leaps light-years ahead of our procedural/imperative
alternative, by completely decoupling the *state* of the data from its
display.

Instead of having the imperative 'if this do that' approach, we have a
highly flexible, decoupled architecture, where each 'component' doesn't need
to know much about any other 'component':

 * the xf:alert does not need to know *why* the control is
   invalid, it just needs to know that it is;

 * the input doesn't need to know anything about the
   existence of the alert;

 * the bind statement doesn't need to know why the data
   has changed, it just needs to know that when it does
   change it should check the data type again;

 * the bind statement also doesn't need to know what is
   'listening' to know when the data goes invalid, it
   just needs to know that it should notify whatever is
   listening when the data is invalid (not an integer).

The combination of these 'decoupled' objects is that you can independently
change:

 * the test in the bind statement (integer, etc.);

 * the control that is using the data (from input to
   range, for example);

 * the message to be given to the user (in the alert);

all without affecting any of the others...in fact without even needing to
know that the others exist!

The key thing therefore in the design of the language is to try and find
patterns that can be broken down into declarative statements. And the
impressive thing about the patterns that have been found so far (i.e., the
current specifications) is that they are sufficiently powerful to have meant
we are only just now needing to add 'if' and 'while' statements. In other
words, we've been producing useful forms without them for a couple of years
now, which shows the range of use-cases that are captured by the
decoupled/declarative approach.

So, in summary, the only reason Hixie (or you, Erik!) are able to say that
those four lines are imperative is because they don't show what is happening
'for free'. But adding more functionality to that program will quickly show
how XForms is very far removed from an imperative language.

Finally, I had much the same discussion over on the SVG list in November
2004, which I summarised on my blog at the time:

  Loosely Coupled Objects and Declarative Programming
 
http://internet-apps.blogspot.com/2004/11/loosely-coupled-objects-and.html

Many of the same issues came up then, so whether people agree with my points
or not, they might find the different positions people adopted in that
thread of interest.( Also, the article looks at XForms' relationship to OO
programming, not just the imperative procedural discussion.)

There are also a few other articles on my blog on XForms and declarative
programming:

  XForms: An Executable Pattern Language:
 
http://internet-apps.blogspot.com/2005/09/xforms-executable-pattern-language
.html

  On Adobe and XForms via Declarative Programming, Wizards and Aspects
 
http://internet-apps.blogspot.com/2005/09/on-adobe-and-xforms-via-declarativ
e.html

Regards,

Mark

[1] http://internet-apps.blogspot.com/2005/03/xforms-myth-myth.html

[2] Many of the early XForms language designers have a background in, or
sympathy for, what you might call functional programming. I'm thinking here
of Steven Pemberton, T. V. Raman, John Boyer and Roland Merrick...those are
the ones I know for sure, but it wouldn't surprise me if other early
contributors were also of the same view.


Mark Birbeck
CEO
x-port.net Ltd.

e: Mark.Birbeck@x-port.net
t: +44 (0) 20 7689 9232
b: http://internet-apps.blogspot.com/
w: http://www.formsPlayer.com/

Download our XForms processor from
http://www.formsPlayer.com/

Received on Thursday, 11 May 2006 11:15:40 UTC