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

J. Shirley jshirley at gmail.com
Wed Feb 4 20:59:40 GMT 2009


On Wed, Feb 4, 2009 at 12:39 PM, Gene Selkov
<selkovjr at observercentral.net> wrote:
> 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
>

The Catalyst method is quite simple, since it tries to adhere to the
MVC design patterns.

You would not set the variable in your templates, instead in the controller.

sub action_name : Local {
    my ( $self, $c ) = @_;
   $c->stash->{surname} = $c->model('LDAP')->get_ldap_surname($id);
}

Then your template gets 'surname' and you can just do:

Hello <% $surname %>!


You can substitute out your model for an API compatible-version and
your app works.
You can substitute out your template language and your app still works.

-J



More information about the Catalyst mailing list