Spry is Inaptly Named

From Dictionary.com,

spry –adjective, spry·er, spry·est or spri·er, spri·est.
active; nimble; agile; energetic; brisk.

Hmmm... agile... that's a good analogy - as in the Agile Manifesto... a couple of the key principles of Agile development as described on Wikipedia are "simplicity" and "regular adaptation to changing circumstances"... and key to the task of shortening development timelines is creating frameworks with loose coupling... Well what is loose coupling? Loose coupling (as compared to strong coupling) means there are very few places in which the code would need to be modified in order to inject or remove a particular item.

In the case of Spry as the example, here's some code from the Spry form validation demo (I've snipped out just the relevant bits):

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry">
<head>
<link href="../css/screen.css" rel="stylesheet" type="text/css" media="all" />
<link href="../../widgets/textfieldvalidation/SpryValidationTextField.css" rel="stylesheet" type="text/css" />
<link href="../../widgets/selectvalidation/SpryValidationSelect.css" rel="stylesheet" type="text/css" />
<link href="../../widgets/textareavalidation/SpryValidationTextarea.css" rel="stylesheet" type="text/css" />
<link href="../../widgets/checkboxvalidation/SpryValidationCheckbox.css" rel="stylesheet" type="text/css" />
<link href="validation.css" rel="stylesheet" type="text/css" media="all" />

<script type="text/javascript" src="../../widgets/textfieldvalidation/SpryValidationTextField.js"></script>
<script type="text/javascript" src="../../widgets/selectvalidation/SpryValidationSelect.js"></script>
<script type="text/javascript" src="../../widgets/textareavalidation/SpryValidationTextarea.js"></script>
<script type="text/javascript" src="../../widgets/checkboxvalidation/SpryValidationCheckbox.js"></script>

</head>

<body>
<noscript><h1>This page requires JavaScript. Please enable JavaScript in your browser and reload this page.</h1></noscript>
      <form id="form1" name="form1" method="post">
      <div id="theTitle">
         <div class="formLabel">Title:</div>
         <input name="movieName" type="text" id="theMovieTitle" value="Conquistador" />
         <img src="images/ok.gif" title="Valid" alt="Valid" class="validMsg" border="0"/>
         <span class="textfieldRequiredMsg">Please enter a title.</span>
      </div>

      ...

      <div id="theDescription">
          <div class="formLabel">Description:</div>
               <textarea name="movieDescription" id="movieDescription" cols="45" rows="5">The story of a historian accompanying Cortez in his quest in the New World.</textarea>
               <span class="textareaRequiredMsg">Please enter a description.</span>
               <span class="textareaMinCharsMsg">Please enter at least 20 characters.</span>
      </div>

      ...

      <div class="buttons">
         <input type="submit" name="Submit" id="submit" value="Submit"/>
      </div>
</form>
</div>
</div>
</div>
</form>

<script type="text/javascript">
<!--
   var theTitle = new Spry.Widget.ValidationTextField("theTitle", "none", {useCharacterMasking:true, validateOn:["change"]});
   var theDate = new Spry.Widget.ValidationTextField("theDate", "date", {useCharacterMasking:true, format:"mm/dd/yyyy", hint:"mm/dd/yyyy", validateOn:["change"]});
   var theDuration = new Spry.Widget.ValidationTextField("theDuration", "integer", {useCharacterMasking:true, validateOn:["change"], allowNegative:false});
   var theRating = new Spry.Widget.ValidationSelect("theRating", {validateOn:["change"]});
   var theStudio = new Spry.Widget.ValidationSelect("theStudio", {validateOn:["change"]});
   var theDescription = new Spry.Widget.ValidationTextarea("theDescription", {useCharacterMasking:true, minChars:20, maxChars:180, counterType:"chars_count", counterId:"Countvalidta1", validateOn:["change"]});
   var checkboxes = new Spry.Widget.ValidationCheckbox("checkboxes", {validateOn:["change"], maxSelections:3});
//-->
</script>
</body>
</html>

Here's a reasonably comparable form using the onTap framework's xhtml library:

<cf_html>
<tap:form id="form1" name="form1" xmlns:tap="http://www.fusiontap.com">
   <input name="movieName" type="text" value="Conquistador" label="Title" tap:required="true" />

      ...

   <textarea name="movieDescription" tap:required="true" label="Description" cols="45" rows="5">The story of a historian accompanying Cortez in his quest in the New World.
<tap:validate type="length" min="20" max="180" />
</textarea>

      ...

   <button type="submit" name="Submit">Submit</button>
</tap:form>
</cf_html>

The marketing on the Adobe Labs site for Spry gets it pretty correct:

The Spry framework is a way to incorporate XML, JSON or HTML data into pages using HTML, CSS, and a minimal amount of JavaScript, without the need for refreshing the entire page. Spry also provides easy to build and style widgets, providing advanced page elements for end users. The Spry framework is HTML-centric, and easy to implement for users with basic knowledge of HTML, CSS and JavaScript. The framework was designed such that the markup is simple and the JavaScript is minimal. The Spry framework can be used by anyone who is authoring for the web in their tool of choice.

But as you see above, it doesn't really deliver on that claim... There are a horde of things that I could comment about in these samples, but the biggest one is simply the amount of code required and not merely the amount, but the way it's sprawled all over the template... Why could code not be put in just one or two places? Javascript makes it eminently available for Spry's form management tools to be very concise, just the way my onTap sample is.

For example:

  • Assuming that you're including a given Spry widget .js file, there's no reason why you should be required to separately include the CSS template for that widget -- the framework might just as easily check for the existence of a link tag with a spry-specific ID and if not present, include the default CSS file from an appropriate location automatically by manipulating the DOM at run-time.
  • Similarly, if you're including the form validation tools, there's no reason why it should require you to manually include a separate script for each type of validation you want (which could all be included in a similarly automated fashion based on what's found in forms on the page).
  • There's also no reason why it should require you to attach validation to the forms in an inline JavaScript block at the bottom. The framework might just as easily cycle through the forms on the page when the page loads and examine the DOM for each form to automatically assign the form validation on the basis of namespace attributes like spry:validateOn="change". Separating the validation from the form doesn't make it easier to do this stuff, it makes it harder!

To me, this is not "html-centric". An "html-centric" framework would be like ColdFusion with respect to having most of the instructions within the XHTML tags and attributes, the way I just showed.

The one thing I'll mention that may be a tad unfair, given that Spry is a pure JS/CSS framework, is that the onTap framework form doesn't require that you manually enter values in form fields (I rarely ever type value=) or create and place error messages for most validation. Because most validation is common across forms, there are default error message templates for each language, so all you have to do is provide the label (and I usually automate that too with XSLT). The warning that the page requires JavaScript is also similarly unnecessary (Section 508 non-complicance, sweet!), but that's because the onTap framework uses the same XHTML that drives the JavaScript validation to perform server-side validation (without resorting to the security nightmare of ColdFusion's built-in server-side validation), so there's not really anything Spry can do about that natively. The only way that could work with Spry is if someone built a server-side framework like the one in onTap and made it to spit out the Spry markup.

The long and the short of it is this: even if I were an EXPERT at Spry (which claims to be easy to learn), Spry forms still require a minimum of about 3-5 TIMES as much maintenance versus comparable forms built with the onTap framework. (And even in pure JS/CSS most of that maintenance could be eliminated if they'd chosen slightly different design principles.) To me, a 300%-500% increase in maintenance isn't "spry" development.

Comments
Raymond Camden's Gravatar Some fair points here - but some unfair ones as well. ;) Your code is server side, and therefore can output a lot of code from one tag. You get to do more behind the scenes just by using a server side language, so I don't think it's fair to do a strict line by line comparison. I can - and often do, abstract out the loading of Spry libraries so I can just tell my CF template to load one lib or another. The end result is that I can easily load in libraries based on what I need with a minimal amount of coding.

Also, your 'snipped' version has things in it it doesn't need for the example you are providing. For example, I see select validation when you don't use the select code on the page.
# Posted By Raymond Camden | 12/11/08 5:35 PM
ike's Gravatar Thanks Ray. :) The extra select validation library was just me snipping the example down a bit sloppily -- but I didn't write that code, that was from an example from the Spry docs. And yes, some of my comments weren't entirely fair ;) But also one of the things I was getting at is that there are techniques that can be used to load the js libraries automatically based on the content in the page. So while a line-by-line comparison may not be entirely fair, it is possible for Spry to have come very close to the same compactness in my example. I think I may have made that clearer in my subsequent blog titled "Learning Curves".
# Posted By ike | 12/11/08 6:43 PM
Raymond Camden's Gravatar Ok. I will say that validation could be simpler. But don't throw the baby out with the bathwater. Getting and displaying data in Spry takes a grand total of one line of JS. It really shines there.
# Posted By Raymond Camden | 12/11/08 9:07 PM
ike's Gravatar That's actually an area of Spry I've never been asked to work with. ;) So I can't really say... I can only speak to the features I've used. I'll take your word for it though.
# Posted By ike | 12/11/08 11:18 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress