XForms: An Executable Pattern Language
Introduction
I realised when I saw a recent blog of Bill McCoy's (which is a reply to my blog, but which is itself a reply to his blog, which was in its turn a comment on my blog...Yes, it has often occurred to me that there might be no-one out there reading this exchange other than me and Bill) that the discussion about XForms and declarative programming might end up being just a debate about whether using XForms is better than using script.Of course that's part of the discussion, but it's certainly not the whole story. The problem is though, that many of the things I've discussed in relation to XForms patterns have tended to also look at AJAX and scripting (since that is often the only place where you can find something to compare with) and I think I have probably given the impression that my prime concern is script.
AJAX and xf:submission
Take for example my discussion about how the standard AJAX HTTP submission mechanism works (yes, with no page refresh...I know, I know...and what will we get in 10 years time when AJAX 2 comes out?).Recall that the most common way of doing an AJAX request is to set up script like this:
var req;
function loadXMLDoc(url) {
// native XMLHttpRequest object
if (window.XMLHttpRequest)
{
req = new XMLHttpRequest();
req.onreadystatechange = readyStateChange;
// IE/Windows ActiveX version
} else if (window.ActiveXObject)
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req)
{
req.onreadystatechange = readyStateChange;
req.open("GET", url, true);
req.send();
}
}
function readyStateChange() {
// '4' means document "loaded"
if (req.readyState == 4)
{
// 200 means "OK"
if (req.status == 200)
{
// do something here
} else
{
// error processing here
}
}
}
(Although a more complete approach would look to handle the error conditions.)
Now the point is not that this is 'wrong', or even inefficient. But simply that in the same way that I eventually got bored of writing optimised assembler algorithms to do multiplication (and started using C instead), so today I really can't be bothered to have to set up code such as this to do nothing more than provide a line of communication with a server.
Of course some will reply that there are already many AJAX libraries emerging that will allow you to do this using some simple APIs, hence hiding this kind of code. But putting aside the fact that we don't have a standard for them, using classes and an API means we're still reserving these useful techniques for the most experienced programmers.
Anyway, let's map this code to XForms:
<xf:submission
id="sub"
method="get"
action="http://example.com/customers"
/>
Pretty simple...but I was using this as an illustration of how the advantages of XForms are not just that it is easier than scripting, so let's dig a little deeper into what XForms submission offers.
The Submission Pattern
As I said, it looks like what I'm saying is that XForms is better than script. I have to say that if that were all we'd achieved with XForms then I'd be pleased, but a lot less vocal. XForms has actually provided us with something far more significant--we now have something close to a pattern language, but one that thinks it's a programming language.To show you what I mean, let's think of our submission as a pattern. What we've got is some behaviour that is defined in a pretty abstract way, along the following lines:
'get' some data from one URL, or 'put' some data to another URL, and when done, generate either a 'success' event or a 'fail' event.
The strength of any pattern is in the fine balance between being sufficiently general that it can apply to many situations, but not so general that it says nothing. In this case it does seem quite vague--getting a document from here and putting it there--but when you think about it, that pretty much covers most of the basics when it comes to sending an email, saving a file to disk, retrieving an RSS feed, posting a document to a server, and so on. It certainly captures our AJAX request.
So, if this is a pattern language that thinks it's a programming language let's see then how XForms uses this pattern to get a file from your disk:
<xf:submission
id="sub"
method="get"
action="file:my-data.xml"
/>
Mmm. So no new API is needed to make the shift from HTTP to the file system? Are we really saying that any author/programmer who mastered the most common technique--the one that gets or puts an XML document to or from an HTTP server--has therefore got teh complete skill-set for getting and putting the same document to or from the hard-drive?
The answer is of course yes, but let's go further and see what new skills our author needs to acquire to send the same XML document by email. Surely they'll need to buy a book on MAPI:
<xf:submission
id="sub"
method="put"
action="mailto:john.doe@example.com?subject=Results"
/>
No new API again? No need to roll your sleeves up and learn MAPI in order to write a powerful application that will allow a user to enter some XML, validate it, and then send it via email?
And that is the key point; it's not that we've hidden a whole load of script--which of course it goes without saying that we have--but rather that we've devised a simple language that captures an enormous amount of generic functionality, whilst crucially still allowing us to use that functionality in very specific situations. We get our specific functionality without learning lots of specific APIs. (And I haven't even mentioned that this simple pattern captures even more functionality; as well as automatically validating the data before it sends it, it also provides an option to serialise the data in a number of different formats.)
Databases
One final example of the power of this approach comes in the form of an enhancement that we added to formsPlayer 2, which allows databases to be accessed using this same pattern. At first sight it seems that our Submission pattern couldn't be appropriate for databases, but if you consider that aSELECT query is like a 'get' and modifying or inserting a record is like a 'put', then we find that our pattern works for us once again.Since the submission pattern involves the use of an XML document and a URL, then the trick is to convert the XML data to and from relational tables, and to make use of the URI syntax to work out what table is being accessed.
But none of this is that difficult, and there are many ways it could be done. In our implementation we chose to make the URI into a combination of a full ADO string (to select the database) followed by the name of the table to access. So to obtain a full list of the contacts (as an XML instance) that are stored in the
tContacts table, we just do this:
<xf:submission
id="sub-get-contact-list"
separator="&"
method="get"
action="db://Driver=\{Microsoft Access Driver (*.mdb)\};Dbq=contacts.mdb;/tContacts/contact"
replace="instance" instance="inst-contact-list"
/>
Note that the use of
'\{' and '\}' is because in formsPlayer 2 you can use Attribute Value Templates to specify the URI. Also, since this is full ADO you can access many other data sources, from MySQL and SQL Server databases, to Excel spreadsheets and CSV files.To update a row in the table (i.e., save any changes) we do this:
<xf:submission
id="sub-put-current-contact"
bind="ns-current-contact"
action="db://Driver=\{Microsoft Access Driver (*.mdb)\};Dbq=contacts.mdb;/tContacts/contact"
separator="&" method="put"
replace="none"
/>
The contacts application that comes as part of the Sidewinder install makes full use of this technique:

Contacts database viewed through the Sidewinder Viewer

Conclusion
Of course in all of these examples we have replaced some script--although in each of these cases the scripts we have replaced will be extremely different to each other--but far more importantly we have created a pattern that has sufficient flexibility to be continually applied to new situations. And in this case, when applied to databases, our pattern even stands up pretty well to very specific, purpose-built approaches like LINQ. (See also Visual Basic 9.0: Looking Forwardby Scott Swigart.)
Tags: AJAX | Computers and Internet | formsPlayer | programming | Web2.0 | XForms









4 Comments:
Seems a bit fast and loose with the method names, Mark. What's the difference between put and post with file: for example?
Chris,
Well, the key point that I am getting at is that the methods are abstract. So whatever they mean in the context of a particular protocol is whatever by convention we all decide they should mean. If we want post to mean something with file: then we can agree it. (As it happens, I can't think of anything meaningful, that's why I used put.) In XForms there are some method/protocol combinations defined, and an important consequence of what I am saying in my blog is that we should define more.
As for being "fast and loose", we carefully thought through the method names used for our extensions, and I think they are pretty consistent. Using put to 'put' some data to a data store is good practive, regardless of whether that is a file write or an HTTP put (quite RESTful, in fact). You might argue that an email should be sent with a post, but even then, it depends on what the email is to do; if it causes data to be stored in a database then it could be argued that the abstract method put is still appropriate. (It's the task, not the protocol that is important.)
Thanks for taking the time to comment.
Best regards,
Mark
I have no problem with XForms and declarative development; I do have a problems with the fact that a Redmond WA software company has effectively said no to XForms and a whole lot of other Web development technologies by not updating IE for 5-6 years.
So why do you develop for that browser only ???
Jacques,
Thanks for posting, but surely, given that you don't know what we do with our time, a more correct question would have been "are you, or will you be, developing for other browsers?"
;)
Anyway, the answer to that question is that we have recently made some substantial advances in that direction, and we hope to be able to release at least some of these new things shortly.
Post a Comment
Links to this post:
Create a Link
<< Home