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
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
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
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 %>, ...
my $surname = get_ldap_surname($uid);
----- 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?