=head1 NAME
 
Text::Forge Style Guide

=head1 SYNOPSIS

  <%

    # This is a code block.
    do_something_interesting(
      $with_some,
      \@very_very,
      \%interesting_arguments,
    );

  %>

  <%
    if ($something) {
      if ($dangerous) {
        # This is something dangerous
  %>
  <em>Danger! Danger!</em>
  <%
      } else {
        # This is something that is not dangerous
  %>
  I see something, but it doesn't seem to be dangerous.
  <%
    } else {
      # There is nothing here
  %>
  Nope, there's nothing there.
  <%
    }
  %>

  I told $who to get <%$ $inside?"out":"back in" %>!!!


=head1 DESCRIPTION
 
Text::Forge shares one important trait with perl: it can be as readable or as
unreadable as you like.

Good code is easy to read and maintain; poor code is difficult to learn and to
modify. This leads us to believe that anything that tends to make code easier
to read or modify makes it better, while anything that detracts from these two
things makes it worse.

Let's examine some best practices in writing Text::Forge documents that are
legible and maintainable.


=head2 Large Code Blocks

Large code blocks are usually found before any output is generated. It is best
to keep code -- even unrelated code that is still adjacent -- together in one
block. The block should only be separated if you want to put some text in
between.

Normally, you want to start and end a block with a 'C<< <% >>' and 'C<< %> >>'
on a line by itself. Keep at least one blank line after the beginning and
before the end to make sure it is clearly visible.

However, some people like to save vertical screen space and join the line with
the C<< <% >> and C<< %> >> with the code. Some prefer to indent the opening
C<< <% >>. This is especially true when you have a very small code block.
Whatever you decide to do, it is probably best to standardize it among your
team.

Also, be sure to indent the code, like you would indent code in curly braces
(C<{>, C<}>) or parentheses (C<(>, C<)>).

Here are three examples of common ways to format some code blocks. You should
decide which one works for you and stick with it.

  <%
    while (shift @options) {
  %>
  Another option is $_->{name}.
  <%
      if ($_->{benefits}) {
  %>
  The benefits of this option are: <%$ join ", ", @{$_->{benefits}} %>.
  <%
      }
    }
  %>

  <% while (shift @options) { %>
  Another option is $_->{name}.
  <%   if ($_->{benefits}) { %>
  The benefits of this option are: <%$ join ", ", @{$_->{benefits}} %>.
  <%   }
     } %>

  <% while (shift @options) { %>
  Another option is $_->{name}.
    <% if ($_->{benefits}) { %>
  The benefits of this option are: <%$ join ", ", @{$_->{benefits}} %>.
    <% } %>
  <% } %>

It's also considered good practice to avoid putting large blocks of
code into Text::Forge templates. Templates are designed to be simple
and readable - a harmony of perl and plain text. Consider abstracting
large code blocks into appropriately named packages.
 
  <%
    use Time::Duration;
  %>
  This page has been "running" for <%$ Time::Duration->runtime() %>.

=head2 Text Intertwined With Code

It is extremely easy to get confused when you are mixing perl code with
regular text. This is most common when you have text that is dependent on
multiple conditions or nested loops.

The best way to handle this is to think of each piece of code as a separate
block. The code may grow in the future as well, so this tends to increase
maintainability.

For HTML, you need to be strategic with your placement of the markers so that
whitespace isn't introduced in the wrong places. Note that a closing marker
followed directly by a newline does not translate to a newline. The next line
of text is treated as if it directly followed the closing tag. 

A good text editor will be able to distinguish between the HTML code and the
perl code. The highlighting cues will be more than enough to see how the code
is structured, as well as how the HTML is structured. Text::Forge highlighting
is available for ViM and Emacs.
 
  <%
    foreach my $q (@questions) {

      # Show the question text
  %>
  <table>
    <tr>
      <td>$q->{text}</td>
    </tr>
    <tr>
      <td>
  <%
 
      # Show the options

      if ($q->{type} eq 'checkbox' or $q->{type} eq 'radio') {
        # We are doing checkboxes or radio buttions.

        foreach my $a ($q->{answers}) {
          # Working through each answer one by one
  %>
        <input type="$q->{type}" name="$q->{id}" value="$a->{id}"
          <%$ $q->{selected}?"checked":"" %> />$a->{text}<br />
  <%
        } 

      } else {
        # We are doing a dropdown
  %>
        <select name="$q->{id}">
  <%

        foreach my $a ($q->{answers}) {
          # Working through each answer one by one
  %>
          <option value="$a->{id}"
            <%$ $q->{selected}?"selected":"" %>>$a->{text}</option>
  <%

        }
  %>
        </select>
  <%
      }
  %>
      </td>
    </tr>
  </table>
  <%
    }
  %>


=head2 Code Snippets

Oftentimes, it is more readable to use small snippets of code that directly
translate into real text than to store the text in a variable and use it later.
In this case, try to keep the code flowing with the text. Here are some
examples.

  You can choose one of these options: <%$ join ", ", @options %>

  Your contract expires <%$ $days_left>30?"in a while":"very soon" %>.

And since templates are always part of the text, it may be wise to include them
in a single line by themselves everytime they are used. This makes them much
more identifiable.
 
  <% $forge->include("my_template", @with_my_args) %>
  

=head2 Direct Substitutions
 
Using direct substitutions in text tend to increase readability and
maintainability.

  Hello $first_name, I'm glad to see you this $weekday morning!

Be sure you know what is in the variable before doing this. You usually want to
encode input from the user or from another source to be sure that it won't harm
the formatting of your text, or do much worse like embedding Javascript in an
HTML page.

  We'll deliver "<%= $book_title %>" immediately to your house!

Remember that pre-encoding the variable is wise if it is going to be used
more than once.

  <%
    $name = $forge->encode_entities($name);
  %>
  Hello, $name!
  ...
  As a member of our website, $name, you are entitled to certain benefits.


=head2 Coding with HTML People

It is common to split the jobs between a web programmer and a web designer. The
programmer is responsible for making the text conditional and putting in
business logic. The web designer is responsible for making the HTML work on a
variety of browsers and keeping track of the tables.

As a web programmer, it is risky to play with the HTML code of the web
designer. They know how to make the HTML work with a variety of browsers and
one small change can affect certain browers in big ways. As a web designer, it
is difficult to read perl code, and so it is hard to identify where to modify
the HTML code.

The web programmer should be responsible for making the perl code explicit,
especially as the code is near or intermixed with HTML. Using comments is
extremely useful. The web designer should become familiar with how C<for>,
C<while>, and other loops work. They should also understand what C<if>,
C<elsif>, and C<else> mean, and how that affects what is shown. The web
programmer should try to keep these statements explicit, using simple logic or
well-named variables. In short, perl is an expressive language, and the web
programmer should try to express perl in something close to English.

Here is some sample code to show how the web programmer can make the web
designer's job a little easier.

  <%
    if ($is_member) {
      if ($must_renew_soon) {
        # Is a member, but must renew soon.
  %>
  You are a member, but you must renew soon.
  <%
      } else {
        # Is a member, but doesn't have to renew soon.
  %>
  You are a member.
  <%
      }
    } else {
      # Not a member
  %>
  You are not a member yet. Sign up now!
  <%
    }
  %>
  

Be sure to keep the two people in each position talking with each other. When
the web programmer doesn't understand why HTML is structured a certain way,
they should ask the web designer. When the web designer doesn't know how to
modify the page, they should ask the web programmer.

=head1 SEE ALSO

Text::Forge Tutorial

Text::Forge

=head1 AUTHOR

Jonathan Gardner <jgardn@alumni.washington.edu>

Contributions and suggestions made by Adam Monsen and Maurice Aubrey.

=head1 COPYRIGHT

Copyright E<copy> 2002, Jonathan Gardner

This document is licensed under the GNU Free Documentation License.
