<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>
      Construindo um Website Din&acirc;mico
      com Class::DBI, CGI::Application e Template Toolkit
    </title>
    <style type="text/css">
      body { padding-left: 10%; padding-right: 8%; }
      p { text-align:justify; font-family: sans-serif; }
      div.title p:first-child{ font-weight: bold; font-size: 200%; text-align: center; }
      div.title p{ font-weight: bold;
                   text-align: center;
                   font-size: 85%;
                   margin-left: 15%;
                   margin-right: 15%;
                 }
      div.preface p:first-child { margin-top: 0px;
                                  font-style: normal;
                                  font-weight: bold;
                                  font-size: 120%;
                                  text-align: left;
                                  text-decoration: underline;
                                }
      div.preface p { text-align: justify;
                      font-style: italic;
                      margin-left: 10%;
                      margin-right: 10%;
                      font-size: 80%;
                    }
      div.paragraph p { text-align: justify; }
      div.paragraph p:first-child { margin-top: 0px;
                                          font-weight: bold;
                                    font-size: 120%;
                                    text-decoration: underline;
                                  }
      pre.code { font-family: monospace;
                 font-size: 80%;
                 border: thin solid lightgray;
                 padding-top: 10px;
                 padding-left: 15px;
                 padding-bottom: 10px;
                 background-color: LightGray;
                 margin-left: 10%;
                 margin-right: 15%;
               }
      pre.code span.reserved-word { font-weight:bold; }
      
      div.display { text-align: center; }
    </style>
  </head>
  <body>
    <div class="title">
      <p>Construindo um Website Din&acirc;mico com Class::DBI, CGI::Application e Template Toolkit    </p>
      <p>Por Luis Campos de Carvalho, L&iacute;der do S&atilde;o Paulo Perl Mongers<br>
      mailto: monsieur_champs [at] yahoo [dot] com [dot] br</p>
    </div>
    
    <div class="preface">
      <p>Pref&aacute;cio</p>
      <p>Quando pensamos em aplicativos World Wide Web em Perl, normalmente nos vêem à cabe&ccedil;a aqueles programas gigantescos, desorganizados, cheios de problemas e praticamente imposs&iacute;veis de se manter. Neste modesto e mal-escrito artigo, eu pretendo mostrar que &eacute; poss&iacute;vel construir aplicativos din&acirc;micos, baseados nas tecnologias da World Wide Web, simples, r&aacute;pidos, f&aacute;ceis de manter e extens&iacute;veis, usando ferramentas de código fonte aberto, no&ccedil;&otilde;es sobre o paradigma da Orienta&ccedil;&atilde;o a Objetos, e algumas t&eacute;cnicas de engenharia de software b&aacute;sica.</p>
    </div>
    
    <div class="paragraph">
      <p>Molhando os P&eacute;s: primeiro contato com as tecnologias utilizadas neste artigo</p>
      <p>Para come&ccedil;ar, vamos falar da aplica&ccedil;&atilde;o que desejamos fazer: &eacute; simples, e chega a ser at&eacute; meio besta, para facilitar a compreens&atilde;o. Desta forma, ao inv&eacute;s de se prender aos detalhes e complexidades da aplica&ccedil;&atilde;o que vamos construir, o leitor ter&aacute; sua aten&ccedil;&atilde;o presa aos detalhes e complexidades envolvidas com <em>como</em> construir a aplica&ccedil;&atilde;o.</p>
      <p>Vamos construir um Módulo de Autentica&ccedil;&atilde;o de Usu&aacute;rios.</p>
      <p>A responsabilidade principal de um Módulo de Autentica&ccedil;&atilde;o de Usu&aacute;rios &eacute; se certificar de que um usu&aacute;rio de nosso website &eacute; realmente quem ele diz ser, e permitir a ele acesso aos demais recursos din&acirc;micos dispon&iacute;veis em nosso website fict&iacute;cio.</p>
      <p>Para construir esta aplica&ccedil;&atilde;o, vamos utilizar um <i>framework</i> de desenvolvimento de aplica&ccedil;&otilde;es din&acirc;micas para a World Wide Web chamado <a href="http://search.cpan.org/~markstos/CGI-Application-4.04_02/">CGI::Application</a>, combinado com um gerenciador de banco de dados relacional (eu escolhi usar o <a href="http://www.postgresql.org">PostgreSQL</a>, mas outros, como o <a href="http://www.mysql.com">MySQL</a> e o <a href="http://www.oracle.com">Oracle</a> se encaixam aqui perfeitamente e n&atilde;o precisam de adapta&ccedil;&otilde;es) atrav&eacute;s do uso de um conjunto de objetos Perl chamado <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a>. Completam o nosso conjunto de bibliotecas-base um <i>framework</i> de visualiza&ccedil;&atilde;o muito poderoso chamado <a href="http://www.template-toolkit.org">Template Toolkit</a> e um pouco de teoria sobre padr&otilde;es de projeto e modelagem orientada a objetos.</p>
    </div>
    
    <div class="paragraph">
      <p>O Projeto da Aplica&ccedil;&atilde;o</p>
      <p>Antes de continuarmos, vamos especificar e modelar rapidamente nossa aplica&ccedil;&atilde;o. Isso, al&eacute;m de nos dar maior consciência sobre o que estamos construindo, ajuda as pessoas a compreender nosso trabalho (e a valoriz&aacute;-lo).</p>
      <p>Nosso Módulo de Autentica&ccedil;&atilde;o de Usu&aacute;rios ter&aacute; apenas um ponto de entrada: ele gerar&aacute; uma p&aacute;gina para coletar o nome e senha do usu&aacute;rio, tomar&aacute; uma decis&atilde;o baseado nos dados que o usu&aacute;rio lhe enviar e executar&aacute; uma das duas &uacute;nicas a&ccedil;&otilde;es planejadas para ele: ou criar&aacute; uma sess&atilde;o para o usu&aacute;rio e o redirecionar&aacute; para a parte restrita de nosso website din&acirc;mico, ou enviar&aacute; uma mensagem de erro, informando ao usu&aacute;rio que o par (nome, senha) apresentado n&atilde;o &eacute; v&aacute;lido. Em <em>Portugol</em>, para ficar simples:</p>
      
      <pre class="code">  <span class="comment"># Processo 1: coleta de credenciais</span>
  <span class="reserved-word">IN&Iacute;CIO;</span>
    constrói p&aacute;gina de coleta de dados;
    envia p&aacute;gina de coleta de dados;
  <span class="reserved-word">FIM.</span>
  
  <span class="comment"># Processo 2: autentica&ccedil;&atilde;o de usu&aacute;rios.</span>
  <span class="reserved-word">IN&Iacute;CIO;</span>
    &lt;usu&aacute;rio preenche informa&ccedil;&otilde;es de autentica&ccedil;&atilde;o&gt;;
    recebe dados de autentica&ccedil;&atilde;o de usu&aacute;rio;
    verifica dados;
    <span class="reserved-word">SE</span> dados v&aacute;lidos, <span class="reserved-word">ENT&Atilde;O</span>
      <span class="reserved-word">IN&Iacute;CIO</span>
        gera informa&ccedil;&atilde;o de sess&atilde;o;
        registra informa&ccedil;&atilde;o de sess&atilde;o;
        envia <i>cookie</i> identificador ao usu&aacute;rio;
        redireciona usu&aacute;rio autenticado para a aplica&ccedil;&atilde;o;
      <span class="reserved-word">FIM</span>
    <span class="reserved-word">SEN&Atilde;O</span>
      <span class="reserved-word">IN&Iacute;CIO</span>
        gera p&aacute;gina de informa&ccedil;&atilde;o de erro;
        envia p&aacute;gina ao usu&aacute;rio;
      <span class="reserved-word">FIM;</span>
    <span class="reserved-word">FIMSE;</span>
  <span class="reserved-word">FIM;</span></pre>

      <p>Agora que sabemos como deve ser nosso processo, vamos modelar rapidamente os dados necess&aacute;rios para autenticar um usu&aacute;rio. Precisamos apenas reter permanentemente algumas informa&ccedil;&otilde;es sobre os usu&aacute;rios, como um nome, e uma senha. Para isso, vamos criar uma tabela em nosso banco de dados relacional, utilizando este código SQL:</p>
      <p>Isto vai criar uma tabela em nosso banco de dados, onde poderemos registrar nossos usu&aacute;rios.</p>

      <pre class="code">-- Este script assume que voc&ecirc; tem um banco de dados PostgreSQL, pode
-- conectar-se a ele e tem permiss&otilde;es m&iacute;nimas para realizar cria&ccedil;&atilde;o de
-- tabelas e inclus&atilde;o de registros nas tabelas criadas.

-- Se voc&ecirc; tiver qualquer problema com isso, converse com seu DBA ou
-- Administrador de Sistemas local.

-- Copyleft 2005 Luis Campos de Carvalho
-- Copyleft 2005 Engenharia de Software Ltda
-- Doado aos S&atilde;o Paulo Perl Mongers

-- This script is free software; you can redistribute it and/or modify
-- it under the term of the GNU Public License.

CREATE SEQUENCE seq_usuario;

CREATE TABLE usuario (
  uid   INTEGER PRIMARY KEY DEFAULT NEXTVAL( 'seq_usuario'::text ),
  login VARCHAR UNIQUE      NOT NULL,
  senha VARCHAR             NOT NULL
);

-- EOF </pre>

    <p>A aplica&ccedil;&atilde;o do <a href="http://www.w3schools.com/sql/default.asp">SQL</a> no banco de dados varia muito. Por isso, vou deixar a tarefa de descobrir como se conectar ao banco de dados e criar tabelas para um futuro artigo sobre <a href="http://search.cpan.org/~timb/DBI-1.48/">DBI</a> e <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a>.</p>
    <p>Vamos passar agora &agrave; parte de modelagem de objetos e módulos necessários para a aplicação. Para isso, antes, precisamos conversar um pouco sobre <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>, <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a>, <a href="http://www.template-toolkit.org">Template Toolkit</a> e <a href="http://search.cpan.org/~markstos/CGI-Application-4.03/">CGI::Application</a>.</p>
    </div>
  
  <div class="paragraph">
    <p>MVC, Class::DBI e CGI::Application</p>
    <p>Agora vamos entrar na parte complicada deste tutorial. O leitor amigo possivelmente deve ter ouvido alguma coisa a respeito de <a href="">MVC</a>, ou, para os iniciados, <em>Model-View-Controller</em>. Este &eacute; um padr&atilde;o de projeto (<em>Design Pattern</em>) que separa toda e qualquer aplica&ccedil;&atilde;o em tr&ecirc;s componentes b&aacute;sicos: o Modelo(<em>Model</em>), a Vis&atilde;o (<em>View</em>) e o Controlador (<em>Controller</em>). Leiam um <a href="http://www.andywardley.com/computers/web/mvc.html">contraponto</a>, por <a href="http://www.wardley.org/">Andy Wardley</a>.</p>
    <p>Em poucas palavras, j&aacute; que eu n&atilde;o pretendo nem de longe esgotar este assunto: o <b>Modelo</b> &eacute; respons&aacute;vel por manter nossos dados e manipul&aacute;-los de acordo com as regras de neg&oacute;cio (que implementamos neles). S&atilde;o os modelos (geralmente temos muitos) que sabem como e onde armazenar e recuperar os dados que captamos e utilizamos.</p>
    <p>Enquanto os modelos s&atilde;o respons&aacute;veis pelos dados e pelas regras de neg&oacute;cio (a forma de manipular os dados), as <b>Vis&otilde;es</b> tem como responsabilidade a exibi&ccedil;&atilde;o dos dados encontrados nos modelos. Uma vis&atilde;o normalmente conhece um modelo e sabe como exibir os dados daquele modelo por alguma m&iacute;dia espec&iacute;fica. Por exemplo: suponha que temos uma lista de usu&aacute;rios (um Modelo representando usu&aacute;rios) e desejamos exibir estes usu&aacute;rios pela internet (com <a href="http://www.w3.org/MarkUp/">HTML</a>) e em um telefone celular (com <a href="http://www.umtsworld.com/technology/wap.htm">WAP</a>). Para tornar isso poss&iacute;vel, n&atilde;o precisamos mexer em nada relacionado com nossa lista de usu&aacute;rios: precisamos apenas implementar Vis&otilde;es capazes de exibir em HTML ou WAP. Assim, quando desejamos exibir a lista de usu&aacute;rios em HTML, utilizamos a vis&atilde;o capaz de exibir a lista em HTML e quando desejamos exibir nossos usu&aacute;rios em WAP, utilizamos a vis&atilde;o que implementa exibi&ccedil;&atilde;o WAP.</p>
    <p>Finalmente, o <b>Controlador</b> tem um papel n&atilde;o muito intuitivo, mas muito importante, depois que se aprende a utiliz&aacute;-lo corretamente: &eacute; dele a responsabilidade de decidir, para cada requisi&ccedil;&atilde;o enviada para nossa aplica&ccedil;&atilde;o, qual modelo deve ser acionado para tratar dela. &Eacute; tamb&eacute;m do Controlador a responsabilidade de verificar as credenciais de um usu&aacute;rio e determinar suas permiss&otilde;es de acesso. Normalmente, uma aplica&ccedil;&atilde;o web tem apenas um controlador, n&atilde;o importa o qu&atilde;o grande ela seja.</p>
    <p>A esta altura, voc&ecirc; deve estar se perguntando qual a rela&ccedil;&atilde;o disso tudo com as bibliotecas Perl <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a>, <a href="http://www.template-toolkit.org">Template Toolkit</a> e <a href="http://search.cpan.org/~markstos/CGI-Application-4.04_02/">CGI::Application</a>. &Eacute; hora de explicar: cada uma desta bibliotecas implementa um dos elementos do MVC que vamos utilizar em nossa aplica&ccedil;&atilde;o: <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a> implementa modelos, <a href="http://www.template-toolkit.org">Template Toolkit</a> implementa vis&otilde;es e CGI::Aplication implementa nosso controlador. Vamos construir agora cada uma das diferentes partes do padr&atilde;o de projeto que utilizaremos:</p>
  </div>
  
  <div class="paragraph">
    <p>Implementa&ccedil;&atilde;o da Camada de Acesso a Dados com Class::DBI</p>
    <p>Para implementar o modelo, vamos precisar de ajuda de mais um padr&atilde;o de projetos, o <i>Data Access Object</i>, ou <a href="http://en.wikipedia.org/wiki/Data_Access_Object">DAO</a>, para os íntimos.</p>
    <p>Este padr&atilde;o de projeto consiste em manter objetos separados para cuidar das responsabilidades específicas de manipular e armazenar os dados. Fazemos isso para que, quando precisarmos alterar a forma ou o local de armanzenamento das informa&ccedil;&otilde;es, n&atilde;o precisemos alterar nossos processo de manipula&ccedil;&atilde;o de dados, apenas o processo de armanzenamento e recupera&ccedil;&atilde;o. Isto torna menor a possibilidade de introdu&ccedil;&atilde;o de novos erros em um sistema antigo por mudan&ccedil;as menos importantes para o neg&oacute;cio.</p>
    <p>Para implementar o DAO, vamos utilizar uma biblioteca pronta. Isto &eacute; muito melhor que ser obrigado a "reinventar a roda" e construir n&oacute;s mesmos.</p>
    <p>Optamos pela biblioteca <a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a>. Poder&iacute;amos ter optado por outras semelhantes, como a <a href="http://search.cpan.org/~cwinters/SPOPS-0.87/">SPOPS</a>, que tem funcionalidade semelhante, mas oferece muitos recursos extras.</p>
    <p><a href="http://search.cpan.org/~tmtm/Class-DBI-0.96/">Class::DBI</a> deve ser implementada atrav&eacute;s de extens&atilde;o do objeto Class::DBI, e declara&ccedil;&atilde;o de alguns m&eacute;todos est&aacute;ticos para informar &agrave; biblioteca sobre nosso banco de dados, nossas tabelas e nosso m&eacute;todo preferido de carga de dados. Adicionalmente, podemos ir al&eacute;m e implementar m&eacute;todos para desempenhar tarefas mais espec&iacute;ficas, como algum tipo de <i>query</i> especial para nossa aplica&ccedil;&atilde;o, ou outras funcionalidades semelhantes. Mas isso tamb&eacute; est&aacute; fora do nosso escopo de hoje. Vamos ver como deve ser nossa classe-base, devidamente comentada:</p>

    <pre class="code">=head1 NAME

DAO::Base - Classe base para objetos de acesso a dados

=cut

package DAO::Base;

use strict;
use warnings;

use base qw( Class::DBI );

our $VERSION = sprintf '%d.%02d', q$Revision:$ =~ m/(\d+)\.(\d+)/;

=head1 SYNOPSIS

  use base qw( DAO::Base );

=head1 DESCRIPTION

  Esta é a classe base dos Objetos de Acesso a Dados, derivados de
  Class::DBI.

=cut

__PACKAGE__->connection( 'dbi:Pg:dbname',
                         'dbuser', 'secret',
                         { AutoCommit => 1,
                           RaiseError => 1,
                           PrinError  => 0,
                         }
                       );

=head1 AUTHOR

  Luis Campos de Carvalho
  Engenharia de Software Ltda.

=head1 REVISION

  $Revision: $

=head1 COPYRIGHT

  Copyleft 2005 Engenharia de Software Ltda.

  Doado aos São Paulo Perl Mongers.

  This module is free software; you can redistribute it and/or modify it
  under the term of the GNU Public License.

=head1 SEE ALSO

    L&lt;Class::DBI&gt;
</pre>
        
    <p>Este m&oacute;dulo &eacute; composto de algumas declara&ccedil;&otilde;es interessantes: primeiramente, o nome do pacote <code>package DAO::Base</code> foi escolhido com finalidade did&aacute;tica. &Eacute; simples modificar isto quando for utilizado em um projeto s&eacute;rio (sim, estou acreditando que as pessoas v&atilde;o se aproveitar deste c&oacute;digo em projeots s&eacute;rios!).</p>
    <p>A pr&oacute;xima coisa interessante a se notar &eacute; relacionada com heran&ccedil;a: eu declarei que este pacote tem como base (e herda funcionalidades de) Class::DBI, com a asser&ccedil;&atilde;o <code>use base qw( Class::DBI );</code> isto &eacute; equivalente a dizer <code>BEGIN{ require Class::DBI; push @ISA, 'Class::DBI'; }</code>, mas &eacute; bem mais curto e f&aacute;cil de entender.</p>
    <p>Tamb&eacute;m &eacute; neste m&oacute;dulo que devemos declarar os dados de conex&atilde;o com nosso banco de dados, para que ela possa ser compartilhada transparentemente entre todos os m&oacute;dulos derivados deste. Declaramos nossa conex&atilde;o utilizando o m&eacute;todo est&aacute;tico <code>Class::DBI::connection()</code>, mas o chamamos com <code>__PACKAGE__->connection()</code>. Isto &eacute; boa pr&aacute;tica de programa&ccedil;&atilde;o orientada a objetos em Perl, j&aacute; que n&atilde;o podemos assumir qual o tipo que ser&aacute; passado para n&oacute;s quando da instancia&ccedil;&atilde;o desta classe. A diretriz <code>__PACKAGE__</code> cuida sozinha destes detalhes, fazendo a coisa certa por n&oacute;s. Ela sempre vai resolver para o nome do pacote correto, n&atilde;o importa o que aconte&ccedil;a. Para saber mais sobre os par&acirc;metros passados ao banco de dados, por favor consultem a documenta&ccedil;&atilde;o do <a href="http://search.cpan.org/~timb/DBI-1.48/">DBI</a>.</p>
    <p>Depois de declarar nossa conex&atilde;o com o banco de dados, estamos prontos para extender esta classe e especializ&aacute;-la para cada uma das tabelas que teremos.</p>
    <p>A &uacute;nica tabela que teremos neste sistema &eacute; a tabela de usu&aacute;rios. Mas lembrem-se: para extender este sistema para um sistema completo e &uacute;til, basta seguir a mesma linha de pensamento que estamos desenvolvendo aqui e continuar implementando as funcionalidades restantes.</p>
    <p>Nosso objeto de acesso a dados de usu&aacute;rio ser&aacute; declarado desta forma:</p>
  
    <pre class="code">=head1 NAME

  DAO::Usuario - Objeto de Acesso a Dados da tabela 'usuario'.

=cut

package DAO::Usuario;

use warnings;
use strict;

use base qw( DAO::Usuario );

our $VERSION = sprintf '%d.%02d', q$Revision:$ =~ m/(\d+)\.(\d+)/;

=head1 SYNOPSIS

  use DAO::Usuario; $user = DAO::Usuario->create( ... ); $user =
  DAO::Usuario->retrieve( ... ); $user = DAO::Usuario->search( ... );

=head1 DESCRIPTION

Este é o módulo de acesso a dados da tabela de usuarios do sistema de
autenticacao de usuarios desenvolvido para o mini-curso da UNISAL.

=cut

__PACKAGE__->table( 'usuario' );
__PACKAGE__->columns( All => qw[ id login senha ] );

=head1 AUTHOR

  Luis Campos de Carvalho Engenharia de Software Ltda.

=head1 REVISION

  $Revision: $

=head1 COPYRIGHT

  Copyleft 2005 Engenharia de Software Ltda.

  Doado aos São Paulo Perl Mongers.

  This module is free software; you can redistribute it and/or modify
  it under the term of the GNU Public License.

=head1 SEE ALSO

L&lt;Class::DBI&gt;
</pre>
  
    <p>Reparem que este m&oacute;dulo se parece muito com o outro. Declaramos um pacote no mesmo n&iacute;vel, <code>DAO::Usuario</code>, para modelar nossos usu&aacute;rios. Em seguida, declaramos que herdamos as fucnionalidades de <code>DAO::Base</code>, em especial duas muito importantes: 1) &eacute; de l&aacute; que vem nossas informa&ccedil;&otilde;es de banco de dados, que vamos precisar para fazer com que este m&oacute;dulo possa recuperar e armazenar alguma informa&ccedil;&atilde;o no banco de dados; e 2) como <code>DAO::Base</code> herda de <code>Class::DBI</code> (lembra?), tamb&eacute;m nosso m&oacute;dulo herda as funcionalidades implementadas l&aacute;. &Eacute; este pequeno detalhe que faz com que tudo isso funcione perfeitamente.</p>
    <p>As declara&ccedil;&otilde;es que precisamos fazer aqui s&atilde;o simples: precisamos declarar qual tabela este m&oacute;dulo acessa, e quais os campos da tabela que estar&atilde;o vis&iacute;veis para nossa aplica&ccedil;&atilde;o. N&atilde;o, voc&ecirc; n&atilde;o precisa declarar todos os campos como vis&iacute;veis. Mas n&atilde;o h&aacute; como o <code>Class::DBI</code> conhecer (ou utilizar) os campos que voc&ecirc; n&atilde;o declarar. Use isto com sabedoria.</p>
    <p>Para declarar tabelas, utilizamos a diretriz auto-explicativa <code>__PACKAGE__->table( 'usuario' )</code>. Como todos j&aacute; perceberam, o &uacute;nico par&acirc;metro passado (o nome da tabela) &eacute; obrigat&oacute;rio.</p>
    <p><strong>Depois</strong> (lembrem-se: <strong>Depois</strong>!) de declarar qual tabela desejamos acessar, podemos ent&atilde;o declarar quais colunas desta tabela desejamos que nosso m&oacute;dulo veja. Note que isso implica que podemos ter tabelas com quantos atributos desejar, e podemos controlar quais m&oacute;dulos acessam que colunas atrav&eacute;s desta declara&ccedil;&atilde;o.</p>
    <p>Para declarar as colunas vis&iacute;veis, utilizamos <code>__PACKAGE__->columns( All => qw[ id login senha ] );</code> isto declara tr&ecirc;s colunas vis&iacute;veis, e <strong>implicitamente</strong> declara que a primeira coluna da lista (<code>id</code>) &eacute; nossa chave prim&aacute;ria.</p>
    <p>Com isso, encerramos a parte de constru&ccedil;&atilde;o da camada de acesso a dados. O que temos at&eacute; este momento s&atilde;o dois objetos simples: <code>DAO::Base</code> e <code>DAO::Usuario</code>. </p>
    <p>Por agora, vamos apenas reservar estes m&oacute;dulos. Vamos precisar deles mais adiante.</p>
  </div>
  
  <div class="paragraph">
    <p>Implementa&ccedil;&atilde;o das Vis&otilde;es com Template Toolkit</p>
    <p>Agora que podemos contar com nossos objetos de acesso a dados, vamos implementar nossas vis&otilde;es. S&atilde;o elas que dar&atilde;o um rosto para nossa aplica&ccedil;&atilde;o, e por isso mesmo devem ser tratadas com um certo cuidado. Como esta &eacute; uma aplica&ccedil;&atilde;o reutiliz&aacute;vel, devemos tomar alguns cuidados extras com a documenta&ccedil;&atilde;o dos <em>templates</em>, para que seja sempre poss&iacute;vel a um desenvolvedor adapt&aacute;-lo &agrave;s suas necessidades.</p>
    <p>Nossa primeira vis&atilde;o precisa pedir ao usu&aacute;rio que entre com seu nome e senha em duas caixas de texto. Tamb&eacute;m precisa oferecer a ele um bot&atilde;o que vai nos levar de volta para a aplica&ccedil;&atilde;o. Nossa segunda vis&atilde;o ser&aacute; utilizada apenas em caso de erros: caso o nome ou senha fornecidos pelo usu&aacute;rio n&atilde;o o identifiquem corretamente, precisamos informar isto a ele. Em caso de autentica&ccedil;&atilde;o positiva, vamos utilizar um redirecionamento HTTP (c&oacute;digo de resposta 302) para indicar ao <em>browser</em> do usu&aacute;rio para onde ir em seguida, e ao mesmo tempo transmitir a este programa as credenciais do usu&aacute;rio que ele conduz.</p>
    <p>Com algum esfor&ccedil;o de desenvolvimento, construimos a primeira vis&atilde;o, que vamos chamar de <code>ask-credentials.tmpl</code>. Ela se parece muito com isso:</p>

    <div class="display">
      <img align="center" valign="middle" src="images/login.gif" alt="quadro de login" border="0" />
    </div>
    
    <p>O c&oacute;digo fonte HTML utilizado para gerar isto &eacute; assim:</p>
    
    <pre class="code">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                          "http://www.w3.org/TR/html4/loose.dtd"&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;meta name="AUTHOR" content="Luis 'Champs' de Carvalho"&gt;
    &lt;style type="text/css"&gt;
      form { font-family: monospace;
             border: thin solid gray;
             position: absolute;
             top: 45%; left: 60%;
             padding-left: 5%;
             padding-right: 5%;
             background-color: lightyellow;
           }
      form p:first-child { font-weight: bold; }
      form p.submit { text-align: right; }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;form action="[% action %]" method="POST" enctype="application/x-www-form-urlencoded"&gt;
      &lt;p&gt;Entrada do Sistema&lt;/p&gt;
      &lt;p&gt;Login:
        &lt;input type="text" name="login" size="16" tabindex="1" align="middle"&gt;
      &lt;/p&gt;
      
      &lt;p&gt;Senha:
         &lt;input type="password" name="passwd" size="16" tabindex="2" align="middle"&gt;
      &lt;/p&gt;
      &lt;p class="submit"&gt;&lt;input type="submit" name="mode" value="Login" tabindex="3"&gt;&lt;/p&gt;
    &lt;/form&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
  
    <p>Preste aten&ccedil;&atilde;o a alguns pequenos detalhes: os nomes dos campos que estamos utilizando s&atilde;o importantes. Vamos conferir: o campo onde o usu&aacute;rio escrever&aacute; seu <em>login</em> chama-se <code>login</code>; o campo onde escrever&aacute; sua senha &eacute; especial (do tipo <code>password</code>, e chama-se <code>passwd</code>; e finalmente, o bot&atilde;o de envio chama-se <code>mode</code>. Isto &eacute; muito importante, pois &eacute; atrav&eacute;s deste campo que a aplica&ccedil;&atilde;o determinar&aacute; qual deve ser o pr&oacute;ximo passo.</p>
    <p>Note tamb&eacute;m que preenchemos o atributo <code>action</code> do <em>tag</em> <code>form</code> com uma esp&eacute;cie de <em>tag</em> especial. Isto &eacute; um comando para o Template Toolkit. Vamos voltar a estes detalhes em breve. Por enquanto, basta prestar aten&ccedil;&atilde;o nisso.</p>
    
    <p>Precisamos ainda de mais uma vis&atilde;o, para informar o usu&aacute;rio que ele n&atilde;o possui credenciais v&aacute;lidas. Ele deve ser assim:</p>
    
    <pre class="code">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
&lt;html&gt;
&lt;!-- $Id$ --&gt;
&lt;head&gt;
  &lt;title&gt;Erro na Autentica&ccedil;&atilde;o!&lt;/title&gt;
  &lt;meta name="AUTHOR" content="Luis 'Champs' de Carvalho"&gt;
  &lt;style type="text/css"&gt;
    p.error { border: thin solid black;
              background-color: red;
              font-weight: bold;
              text-align: center;
              position: absolute;
              left: 35%;
              top: 35%;
            }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;p class="error"&gt;[% error_message %]&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

    <p>Note que voltamos a utilizar um daqueles comandos especiais para o Template Toolkit. Vamos falar sobre isso em alguns instantes. O importante agora &eacute; que isso liq&uuml;ida com o assunto das vis&otilde;es, e nos permite come&ccedil;ar a explicar como deve ser constru&iacute;o o n&uacute;cleo da aplica&ccedil;&atilde;o.</p>

  </div>
  
  <div class="paragraph">
    <p>Introdu&ccedil;&atilde;o ao conceito de Stash</p>
    <p><b>Stash</b> &eacute; simplesmente um conceito. &Eacute; um reposit&oacute;rio de dados semi-p&uacute;blico, que utilizamos para acumular informa&ccedil;&otilde;es sobre a requisi&ccedil;&atilde;o que estamos processando. Eu digo semi-p&uacute;blico por que n&atilde;o podemos acessar o stash de uma requisi&ccedil;&atilde;o exceto se estivermos processando esta requisi&ccedil;&atilde;o.</p>
    <p>Vamos implementar nosso stash com um <i>design pattern</i> chamado <a href="">Singleton</a>, que no nosso caso servir&aacute; para garantir que todas as refer&ecirc;ncias para o stash sejam processadas pelo mesmo stash, dentro de uma determinada requisi&ccedil;&atilde;o.</p>
    <p>Nosso m&eacute;todo stash() &eacute; implementado automaticamente pela biblioteca <a href="">Class::Accessor</a>, que cria automaticamente m&eacute;todos de acesso a estruturas de dados auxiliares, com declara&ccedil;&otilde;es simples como "<code>__PACKAGE__->mk_accessors( qw[ stash ] );</code>".</p>
  </div>
      
  <div class="paragraph">
    <p>Introdu&ccedil;&atilde;o ao Class::Accessor</p>
    <p>Acabamos de falar que alguns m&eacute;todos s&atilde;o gerados autom&aacute;ticamente pela biblioteca Class::Accessor. Por favor n&atilde;o se assustem. Gerar c&oacute;digo em Perl em tempo de execu&ccedil;&atilde;o &eacute; uma coisa normal e at&eacute; esperada. Esta &eacute; uma das principais vantagens e desvantagens das linguagens de programa&ccedil;&atilde;o interpretadas em tempo de execu&ccedil;&atilde;o: todas elas permitem que voc&ecirc; execute trechos de c&oacute;digo que acabou de gerar.</p>
    <p>Para tornar curta uma hist&oacute;ria bem longa, o importante aqui &eacute; o seguinte: ao inv&eacute;z de codificarmos um m&eacute;todo assim:</p>
    <pre class="code">sub stash{
      my $self = shift;
      my $new_stash = shift;
      return $new_stash? $self->{stash} = $new_stash : $self->{stash};
    }</pre>
    <p>Simplesmente solicitamos para a biblioteca Class::Accessor que gere um m&eacute;todo para n&oacute;s com esta "forma". Todos os m&eacute;todos gerados fazem a mesma coisa (permitem acesso a um objeto ou estrutura de dados conhecido pelo objeto que estamos implementando), mas n&atilde;o precisam ser escritos. Isto economiza tempo e faz os programas mais simples de ler.</p>
  </div>
  
  <div class="paragraph">
    <p>Introdu&ccedil;&atilde;o ao AppConfig</p>
    <p>Esta biblioteca &eacute; uma das mais poderosas ferramentas de configura&ccedil;&atilde;o de sistemas que eu conhe&ccedil;o.</p>
    <p>Entre as funcionalidades mais interessantes do <code>AppConfig</code>, vou destacar duas que vamos utilizar bastante. A primeira &eacute; a facilidade de verifica&ccedil;&atilde;o de consist&ecirc;ncia dos arquivos de configura&ccedil;&atilde;o processados: basta declarar quais palavras-chave s&atilde;o aceitas e quantos argumentos elas podem ter para se obter este resultado. Por exemplo, para aceitar como diretriz de configura&ccedil;&atilde;o qualquer palavra-chave com apenas um argumento associado, passamos ao construtor de nosso <code>AppConfig</code> os argumentos</p>
    <pre class="code">  my $cfg  = new AppConfig
    ( { CASE     => 1,
        PEDANTIC => 1,
        CREATE   => 1,
        GLOBAL   => { EXPAND   => 1,
                      ARGCOUNT => ARGCOUNT_ONE,
                    },
      }
    );</pre>
    <p>que essencialmente dizem "diferencie mai&uacute;sculas de min&uacute;sculas" (<code>CASE=&gt;1</code>); "tenha toler&acirc;ncia zero com discrep&acirc;ncias" (<code>PEDANTIC=&gt;1</code>); "aceite qualquer palavra como diretriz de configura&ccedil;&atilde;o" (<code>CREATE=&gt;1</code>); "aplique expans&atilde;o de vari&aacute;veis (<code>EXPAND=&gt;1</code>) a todas as diretivas"; e "aceite apenas um argumento associado a cada diretiva" (<code>ARGCOUNT=&gt;ARGCOUNT_ONE</code>).
    </p>
    <p>A segunda funcionalidade que utilizamos &eacute; a capacidade de transformar um conjunto de diretivas de configura&ccedil;&atilde;o em uma estrutura de dados arbitr&aacute;ria, como um hash de hashes, assim:</p>
    <pre class="code">  { error    =&gt; { $cfg-&gt;varlist( '^error_message_', 1 ) },
    template =&gt; { $cfg-&gt;varlist( '^template_',      1 ) },
  };</pre>
  <p>Em poucas palavras, o m&eacute;todo <code>AppConfig::varlist()</code> retorna todas as diretivas de configura&ccedil;&atilde;o que baterem com a express&atilde;o regular passada como primeiro argumento em forma de um hash, associando-as com os seus respectivos valores. Caso o segundo argumento seja um valor verdadeiro, este m&eacute;todo ainda transforma as diretivas, removendo delas a express&atilde;o regular passada como primeiro argumento (de forma que voc&e&circ; n&atilde;o precisa ficar repetindo a string "error_" sempre que deseja pegar uma mensagem de erro confirgurada pelo usu&aacute;rio).</p>
  </div>
  
  <div class="paragraph">
    <p>Introdu&ccedil;&atilde;o ao Template Toolkit</p>
    <p>Todo mundo que um dia pensou em programar Perl para a web com seriedade tentou escrever uma biblioteca capaz de gerar c&oacute;digo HTML a partir de arquivos contendo a parte "fixa" do c&oacute;digo e "substituindo" palavras-chave pr&eacute;-determinadas por express&otilde;es calculadas din&acirc;micamente em tempo de execu&ccedil;&atilde;o. Um sujeito chamado <a href="http://www.wardley.org/">Andy Wardley</a> pensou nisso e escreveu <b>a</b> biblioteca para realizar este tipo de opera&cedil;&atilde;o, o Template Toolkit. Trata-se de um interpretador para uma meta-linguagem de programa&ccedil;&atilde;o que pode ser utilizada at&eacute; mesmo para gerar HTML para nossa aplica&ccedil;&atilde;o de exemplo. Eu, particularmente, j&aacute; a utilizei at&eacute; para fazer manuten&ccedil;&atilde;o em bancos de dados <a href="http://www.oracle.com.br/">Oracle</a>.</p>
    <p>Para utilizar templates baseados em Template Toolkit em nosso sistema de exemplo, vai nos bastar umas poucas diretivas de configura&ccedil;&atilde;o e uma inst&acirc;ncia do objeto Template, o interpretador da meta-linguagem dos templates:</p>
    <pre class="code">  my $options =
    { INCLUDE_PATH => $ROOTDIR.'/'.$self->config->{template}{include_path},
      PRE_CHOMP    => $self->config->{template}{pre_chomp}   || 0,
      POST_CHOMP   => $self->config->{template}{post_chomp}  || 0,
      TRIM         => $self->config->{template}{trim}        || 0,
      COMPILE_EXT  => $self->config->{template}{compile_ext} || 'c',
      COMPILE_DIR  => $self->config->{template}{compile_dir} || '/tmp/ttc',
    };

  # Retorna um template prontinho para usar.
  return new Template( $options );</pre>
    <p>Outra vez, para tornar mais curta uma hist&oacute;ria bem longa, as diretivas dizem: "localize templates dentro do diret&oacute;rio configurado pelo usu&aacute;rio" (<code>INCLUDE_PATH</code>); "remova autom&aacute;ticamente todos os espa&ccedil;os encontrados antes de um valor aplicado sobre o template" (<code>PRE_CHOMP</code>); "remova todos os espa&ccedil;os encontrados depois de um valor aplicado sobre o template" (<code>POST_CHOMP</code>); "remova linhas em branco antes e depois de um valor aplicado sobre o template" (<code>TRIM</code>); "armazene templates pr&eacute;-compilados com a extens&atilde;o definida em (<code>COMPILE_EXT</code>)"; e "armazene arquivos de templates pr&eacute;-compilados no diret&oacute;rio (<code>COMPILE_DIR</code>)".</p>
    <p>Depois de obter uma inst&acirc;ncia do objeto Template, basta utiliz&aacute;-lo para processar os arquivos contendo c&oacute;digo HTML mesclado com meta-c&oacute;digo Template Toolkit para obter p&aacute;ginas HTML completas e prontas para enviar ao browser. Vamos falar sobre como fazer isto durante a an&aacute;lise do c&oacute;digo fonte, mais adiante.</p>
  </div>

  <div class="paragraph">
    <p>Introdu&ccedil;&atilde;o ao CGI::Application</p>
    <p>Toda aplica&ccedil;&atilde;o para a world-wide-web executa basicamente um ciclo de processamento id&ecirc;ntico para atender cada requisi&ccedil;&atilde;o enviada para ela:
    <ol>
      <li>Obt&ecirc;m as informa&ccedil;&otilde;es enviadas pelo browser (cliente)</li>
      <li>Determina qual o estado atual da aplica&ccedil;&atilde;o para este cliente em espec&iacute;fico</li>
      <li>Decide qual a pr&oacute;xima a&ccedil;&atilde;o a ser executada para esta situa&ccedil;&atilde;o</li>
      <li>Aloca os recursos necess&aacute;rios para a execu&ccedil;&atilde;o da a&ccedil;&atilde;o</li>
      <li>Executa a a&ccedil;&atilde;o planejada</li>
      <li>Libera recursos utilizados localmente para o processamento da requisi&ccedil;&atilde;o.</li>
      <li>Envia resultados</li>
    </ol>
  </p>
  <p>Claro, n&atilde;o &eacute; preciso dizer que este processo, ao se misturar com o c&oacute;digo da nossa aplica&ccedil;&atilde;o, pode potencialmente criar uma confus&atilde;o emaranhada, complicada de manter e cheia de problemas de implementa&ccedil;&atilde;o, que vai dar dor-de-cabe&ccedil;as hom&eacute;ricas nos mantenedores do c&oacute;digo e obrigar os respons&aacute;veis a contratar sujeitos como eu para consertar o problema, a pre&ccedil;os absurdos.</p>
  <p>Para evitar que este seja o destino de seus aplicativos para a web, alguns programadores criaram suas pr&oacute;prias bibliotecas de implementa&ccedil;&atilde;o de processamento de requisi&ccedil;&otilde;es, que realizavam as tarefas listadas de uma forma abstrata, permitindo a eles extender o c&oacute;digo para implementar a l&oacute;gica de neg&oacute;cio de seus programas separadamente, de uma forma mais organizada e simples de entender. Foi assim que nasceu a biblioteca CGI::Application, a mais veloz e flex&iacute;vel de todas as bibliotecas de processamento de requisi&ccedil;&otilde;es dispon&iacute;ve para a linguagem Perl. Ela ser&aacute; a base de nosso c&oacute;digo fonte, nos permitindo concentrar nas particularidades que nos interessam, sem precisar nos preocupar com coisas menores, como saber qual a pr&oacute;xima a&ccedil;&atilde;o que devemos tomar para continuar processando uma requisi&ccedil;&atilde;o enviada por um usu&aacute;rio.</p>
  </div>
    
  <div class="paragraph">
    <p>Implementa&ccedil;&atilde;o do Controlador com CGI::Application</p>
    <p>Lembram-se de que falei sobre o padr&atilde;o de projeto MVC, h&aacute; pouco? Pois bem, vamos implementar o "C" do MVC, nosso controlador de processo. Ele ser&aacute; baseado na biblioteca CGI::Application, e ser&aacute; assim: </p>
    <pre class="code">package Auth::Base;
use warnings;
use strict;
use base qw( CGI::Application Class::Accessor );
use Auth::RootDir qw( $ROOTDIR );
use AppConfig qw( :argcount );
use Template;

=head1 NAME

Auth::Base - Classe base da aplicação de autenticação de usuários.

=head1 SYNPOSIS

  use base qw( Auth::Base );

=head1 DESCRIPTION

Classe base para o framework MVC utilizado para o desenvolvimento de
uma aplicação de autenticação de usuários didática.

=head1 ATTRIBUTES

=over 4

=item config

Campo para manter o nosso objeto de configuração. Para esta aplicação,
vamos utilizar um L&lt;AppConfig&gt;, by Andy Wardley, o meu favorito.

=item template

Campo para manter o nosso objeto de processamento de templates. Isto
ajuda muito a gerar HTML na saída. Felizmente, a maior parte dos
mortais pode simplesmente utilizar este framework e esquecer que isso
existe. Vamos usar um objeto L&lt;Template&gt;, do Template Toolkit, by Andy
Wardley. Este também é um dos meus módulos favoritos.

=item stash

Um Stash é nada mais, nada menos que um conceito. Um stash é um
"contexto", um conjunto de variáveis logicamente relacionadas e
agrupadas com a finalidade de facilitar seu uso e manutenção. Nada
mais de convenções de chamadas de métodos, ou de contagem de
argumentos para saber se todos os parâmetros foram
passados. Simplesmente inclua os dados relevantes no stash, baseados
na chave correta, e permita que o método interessado os utilize quando
e como bem entender.

O stash é inicializado a cada nova requisição com as informações
provenientes dela, e, depois do processamento, é passado na íntegra
para o objeto Template, que disponibilizará as informações contidas
nele para o template que será processado para a geração de conteúdo.

=back

=cut

__PACKAGE__-&gt;mk_accessors( qw[ config template stash ] );

=head1 METHODS

=over 4

=item init_config

Inicializa e carrega o subsistema de configuração.

Utilizamos um objeto AppConfig para interpretar o nosso arquivo de
configuração, e simplemente mantemos toda a configuração de que
precisamos em memória em tempo integral. Desta forma, economizamos
recursos mais escassos que memória RAM, Pois não precisamos mais ler e
interpretar o arquivo de configuração.

=cut

sub init_config{
  my $self = shift;
  my $cfg  = new AppConfig
    ( { CASE     =&gt; 1,
        PEDANTIC =&gt; 1,
        CREATE   =&gt; 1,
        GLOBAL   =&gt; { EXPAND   =&gt; 1,
                      ARGCOUNT =&gt; ARGCOUNT_ONE,
                    },
      }
    );
  $cfg-&gt;file( $ROOTDIR.'/etc/auth-app.cfg' );

  return { error    =&gt; { $cfg-&gt;varlist( '^error_message_', 1 ) },
           template =&gt; { $cfg-&gt;varlist( '^template_',      1 ) },
         };
}

=item init_template

Inicializa e instancia um objeto Template, interpretador de scripts de
template do Template Toolkit. Um único objeto Template dá conta de
interpretar e fazer funcionar todas as páginas dinâmicas baseadas em
templates da nossa aplicação.

=cut

sub init_template{
  my $self = shift;

  # inicializa o template engine, baseado na configuração incorporada.
  my $options =
    { INCLUDE_PATH =&gt; $ROOTDIR.'/'.$self-&gt;config-&gt;{template}{include_path},
      PRE_CHOMP    =&gt; $self-&gt;config-&gt;{template}{pre_chomp}   || 0,
      POST_CHOMP   =&gt; $self-&gt;config-&gt;{template}{post_chomp}  || 0,
      TRIM         =&gt; $self-&gt;config-&gt;{template}{trim}        || 0,
      COMPILE_EXT  =&gt; $self-&gt;config-&gt;{template}{compile_ext} || 'c',
      COMPILE_DIR  =&gt; $self-&gt;config-&gt;{template}{compile_dir} || '/tmp/ttc',
    };

  # Retorna um template prontinho para usar.
  return new Template( $options );
}

=item cgiapp_init

Sobrecarga de método do CGI::Application para inicialização da nossa
aplicação. Este método é chamado automaticamente pelo CGI::Application
quando da inicialização do objeto de aplicação.

=cut

sub cgiapp_init{
  my $self = shift;
  $self-&gt;config( $self-&gt;init_config );
  $self-&gt;template( $self-&gt;init_template );
}

=item setup

Método sobrecarregado do objeto CGI::Application para permitir a
configuração do nosso objeto de aplicação.

Este método é chamado sempre que um novo objeto de aplicação é criado,
logo depois de cgiapp_init(), mas antes de cgiapp_prerun() / run() /
cgiapp_postrun().

É aqui que estabelecemos valores e comportamento default para nossa
aplicação.

=cut

sub setup{
  my $self = shift;
  $self-&gt;mode_param( 'mode' );
  $self-&gt;start_mode( 'action' );
  $self-&gt;run_modes( action =&gt; 'action' );
}

=item init_stash

Stash é o conceito de que tudo o que está relacionado com os
diferentes métodos da aplicação deve permanecer junto. Por isso,
preparamos uma referência para um hash, que inicializamos com os
diversos parâmetros provenientes da requisição e o disponibilizamos
para o método de geração de conteúdo. Assim, o método de geração de
conteúdo simplesmente não precisa mais se preocupar com a proveniência
ou o destino dos parâmetros iniciais ou do conteúdo gerado. Basta que
se posicione estas coisas em seus devidos lugares no "stash" e passar
o controle para o próximo método da nossa cadeia de responsabilidades.

=cut

sub init_stash{
  my $self = shift;

  # inicializa uma referência de hash caso não tenhamos uma...
  my $stash = $self-&gt;stash || {};

  # Recupera uma referência para um tied hash contendo os parâmetros
  # passados para o script na requisição.
  my $vars  = $self-&gt;query-&gt;Vars;

  # copia organizadamente estes parâmetros, tomando o cuidado de
  # expandir novamente as listas de valores que alguns deles podem
  # conter.
  map { $stash-&gt;{$_} = $vars-&gt;{$_} =~ /\0/?
          [ split qr/\0/, $vars-&gt;{$_} ] : $vars-&gt;{$_};
      } keys %$vars;

  # inicializa nosso stash em sua posição definitiva.
  $self-&gt;stash( $stash );
}

=item cgiapp_prerun

Chamado automaticamente pelo CGI::Application a cada nova requisição,
antes que o método associado ao modo de operação determinado por
CGI::Application::run() tenha chance de rodar.

Vamos utilizar este "gancho" para inicializar o Stash de nossa
aplicação corretamente, de modo a permitir que os métodos geradores de
conteúdo ignorem a proveniência dos parâmetros utilizados em cada
requisição. Tudo o que precisam estará no Stash.

=cut

sub cgiapp_prerun{
  my $self = shift;

  # Prepara o stash que vai ser utilizado nesta requisição.
  $self-&gt;init_stash;

  return $self;
}

=item cgiapp_postrun

Chamado automaticamente pelo CGI::Application a cada nova requisição,
logo depois que o método de geração de conteúdo terminar de rodar.

Vamos utilizar este método para gerar efetivamente o conteúdo, já que
os métodos geradores de conteúdo apenas realizam seu processamento
interno e colocam todas as informações necessárias para a geração de
conteúdo nas variáveis definidas no Stash, juntamente com uma variável
especial chamada "template". Esta chave indica qual o template que
devemos passar ao Template Toolkit para obter o conteúdo que
desejamos.

Depois de rodar, este método substitui o que quer que tenha sido
gerado como "conteúdo" pelo método associado com o run-mode atual e
permite ao CGI::Application enviar corretamente o conteúdo gerado ao
browser.

=cut

sub cgiapp_postrun{
  my $self = shift;
  my $output;
  my $out = shift;

  if( UNIVERSAL::isa( $self-&gt;template, 'Template' ) ){
    $self-&gt;template-&gt;process( $self-&gt;stash-&gt;{template},
                              $self-&gt;stash,
                              \$output
                            )
      or $self-&gt;template-&gt;process( $self-&gt;config-&gt;{template}{error},
                                   { %{$self-&gt;stash},
                                     error =&gt; $self-&gt;template-&gt;error()
                                   },
                                   \$output
                                 );
  }else{
    $output = $self-&gt;config-&gt;{error}{template_not_defined};
    $self-&gt;header_type( 'header' );
    $self-&gt;header_add( type =&gt; 'text/plain' );
  }

  $$out = $output;
}

=item action

Finalmente, mas não menos importante, implementamos a "ação default"
de um módulo (ou seja, um erro, já que este módulo é considerado
"abstrato" e não deveria ser instanciado ou rodado como um módulo
qualquer...).

=cut

sub action{
  my $self = shift;
  $self-&gt;stash-&gt;{template} = $self-&gt;config-&gt;{template}{error};
  $self-&gt;stash-&gt;{error_message}
    = $self-&gt;config-&gt;{error}{action_not_defined_for_this_object};
}

=back

=head1 AUTHOR

Luis Campos de Carvalho - Engenharia de Software Ltda.

=head1 REVISION

$Revision: $

=head1 COPYRIGHT

Copyleft 2005 Engenharia de Software Ltda.

Doado aos São Paulo Perl Mongers.

This module is free software; you can redistribute it and/or modify it
under the term of the GNU Public License.

=head1 SEE ALSO

L&lt;CGI::Application&gt;

1;
</pre>
  </div>

  <div class="paragraph">
    <p>Como utilizar o Controlador implementado</p>
    <p>Como extender o contorlador implementado aqui para implementar a&ccedil;&otilde;es e novos controladores conforme a necessidade.</p>
  </div>
  
  <div class="paragraph">
    <p>Como implementar a p&aacute;gina din&acirc;mica (CGI)</p>
    <p>Como implementar o script CGI que ser&aacute; chamado para disparar o processamento.</p>
  </div>
  
  <div class="paragraph">
    <p>Construindo mais p&aacute;ginas com o mesmo controlador</p>
    <p>Como continuar escrevendo a aplica&ccedil;&atilde;o, repetindo parte do processo descrito neste artigo.</p>
  </div>
  
  <div class="paragraph">
    <p>Interligando aplicativos</p>
    <p>Como interligar aplicativos atrav&eacute;s de cookies, par&acirc;metros de estado e redirecionamentos.</p>
  </div>
  
  <div class="paragraph">
    <p>Uma palavra de cautela</p>
    <p>Lembre-os do planejamento, do cuidado com a implementa&ccedil;&atilde;o e da necessidade de testes e documenta&ccedil;&atilde;o!</p>
  </div>
  
  <div class="paragraph">
    <p>Conclus&atilde;o</p>
  </div>
  
  <div class="paragraph">
    <p>Cr&eacute;ditos</p>
    <p>Este artigo foi escrito por Luis Campos de Carvalho, tamb&eacute;m conhecido por <i>Monsieur Champs</i>, L&iacute;der dos <a href="http://sao-paulo.pm.org/">S&atilde;o Paulo Perl Mongers</a>, empres&aacute;rio e fan&aacute;tico por Perl e Bancos de Dados Oracle.</p>
    <p>Contato: (11)9297-4646 ou mailto:<a href="mailto:monsieur_champs@yahoo.com.br">monsieur_champs@yahoo.com.br</a></p>
  </div>
  
  <div class="paragraph">
    <p>Licensa de Uso e Distribui&ccedil;&atilde;o</p>
    <pre class="code">Este artigo &eacute; um software livre; voc&ecirc; pode redistribu&iacute;-lo e/ou 
modific&aacute;-lo dentro dos termos da Licen&ccedil;a P&uacute;blica Geral GNU como 
publicada pela Funda&ccedil;&atilde;o do Software Livre (FSF); na versão 2 da 
Licen&ccedil;a, ou (na sua opni&atilde;o) qualquer vers&atilde;o.

Este artigo &eacute; distribu&iacute;do na esperan&ccedil;a que possa ser &uacute;til, 
mas SEM NENHUMA GARANTIA; sem uma garantia implicita de ADEQUA&Ccedil;&Atilde;O
a qualquer MERCADO ou APLICA&Ccedil;&Atilde;O EM PARTICULAR. Veja a
Licen&ccedil;a P&uacute;blica Geral GNU para maiores detalhes.

Voc&ecirc; deve ter recebido uma c&oacute;pia da Licen&ccedil;a P&uacute;blica Geral GNU
junto com este programa. Se n&atilde;o, escreva para a Funda&ccedil;&atilde;o do Software
Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</pre>
  </div>
  
  </body>
</html>