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
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006.