[Catalyst] template design issue: varibales stand-alone components

Gene Selkov selkovjr at observercentral.net
Wed Feb 4 20:39:56 GMT 2009


This question may be slightly off-topic, as it stems from my use of Mason 
in templates. Maybe I wouldn't have had this problem if I used something 
else. But I intend to re-organize my existing app with Catalyst, in a way 
that would allow me to continue using Mason, and I would like to know 
proficient Catalyst users' opinion on what seems to be fairly general 
design problem.

I looked at TT once; it scared me: I didn't like the way it looked and 
found it more difficult to type than Mason. Let me assume for a moment 
that the question is generic, and I will attempt to present it in abstract 
terms.

Mason templates usually consist of two parts: the template itself and the 
code providing values for its variables. Mason calls that code <%init>, 
and the variables defined there can be interpolated into the template. 
<%init> is not the only source of values for template variables, and it is 
entirely optional. Variables can also be defined as template arguments; in 
that case, their values will be supplied by the caller. But I am not 
concerned with arguments. I am concerned with the variables whose values 
are created through hard work, requiring possibly a lot of code and 
interactions with various agents. In a complicated Mason template, that 
usually happens in the <%init> section, which contains regular perl code.

Additionally, perl can be used across the template in a manner similar to 
c preprocessing directives, providing means for conditional rendering and 
for generation of repetitive patterns (tables, lists, &c.).

Even further, instead of inserting a value of a variable into the text, 
a chunk of perl code can be called in-line and replaced with its return 
value.

Alternatively, instead of calling perl code embedded into the template, 
the template can insert another template.

I am conflicted about the best way to use templates even in the 
non-catalyzed Mason, and I would like to resolve this conflict before I 
move it to Catalyst. Here's an example. I can generate the same output 
with these two template variants:

----- variant 1 ------

Dear Dr. <% $surname %>, ...

<%init>
   my $surname = get_ldap_surname($uid);
</%init>
~~~~~~~~~~~~~~~~~~~~~~

----- variant 2 ------

Dear Dr. <& lib/ldap_surname.mason, uid => $User &> ...

~~~~~~~~~~~~~~~~~~~~~

The first variant does all the work within the same template, while the 
second variant delegates that same work to another template, which can be 
reused in other templates. I can't afford more than a trivial example, but 
please imagine that a typical template can have dozens of variables and/or 
sub-templates (known as components in Mason).

If I consistently follow the first variant, I end up with fairly 
efficient, but extremely messy and unreadable code that provides 
everything the template needs in one place. The template itself 
tends to be complicated and incomprehensible.

However, if I delegate bits of work (as well as rendering) to various 
sub-templates, I can achieve highly readable object-oriented structure, 
with simple and easy-to-understand components -- in terms of appearance as 
well as behavior -- at the cost of elevated redundancy and poor 
performance. Many components end up going to the same place for copies of 
the data, not knowing that their siblings have already been there and 
queried the same table row, for example.

I wonder what is considered good design, vis-a-vis this dilemma, and what 
is the Catalyst way of doing this. I understand, roughly, that my first 
variant is more easily adaptable to Catalyst: take all that code in 
<%init>, put it in one controller action and make it fill places in a 
single template -- right? What should I do if I want to implement the 
second variant, based on sub-templates, and what can I do to avoid 
redundancy in controller actions, if I go that way? Is there a third way I 
am not aware about?

Thanks,

--Gene



More information about the Catalyst mailing list