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.