The Verifiability of Syntax

Imagine you're building a web application. Imagine that the application exposes several URLs. Imagine that the application's workflow requires navigation through those URLs.

You have to develop and deploy a model of those URLs somehow.

The well-worn CGI approach is to write separate semi-interdependent programs for each step of the application. Each new URL element is a separate program. (This model matches the statelessness of HTTP nicely, but requires careful thought on the server side to manage the necessary statefulness securely.

Much of the web has settled on an MVC approach where all requests come in through one or more controllers which dispatch to functions or methods based on request contents: the URI, any form parameters, and the query string. Often a framework handles this dispatch by unpacking all of this information and matching regular expressions or fraguments of the URI, then traversing all the way to an endpoint.

I like Catalyst's approach to dispatch (see especially Catalyst's chained dispatch, a feature I'm pleased to see Dancer adopting as well): dispatch points are methods on a controller object with metadata attached in the form of subroutine attributes. This metadata registers methods as dispatch points and identifies the pieces of the URI they consume and any necessary preconditions.

It's flexible and powerful. Once you understand the terms used in the Catalyst world, you have many options to do the right thing for your application. You also get some form of validation because subroutine attributes are merely Perl 5 syntax, not entirely raw string text (though admittedly, the parameters to these attributes are raw strings which require validation—fortunately, as Perl 5 processes attributes during compilation, the attribute handlers can sanitize and validate these parameters to some degree during compilation).

Another approach, used in many places including the Java framework which shall remain nameless, is to use an external file to manage routing information. In this case, it's an XML file which maps URI components to controller classes and methods on those controllers. It also maps the results of those methods to template bundles (declared in another XML file).

Thanks to the Java web world's tragicomic affair with Beans and the prevalence of CamelCase, I constantly get capitalization wrong in this file. You see, while I may have a controller class named AdminAction, the right way to instantiate classes in Java is to let Spring manage their lookup and instantiation and lifecycle.

In other words, even though I know that this application needs a class named AdminAction and that that class will always be a controller and that the routing information declared in this XML file relies on AdminAction behaving as coded, the right way to write this application means declaring a bean named adminAction (notice the capitalization) in yet another XML file and using that in the routing XML file instead of the class name.

(Apparently this makes replacing the real controller with a mock controller easier for testing, as if testing a mock controller were worth my time—what could it tell me about the validity of my Spring configuration or my routing configuration that basic end-to-end testing couldn't tell me better? And people who like to write tests wonder why some people complain that a focus on unit testing is, in many cases, useless busy work.)

The funny thing about the bean syntax is that it means, at its core, that if you have an object with instance data such as companyName or userAddress, those fields are private which means that you have to have public getters and setters which match the form getCompanyName and setUserAddress, but when you refer to those bean properties, you leave off the get and set and follow the capitalization of the field names (companyName)—the private names, even though you're using the public accessors with different capitalization.

Compound this with the fact that the right way is to use Spring, which instantiates these objects lazily and introspects their properties and... well, you get to find your capitalization typos at runtime.

Whereas in a language or framework or toolkit which allowed you to define syntax for all of these things would let you validate even capitalization conventions (hey, if such a parser existed, it could have opinions about things like this!) and let you know far, far before some hapless tester clicking his way through a 38 page test script hit a runtime error that you made a silly typo...

... because hoping that unstructured data is correct without ensuring that it is correct is a recipe for errors.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on April 8, 2011 8:55 AM.

Beans versus Immutable Objects was the previous entry in this blog.

A Working Alternative to FLOSS and IP Risk is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?