reuse

"You have to have something bad happen to you"

Steve Yegge on code’s worst enemy:

… This brings us to the second obviously-bad thing that can go wrong with code bases: copy and paste. It doesn’t take very long for programmers to learn this lesson the hard way. It’s not so much a rule you have to memorize as a scar you’re going to get whether you like it or not. Computers make copy-and-paste really easy, so every programmer falls into the trap once in a while. The lesson you eventually learn is that code always changes, always always always, and as soon as you have to change the same thing in N places, where N is more than 1, you’ll have earned your scar….

Code reuse is great, although some languages punish you for it: Coldfusion takes a performance hit on behalf of debug logging whenever it crosses a component boundary, even if debugging is turned off. And a lot of includes scattered across the place can make it difficult to track what’s going on (unless you use those very IDEs that Steve suggests treat code like heaps of dirt to be rearranged). I suppose ultimately it’s about developing an instinct for balancing short-term performance, ongoing maintainability and long-term scalability, and you only learn that by dint of many, many scars.

CFJavaXML - a component for cached XML transformations

Mark Mandel wrote his own version of Coldfusion’s XmlTransform() function, using the underlying Java transform classes. Although one of his annoyances—that XmlTransform() won’t take any parameters—has been solved in CFMX7, XmlTransform() is nonetheless a slow operation, as the transform engine has to be cranked up, the XSL compiled, the transform effected and then everything garbage-collected, each call to the function, each request.

To improve Coldfusion for dedicated XSL programmers, I’ve turned Mark’s one-off function into a more granular component for cacheable, Java-based XSL transformations, called CFJavaXML. You can cache this component from request to request in a persisting scope. You can also compile an XSL transformation once, then store that in a persisting scope too and re-use it without having to keep accessing the XSL file (and compiling it, which can take time). It’ll bring in all its xsl:import references at compilation too, so you needn’t worry about having to keep track of your XSL directory from transformation to transformation.

The component needs no initialization, so create it as follows:

<cfset comp_cfjx = createObject(”component”, “#PATH_TO_COMPONENTS#.cfjavaxml”)>

You can cache this in a persisting scope at this point.

Using CFJavaXML is always a two-stage process, so that you get a compiled transformation object you can store and re-use. In the following example, XSL and XML can be either local file://(/) references, http:// URLs or even strings of valid XML:

<script>
    t = comp_cfjx.XslTextToTransformer( XSL );
    xmltext = comp_cfjx.XmlTransformFromTextAndJava( XML, t [, params]);
<script>

(The transform t is the compiled transform that you can cache from request to request.) Note also where any optional parameters can be inserted, using a params struct.

Depending on the transformation (and how many times you use it) the speed increase of using CFJavaXML has been quite striking: up to ten times with certain transformations. Benchmarking is quite difficult because it depends so much on the intricacy of the XSL: your mileage may vary.

(Thanks to my employers, Torchbox, who’ve given me permission to make this code available, and thanks to Mark for showing how to do it in the first place!)

Blog category:

Subscribe to RSS - reuse