Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

HTML - separating design and logic

by muba (Priest)
on Jul 01, 2004 at 11:17 UTC ( [id://371039]=perlmeditation: print w/replies, xml ) Need Help??

· Prologue
I am aware of the fact that something of the same subject has recently been posted at PerlMonks. I am also aware of the fact that people have written many texts about this subject, both at PerlMonks and many other places. Also am I aware of the fact that this node possibly does not tell you something new.
The main reason for writing this, was that I was thinking about HTML::Template and it's idea and I felt I needed to share my thoughts with others.
So, thank you in advance for reading my thoughts.

· Introduction
Recently, I read the documentation of HTML::Template. I think the idea behind this kind of modules is rather interesting, although sometimes not too consistent.
To truly separate logic and design,
  1. no HTML tags should be in the Perl code, and
  2. no logic should be in the HTML template
· No HTML tags should be in the Perl code
Well, the first thing is not too difficult: while writing your Perl code, just imagine that readers of your page should be able to read it with interpreters of any mark up language. Imagine HTML::Template could be LaTeX::Template, POD::Template, Man::Template or whatever else template as well.

· No logic should be in the HTML template
Of course, a little logic is allowed, for example to create rows that have different colors (the odd numbered rows are white, the even numbered rows are grey) and such things. Just not too many logic.

· Let's have a look at PerlMonks
No, I am not going to critizise PM. I was just thinking how PerlMonks would be written if it would use HTML::Template (does it, actually)? For example, let's have a look at the nodelets column.
PM offers a couple of nodelets, all of which have other contents (XP Nodelet: only text; Personal Nodelet: links which the user can specify, chatterbox: text and a form, voting booth: a form).
Not only are users able to choose which nodelets they want to see, also they're able to choose in which order the nodelets will be shown.

· One way
The very easiest way of implementing this, is to just create a loop in the HTML template, that uses only two variables: nodelet_title and nodelet_contents. The contents, in this case, will contain HTML tags to create the links and forms and such. So this violates the first rule.
This way, if you want to create a new nodelet, you only have to modify the Perl script. The template will automatically accept the new nodelet because it will get the title and the contets just in one of the iterations of the loop.

· Another way
Another way is to create a loop which will get the nodelet titles. Then, for every title you make an if-tag and within the if-tag, the proper variables are retrieved (eventually with the use of loops (within loops (within loops))).
This moves the design issues to the template. Also, it moves much of the logic to the template. Besides, if you want to create a new nodelet, both the Perl code and the template need to support the new nodelet.

· Conclusion
I think it is never trully possible to separate design and logic, unless with a fairly simple interface where everything will be as the coder and/or designer wants it to be. Whenever it gets more complex (more customizable for instance) it will become harder to separate the two.
Update: fixed some typo's and grammar errors. Thanks to injunjoel

Replies are listed 'Best First'.
Re: HTML - sharing design and logic
by dfaure (Chaplain) on Jul 01, 2004 at 12:59 UTC
    I think it is never trully possible to seperate design and logic

    IMHO, you should take care to differentiate applicative-logic and GUI-logic, and consider 3 abstraction layers:

    1. HTML-Template data, aka GUI elements, look-and-feel, skins, whatever you call it.
    2. GUI-logic, tiny code elements, totally dedicated to data appearance. There you'll use HTML::Template modules or equivalent to handle HTML data from above layer. Taking an OO-approach, you may define here a "widgets" hierarchy of specialized objects.
    3. Lastly, You'll have applicative-logic dedicated to manage applicative-datas and providing them to users through the help of above layer functionnalities.

    Pro: Design and logic are separated.

    Cons: You'll have to stricly follow the rules of responsability separation when developping the differents layers. Anyway, you'll have a bit more code to produce and support all caveats involvde (more code => more bugs => more tests required => less time).

    This kind of slicing gives you the basements to build applications decribed as 'Model-View-Controller' in Design-Pattern litteracy.

    Updated:corrected some typos and added schematic.

    HTH, Dominique
    My two favorites:
    If the only tool you have is a hammer, you will see every problem as a nail. --Abraham Maslow
    Bien faire, et le faire savoir...

Re: HTML - sharing design and logic
by perrin (Chancellor) on Jul 01, 2004 at 15:00 UTC
    The point is not to keep ALL logic out of your template but to keep everything except display logic out. Your "another way" approach does not put any application logic (database work, user pref manipulation, etc.) in the template. Having to update both the Perl code and the templates when adding a new thing to be displayed is not a bad thing. There are always these two tasks (update code, update display) even if you have no separate templates.

    By the way, I would make each nodelet a separate included template, and just pass a list of nodelet templates to include.

Re: HTML - sharing design and logic
by hardburn (Abbot) on Jul 01, 2004 at 12:57 UTC

    No HTML tags should be in the Perl code

    This is a nice dream. However, HTML won't allow it. The best example is in specifying an option in a select list:

    <select name="options"> <option>1</option> <option>2</option> <!-- select this one --> <option>3</option> </select>

    If HTML allowed you to make the selection in the select tag itself (like <select name="options" option="2">), then this wouldn't be a problem. As it is, there are numerous ways to solve the problem, none of which are particularly satisfying.

    I haven't looked at XForms much (though I like what I have read about it), so I'm not sure if it fixes this problem.

    send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

      Select lists are simple to populate using HTML::FillInForm. Templates get cluttered up very quickly if you try to fill in forms using template tags. They also become much harder to validate (eg <input type="text" name="foo" value="<TMPL_VAR NAME="foo">" />). Also, if you allow the code to generate the form fields, then you remove the ability of the template designer to change the form fields.

      You may argue that HTML::FillInForm needs to have some HTML code in it in order to be able to fill in the HTML form. But it is effectively doing the same thing as a template parser, searching through the HTML for tags that it recognizes (ie HTML form fields), and altering them by assigning a value to the form field. It in no way limits what the template designer can do with the template (ie a select list could be replaced with a series of radio buttons without requiring any code changes, and without needing to alter or adjust any template tags for that matter).

      Of course HTML::FillInForm doesn't actually generate the form fields for you, but that is really the job of the Template anyway. In my templates I always try to statically define my form fields unless an option list is dynamically generated by the code. Then a simple loop will do (remember, there will always be some logic in your templates, but it should be display logic only).

      Separating code and HTML is easy. You just need to find the right toolset that works for you...

      - Cees

        Hmm this one is rather interesting!
        Thank you a lot!
        "2b"||!"2b";$$_="the question"
      Well, I'd say you could do this by placing the select tag within the template, then use a loop to place all the options and use the template's IF tag to insert the 'selected' keyword.

        Yes, you can do it that way, and many people do. It makes the templates really, really ugly. If there is a clean solution to this, I haven't seen it yet. Ironically, some of the cleanest ones I've seen involve creating the HTML on the Perl side (though usually with a backend module doing the actual HTML generation).

        send money to your kernel via the boot loader.. This and more wisdom available from Markov Hardburn.

Re: HTML - sharing design and logic
by kiat (Vicar) on Jul 01, 2004 at 14:04 UTC
    Hi MUHA,

    Same sentiment here. Basically, the options are as follows:

    1) no attempt at separation - the perl script contains both code and html

    2) some attempt at separation - part of the logic is moved to the template

    3) strict separation - no html in code

    (3) gives you clean and highly maintainable code but is hard to achieve in some cases. I've been through (1) and the result is ugly and difficult-to-maintain code (which has lots of html in it). (2) seems like a neat solution :)

Re: HTML - seperating design and logic
by l3nz (Friar) on Jul 03, 2004 at 08:09 UTC
    I have worked extensively with templating systems (mostly in Java Model 2 webapps, I fear) and I believe that what actually matters is separating data production from display logic. This usually means that on one side you decide WHAT has to be shown to the user and on the other side you decide HOW. This does not automagically imply that all logic has to be on the first side; and this is a serious flaw of pure-templating systems. As the templating logic might be weak, you end up doing elaborations in the WHAT part just to fill in HTML controls. This is the wrong way to do it.

    My best experiences have been with Model 2's where:

    • All appication flow logic is centrally managed (might be a servlet, or an invonking stub cgi, or what), together with security and sessions and error control.
    • Data elaboration (the WHAT) is modularly loaded by the central manager, so you can plug and play new logic in the system
    • Data presentation logic (the HOW) is altogether independent but heavily programmable; might be a different CGI, or a JSP/ASP page or a Perl module called after the proper elaboration took place; anything that might load an external library for common layout units
    • HTML controls are not embedded in the template as pure text but as function calls. This way is easy to accomodate all the quirks of HTML like SELECTs, radio buttons, disabled fields, hidden fields and all the other pure HTML nuisances. You can also build "custom" controls, like e.g. a Date control made of three combos (day, month, year) that you want to use logically as a single unit.
    Hope this helps (though not too much Perl-specific...)
Re: HTML - seperating design and logic
by MidLifeXis (Monsignor) on Jul 01, 2004 at 17:41 UTC

    You could also drive your "nodelet_title" / "nodelet_contents" method within a Nodelet class, which, when subclassed, fills nodelet_contents from its own private template file.

    So you end up with a top-level display module, and each of the "objects" contained within are able to generate their own contents, possibly through their own templates. I am currently using this, am able to keep the logic and display seperate, and have not run into too many problems.

    Most of y problems come down to data structures, and shifting between structures for the program and structures for the display (H::T) has been reduced to a couple of translation routines.


Re: HTML - seperating design and logic
by submersible_toaster (Chaplain) on Jul 03, 2004 at 11:45 UTC
    You raise a valid point, what concerns me the most with code I write and/or maintain is when architecture says that code and display logic are supposed to be seperate but you end up resorting to stuff like.
    my $t= HTML::Template->new( $sometemplate ); my $insert = $q->table ( $self->build_some_table ); $t->param ( bigtable=>$insert );
    This is obviously a naff example, since $insert should be a TMPL_INCLUDE (if you talk HTML:Template).

    As raised earlier , display logic within templates is seen to be a necessary evil, less important that seperating WHAT data should be rendered as opposed to HOW that data should be presented. Your code should build valid structures of data that make sense to your templating system.

    What this suggests to me is that there is room in the design for a pre-output process between generating valid data and filling a template with that data. When I find myself writing objects with a data struct one way, but a method to output something that makes sense to a template system. eg

    my $self = Some::CGI::Class->new( %params ); $self->update_data; return $self->template_data;
    It feels like the reformatting of my object's data for a template system is NOT the responsibility of my object. There ought to be a preprocessing phase. Yet another level of complexity. This pre-processing stage is where I would expect the addition of things like odd/even line BG color changes, or turning a structure inside out to list it as entities by sorted key. For example , your method returns an hash of object references with names as keys that are valid and relevant to the current application's run_mode, you pass that data structure to a template preprocessor because you would like the data ordered by keys and flattened into an array of hashes suitable for a TMPL_LOOP. MIght look more like.
    $self->update_data; my $t = HTML::Template->new( $sometemplate ); my $tpp = HTML::Template::PreProcessor->( hash=>'sorted' , style=>'arr +ay' , object=>$self ); $t->param ( $tpp->preprocess ); return $t->output;

    I can't believe it's not psellchecked

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://371039]
Approved by herveus
Front-paged by rlb3
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-24 05:51 GMT
Find Nodes?
    Voting Booth?

    No recent polls found