I'm not sure if this has much to do with what you're talking about here,
but... This is an example of some things that I'm doing to make my work
extensible and clean.
I'm hurrying on a "build engine" for our business, and in doing so, I have
tried to be as future-proof as possible, since I know that what I have will
work great now, but new features are inevitable...
Currently, we use custom software with all kinds of bizarre flags and
switches, which are interpreted by dozens of ancient C programs (very poorly
coded) to format the data.
In the workflow that will develop (this is not all live yet), there will be
people creating database extracts for customers.
The new workflow will involve generalized "business objects" that are made
available to template writers, who will read documentation on the objects
available to them.
The "Widget" extract would provide them with a general object named "widget"
that will be represented by one single row of data.
The buildengine will examine the user's template before it's processed to
see which fields need to be selected from the database, and if fields are
used that will relate to other tables, the buildengine is "smart" enough to
make the correct "JOIN" sql. This will let us add fields as necessary to
the database, and simply publish their availability in the general
buildengine documentation.
Then, the user can make a template like this:
-----------------------------------------------
Widget name [% widget.name %] Price: [% widget.price %] Release Date:
[% widget.release_date %]
-----------------------------------------------
This template will be evaluated repeatedly for each row (which I'm buffering
into an array for efficiency's sake.) I take the template and wrap it up
like this:
-----------------------------------------------
[%- FOREACH widget = internal_widget_buffer -%]
<insert actual template here>
[%- END %]
-----------------------------------------------
"internal_widget_buffer" is basically just an array of rows from the
database query. The nice thing about this is that I can change the number
of rows to find a sweet-spot between speed/memory efficiency, or to make it
run more smoothly on an old linux box.
After seeing that, I decided to extend some of the functionality... I
convert all 'datetime' column types into DateTime objects of my own
creation, allowing the user to format dates using normal "strftime"
formatting, so a user can do this:
-----------------------------------------------
Widget name [% widget.name %] Price: [% widget.price %] Release Date:
[% widget.release_date.as_string("%m/%d/%Y") %]
-----------------------------------------------
Then the thought arose that I would need a "library" of functions with which
users could manipulate the widget data... I decided on a perl Object to
represent this library.
-----------------------------------------------
package Library;
sub new {
...
}
sub pricedoubler {
$_[0] * 2;
}
-----------------------------------------------
So that then a template user might use that this way:
-----------------------------------------------
Widget name [% widget.name %] Doubled Price: [%
lib.pricedoubler(widget.price) %] Release Date: [%
widget.release_date.as_string("%m/%d/%Y") %]
-----------------------------------------------
And you can add any new functions you want into the Library.pm, a reference
to which is passed into the TT processor.
Why an object? Right, these could just be subroutines, but then I was
afraid of modifying the actual buildengine code adding each new sub to the
template processor, and stumbling all over my namespace...
The object representation will allow me to do something like this to change
functionality in the future, so that thousands of product templates won't
have to be updated when I make a bugfix or a change:
-----------------------------------------------
[%- lib.setversion("REALLY_OLD_VERSION") -%]
Widget name [% widget.name %] Doubled Price: [%
lib.pricedoubler(widget.price) %] Release Date: [%
widget.release_date.as_string("%m/%d/%Y") %]
-----------------------------------------------
Then, I can just do the test for a version number inside of the Library
object, and do The Right Thing without breaking templates etc. The version
number (and other object attributes) will be kept around "for free" because
it is an object. This way, once our C formatting logic is ported to perl, I
could provide a "formatlib" object to the template writers and so forth.
Among these things, I've written a "Template Collector" object that is used
by the buildengine to examine which extracts produce which output files, and
collect them together, doing different things for post-production:
script => runs a script to do any other perl-like massaging of data
or data validation/reporting etc.
sort => sorts a delimited file (needed quite frequently)
merg => merges files together
etc.
The TT abstraction (object ref looks like list or hash or function or...) is
very nice in this respect, allowing the programmer to change the
implementation of the process without even hinting that a change has been
made to the template maintainers. This is a Good Thing even if the
programmers *are* the template writers!
I would love to hear any comments or suggestions on the my ideas above...
Maintainability is key to this whole thing, and this kind of stuff will
alleviate our headache of trying to maintain ancient write-only C code.
Comments?
Regards,
-Bryan Shannon
> -----Original Message-----
> From: Perrin Harkins [mailto:[EMAIL PROTECTED]]
> Sent: Thursday, June 06, 2002 10:55 AM
> To: Sam Tregar
> Cc: modperl List; Template Toolkit List
> Subject: [Templates] Re: Separating Aspects (Re: separating C
> from V in
> MVC)
>
>
> Sam Tregar wrote:
> > Now, I don't use HTML::Template::Expr. I think it's
> generally not such a
> > good idea. But it's there if you want it...
>
> For posterity, and possible inclusion in the next rev of the
> templating
> tutorial, how would you recommend people handle this sort of
> situation
> without using HTML::Template::Expr?
>
> Suppose you have a model object for a concert which includes
> a date. On
> one page, the designers want to dipslay the date in a verbose
> way with
> the month spelled out, but on another they want it
> abbreviated and fixed
> length so that dates line up nicely. Would you put that
> formatting in
> the controller?
>
> What if you had a model object that generates a list of these
> concerts,
> and on a certain page the designers want to show it in two columns.
> Would you split it into two arrays in the controller?
>
> - Perrin
>
>
> _______________________________________________
> templates mailing list
> [EMAIL PROTECTED]
> http://www.template-toolkit.org/mailman/listinfo/templates
>