Continuing from the thread on the modperl mailing list: On Sun, Jun 02, 2002 at 05:04:01PM -0400, Sam Tregar wrote: > > I don't think the standard HTML::Template has support for formatting > > numbers, dates, etc. > > And thank the sweet lord it doesn't! HTML::Template is a "do one thing > and do it well" module. If you want routines for formatting "numbers, > dates, etc." then CPAN has just what you need.
I (mostly) consider formatting of numbers, etc., to be a presentation issue, not a programming one. That's why TT supports this kind of thing in the templates (or in the code if you prefer). Of course, the fact that it's a module/object is entirely hidden. TT abstracts the front end templates from the backend implementation, so that the HTML designers don't have to know if a data structure is implemented as a hash, object, or subroutine, it just does the right thing. This allows the developers to worry about implementing a back-end system in the best way possible and the front-end designers to just use it. > HTML::Template::Expr may present a solution to this particular desire, > although it isn't one I've come across. How often are HTML designers > fiddling with numeric formats? Are they really HTML designers if they can > deal with, say, a printf-style format string? In TT, you would usually pre-declare a particular format in a config file, pre-processed templates, or some other "global" style document. e.g. [% USE money = format('%.02f') %] In your main page templates you would do something like this: [% money(order.total) %] Then you can change the money format in one place and your designers don't have to worry about sprintf formats. If you prefer to write your own formatting subroutine you can do it like so: my $vars = { money => sub { return sprintf("%.02f", shift) }; order => { total => 22.95, } }; $template->process($file, $vars) || die $template->error(); Guess what? You don't have to change any of the templates. They still use the same syntax: [% money(order.total) %] This is abstraction. Not to be confused with MVC which is one particular architecture well suited to GUI applications. Blindly applying MVC without understanding the real issues (abstraction of front/back ends, separation of concerns, don't repeat yourself, etc.) is likely to build a system which is highly fragmented. Maintenance becomes harder because everything is split up into many different pieces and it becomes difficult to see the wood for the trees. Aspect oriented programming teaches us that as soon as you decompose a system into a particular structure you inevitably fragments aspects which cut across the system. I have seen this in close and painful detail over the past few months while helping to build a very strictly partitioned MVC architecture system for Fotango(.com). We're using TT for presentation, Openframe for the application pipeline/dispatch and a custom data backend called Vx. Despite our best intentions, this web site doesn't neatly fall into clearly defined chunks of model, application and view. Well, actually, those parts do split down quite nicely. But then you look at localisation, for example, and we find there is localisation required in the data backend, localisation required in the applications and localisation required in the templates. Thus, localisation is an aspect which cuts across the system. By building a strict MVC we've fragmented localisation and have to trawl through hundreds of different files to localise the site. Another example is that different countries running their localised versions of this web site will want to change the URLs. Where the english version uses /product/shirt/red.html, the french version should instead be /produit/chemise/rouge.html, for example. Again, these URLs are (currently) embedded throughout the system and making any changes to them is a painful process involved many files spread across the M, the V and the C. In an ideal world, English and French would just be different views of the same model. Alas, it's never that easy because the chances are that parts of the model and parts of the controllers will also need changing. See, the problem is that MVC is just one particular decomposition. It's generally a good one because application, data and presentation are typically the three biggest aspects that you want to separate. However, it doesn't take into account any of the other dozen or so aspects that you might want to model in your system. Nowhere in MVC or any other Design Pattern does it tell you to define all your URLs in one place in case you ever need to change them en masse. You have to think of that all by yourself. MVC is no substitute for thinking and it often encourages the opposite, lulling you into a false sense of security by the fact that you think you're doing the Right Thing. I've seen far too many example of people who didn't pass objects into their templates, didn't embed Perl code, or didn't do this or that because they thought that it might violate the MVC principal. The end result was that they jumped through hoops and made the system more complex than it needed to be for the sake of "purity". Sometimes it really is a good idea to embed Perl code in templates. Not often, no, but if the Perl code is performing a *presentation* function and not an *application* function, and as long as it's defined in one convenient place so that you can get your hands on it, then it can be the Right Thing to do. Now I'm not suggesting that embedding Perl is a good idea, per se, but I'm saying that the smart people know when and how to break the rules. Separation of concerns is the goal, and MVC is one particular approach that can help you to acheive that. To address the problem in the fotango site, I'm borrowing a technique from AOP called aspect weaving. I currently define 12, yes 12 separate models (either as Perl code or XML files) each of which defines one aspect of the site. One defines the abstract site/section/page structure, another defines the URL -> page mapping, another defines page titles, short names, descriptions and anything other information about a page (e.g. not content) that might need to be localised. Another aspect defines pure style elements (e.g. colours, fonts, CSS styles, etc), another defines flags and other data for building the site interface, another defines database connection and other backend data values. And so on. Each of these elements can be "subclassed" to change one particular aspect of the site. A simple bit of code weaves the 12 different aspects together into one coherent data model which is the definitive reference model for everything in the site. This is all still in development as I type (or rather it's not in development because I stopped to type this :-). Assuming that it matures well and proves that it does what it says on the tin, I'll be releasing it as some kind of general tool for the modelling and building of web sites. It will be entirely generic so you will be able to use it equally well with TT as with HTML::Template. So to summarise a long, rambling post, MVC often isn't the answer by itself and sometimes it's not the answer at all. AOP might help, but only until we reach the next problem horizon. Five years ago I was saying "Object Oriented Programming isn't the answer by itself and sometimes it's not the answer at all". Any idiot can write an object, but we all know that it takes a great deal more to design a coherent OO application. In five years time, I'll probably be saying "Aspect Oriented Programming isn't the answer by itself..." :-) Or, more generally: [% silver.bullet %] isn't the answer by itself... A