Treinamento Online
Segunda-feira, 29 de junho de 2009 às 09h30

Adicione poder ao seu PHP com aplicações multi-tiered

Como aplicações PHP se tornam cada vez mais e mais complexas, isso pode ser fácil para acabar com um emaranhado de códigos que faz a manutenção ser quase impossível. Aplicar o conceito de diferenciação de aplicativos pode ajudar a aliviar algumas das dificuldades em manter aplicações complexas.

O que queremos dizer por Tiered Applications?

Tiered Programming é a prática de manter diferentes componentes, ideias ou línguas separadas umas das outras. No desenvolvimento front-end, diferenciar marcação seria usar stylesheets e JavaScript externos.

Ao ligar a um arquivo CSS em vez de encaixar estilos em seu HTML markup, torna-se mais fácil para alterar a formatação de seus sites porque agora toda informação estilizada é convenientemente armazenado em um lugar, separado da marcação do documento. E múltiplas páginas HTML podem puxar exatamente o mesmo arquivo CSS, todo o seu site pode ser atualizado simplesmente ao mudar uma linha de CSS.

Em desenvolvimento back-end, as mesmas regras se aplicam, mas estamos lidando com diferentes componentes. Em termos gerais, estamos olhando para três níveis: a Database (armazenando e recuperando de dados), Business (processando e manipulando os dados), e Presentation (como os dados são apresentados).

Por que eu devo ter cuidado?

Pode não ser imediatamente óbvio, mas separando as suas aplicações em uma estrutura em camadas terá um enorme impacto sobre a habilidade do código ao ser mudado no futuro. Por exemplo, se você tem um sistema de criação de blogs, e torna-se necessário criar um feed RSS para o blog, as aplicações diferenciadas apropriadas lhe autorizariam a simplesmente criar um template RSS, e em seguida conectar ao banco de dados e funções empresariais que você escreveu.

Por outro lado, se o seu cliente de repente decidiu que PostgreSQL era uma escolha melhor para sua organização do que o MySQL, você teria que reescrever as funções do seu banco de dados, todos sem tocar o negócio ou apresentação lógica da aplicação.

Em termos de reutilização, você poderia ter várias funcionalidades do banco de dados (suportando MySQL, PostgreSQL e Oracle, por exemplo), que poderiam ser facilmente usadas em novas implantações de sua aplicação usando apenas algumas linhas de código em um lugar, em vez de editar várias linhas do seu código através de várias funções.

O caminho errado

Para começar, vamos ter uma tarefa bastante simples - puxar o título e o corpo do texto de uma entrada de um banco de dados, criar uma versão abreviada da entrada, e colocar os dados em HTML markup - e vá completamente no caminho errado. No código a seguir, vamos escrever uma função para realizar todas as nossas tarefas:

function displayEntry()
{
$entryDisp = NULL;

// Get the information from the database
$sql = "SELECT title, entry FROM entries WHERE page='blog'";
$r = mysql_query($sql) or die(mysql_error());
while($entry = mysql_fetch_assoc($r)) {
$title = $entry['title'];
$text = $entry['entry'];

// Create the text preview
$textArray = explode(' ',$text);
$preview = NULL;
for($i=0; $i<24; $i++) {
$preview .= $textArray[$i] . ' ';
}
$preview .= $textArray[24] . '...';

// Format the entries
$entryDisp .= <<<ENTRY_DISPLAY

<h2> $title </h2>
<p>
$preview
</p>
ENTRY_DISPLAY;
}

return $entryDisp;
}

O código do HTML markup sai de acordo com estas linhas:

<h2> Entry One </h2>
<p>
This is the shortened description of entry number one. It
displays the first 25 words of the entry and then trails
off with an ellipsis...
</p>
<h2> Entry Two </h2>
<p>
This is the shortened description of entry number two. It
displays the first 25 words of the entry and then trails
off with an ellipsis...
</p>

Embora isso possa parecer lógico, é realmente muito indesejável. Vamos passar em revista o que torna este um código menos do que uma ótima abordagem.

O problema com esta abordagem

Poor Legibility  - Este código é diluído. O seu objetivo, embora documentado nos comentários (ou algo do tipo), é difícil de discernir. Se você escreveu isso, quando voltar para ele em seis meses, não será claro o que estava acontecendo, o que significa alguns segundos/minutos desperdiçados tentando interpretar o seu próprio código.

Too Narrow em Foco - Esta função é falha pela sua especificidade: a query do banco de dados só funciona para um tipo de entrada; um preview na criação do código é muito bem codificado para a função, a formatação é específica para o tipo de entrada que está sendo exibido. A fim de criar uma implementação ligeiramente diferente desta funcionalidade, seríamos forçados a criar uma segunda função que pareceria quase exatamente o mesmo, ainda que o necessário fosse apenas mudar o número de palavras na visualização do texto.

Falta de Escalabilidade - Isso é muito relacionado com a idéia de ser demasiado em destaque. Se queremos adicionar mais funcionalidades (como um link ou uma imagem), a nossa função será maior e mais difícil de gerenciar. E se quisermos acrescentar condições que afetam o modo como uma entrada é exibida? É fácil ver como programar assim deixa fácil para o código se tornar rapidamente expansivo e ingerenciável.

O grande problema: Database, Business e Display Logic


Esta é a questão que está causando varredura de todos os problemas acima mencionados.

"Ao combinar os três tipos de nossa lógica, acabamos com um limitado, confuso, difícil de gerenciar, quase impossível para reutilizar emaranhado de código."

Imagine uma aplicação onde cada tipo de visualização (RSS feed, entrada preview, total entrada no visor, etc.) foi construído com uma função similar às citadas acima, com acesso a base de dados, lógica empresarial, e apresentação lógica tudo escrito em conjunto. Agora imagine que há nove páginas do site, e todas têm a sua própria entrada exibir e visualizar funções.

Mesmo se considerarmos que a aplicação é muito simples e que existam apenas duas funções por página do site, ainda estamos olhando para quase vinte funções que terão de ser atualizadas, se as alterações se tornarem necessárias.

Melhorando o código

Para melhorar o código acima, nós iremos espalhar nossos diferentes tipos de lógica através de várias funções. Se feito corretamente, devemos acabar com um conjunto de funções reutilizáveis, fáceis de entender e que executam uma variedade de tarefas.

Para começar, vamos planejar as funcionalidades necessárias para ter uma melhor ideia de como ele deveria ser construído:

  1. Obtenha a entrada e uma coluna de títulos para uma determinada página da tabela "entries" no banco de dados
  2. Encurte o corpo da entrada para visualização de 25 palavras e anexe uma elipse
  3. Insira os dados em tags HTML para exibição no navegador do usuário

Como você pode ver, o nosso plano identifica claramente um banco de dados, negócios, apresentação e grau. Podemos agora escrever funções para cumprir cada um desses passos com relativa facilidade.

Passo 1 - A camada do banco de dados

Para obter informação do banco de dados, nós iremos escrever uma função muito simples. Para incentivar boas práticas de codificação, eu irei usar a extensão mysqli, mas não vou me focar em como isso funciona. Se você ainda não está usando, eu te incentivo a explorar o mysqli ou uma extensão similar (i.e. PDO) para garantir suas consultas do MySQL contra ataques de injeção.

function getDataFromDB($page)
{
/*
* Connect to a MySQL server
*/
$mysqli = new mysqli('localhost', 'user', 'password', 'world');
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit;
}

/*
* Create a prepared statement for pulling all entries from a page
*/
if ($stmt = $mysqli->prepare('SELECT title, entry FROM entries WHERE page=?')) {
/*
* Create a multi-dimensional array to store
* the information from each entry
*/
$entries = array();

/*
* Bind the passed parameter to the query, retrieve the data, and place
* it into the array $entries for later use
*/
$stmt->bind_param("s", $page);
$stmt->execute();
$stmt->bind_result($title, $entry);
while($stmt->fetch()) {
$entries[] = array(
'title' => $title,
'entry' => $entry
);
}

/*
* Destroy the result set and free the memory used for it
*/
$stmt->close();
}

/*
* Close the connection
*/
$mysqli->close();

/*
* Return the array
*/
return $entries;
}

Se você quebrar o que esta função está fazendo, estamos literalmente solicitando apenas duas colunas (título e entrada) de nossa tabela (entries) e, em seguida, armazenando cada entrada em uma matriz associativa multi-dimensional, que é o valor de retorno da função. Nós passamos um parâmetro, $ page, para que possamos determinar qual página iremos obter as informações. Ao fazê-lo, temos agora criada uma função que irá trabalhar para todas as páginas do nosso site (desde que todas elas tenham as fields "title" e "entry").

Repare que a nossa função não faz nada para lidar com os dados, ele simplesmente age como um correio, pegar as informações que solicitamos e passando-o para o que vem a seguir. Isto é importante, porque se fez nada de mais, gostaríamos de estar na esfera da lógica empresarial.

Por que isso é importante para separar a lógica empresarial da lógica do banco de dados?

A resposta curta é que isso autoriza a abstração do banco de dados, o que significa essencialmente que o dado poderia ser migrado do MySQL dentro de um outro formato de base de dados, tal como PostgreSQL ou Oracle, todos, sem alterar as funções dos dados de movimentação (business tier), desde que a produção continue a ser simplesmente uma ordem multi-dimensional associativa contendo entradas com uma coluna de título e de entrada, não importa que tipo de banco de dados que estamos utilizando.

Passo 2 - A camada Business

Com os dados carregados em nossa matriz, podemos iniciar processando a informação para servir para nossos propósitos. Neste exemplo, estamos tentando criar uma entrada de visualização. No primeiro exemplo, a duração da visualização foi dificilmente codificada dentro da função, o que decidimos que é de má prática. Nesta função, vamos passar dois parâmetros para o nosso código: o texto a processar, e o número de palavras que deseja exibir como nossa pré visualização.

Dê uma olhada na função:

function createTextPreview($text, $length=25)
{
/*
* Break the text apart at the spaces and create the preview variable
*/
$words = explode(' ', $text);
$preview = NULL;

/*
* Run a loop to add words to the preview variable
*/
if($length < count($words)) {
for($i=0; $i<$length; $i++) {
$preview .= $words[$i] . ' '; // Add the space back in between words
}
$preview .= $words[$length] . '...'; // Ellipsis to indicate preview
} else {
/*
* If the entry isn't as long as the specified preview length, simply
* return the whole entry.
*/
$preview = $text;
}

/*
* Return the preview
*/

return $preview;

}

Na função acima, simplesmente checamos que o número de palavras na entrada fornecida é superior ao número de palavras que queremos exibir em nossa visualização. Em seguida, adicione palavras à recém-criada variável $preview uma de cada vez até atingir o comprimento máximo, ao ponto que colocar uma elipse e retornar $preview.

Assim como na camada de nossa base de dados, estamos mantendo o código dentro dos limites da camada Business. Tudo que nós estamos fazendo é criando um texto visualização; não há interação com o banco de dados, nem elementos presenciais, como HTML markup.

Passo 3 - A camada de apresentação

Finalmente, temos de mostrar os dados que obtivemos e processamos. Para nosso propósito, o que vamos exibir é extremamente simples com HTML markup:

<?php
$entries = getDataFromDB(); // Load entries into an array
foreach($entries as $entry) {
/*
* Place the title and shortened entry text into two appropriately
* named variables to further simplify formatting. Also note that
* we're using the optional $length parameter to create a 30-word
* text preview with createTextPreview()
*/
$title = $entry['title'];
$preview = createTextPreview($entry['entry'], 30);
?>

<h2> <?php echo $title; ?> </h2>
<p> <?php echo $preview; ?> </p>

<?php
} // End foreach loop
?>

A ideia por trás do código é bem simples: primeiro, carrega as entradas usando a função da base de dados, então faz um loops nos dados através das entradas, encurtando a entrada do texto utilizando a nossa função preview e, em seguida, colocando o título e a entrada preview na marcação da apresentação.

Agora, para mudar o layout das pré visualizações da entry, somente duas linhas de HTML são necessárias para serem ajustadas. Este é um grito muito menos confuso do que a função original que tratava dos três níveis.

Olhando através de diferentes tipos de programação

Gostaria de salientar que o exemplo acima é muito básico, e serve somente para demonstrar o conceito de Tiered Programmin. A ideia é que, mantendo os diferentes tipos de lógica de programação separados, você pode aumentar enormemente a legibilidade de manutenção do seu código.

Nota: Há um grande artigo sobre TheDailyWTF.com discutindo o uso e abuso de softwares diferenciados de design, e maravilhoso comentário sobre o artigo que apresenta diferentes opiniões. Aplicações Multi-tiered são extremamente úteis, mas também fácil de se compreender mal e o excesso de complicar, por isso lembre-se de planejar cuidadosamente o seu software antes de construir para evitar que causem mais problemas do que você está resolvendo.

*

Publicado originalmente em: http://net.tutsplus.com/tutorials/php/add-power-to-your-php-with-multi-tiered-applications/

Nenhum comentário até agora

Cancelar resposta

Qual a sua opinião?

Faça login abaixo ou cadastre-se rapidamente.


2001 - iMasters FFPA Informática Ltda - Todos os direitos reservados.