Livro Padroes de Projeo
Livro Padroes de Projeo
Livro Padroes de Projeo
Padrões de
Projeto em PHP
William Sanders
Novatec
Authorized Portuguese translation of the English edition of titled Learning PHP Design Patterns ISBN 9781449344917
© 2013 William B. Sanders. This translation is published and sold by permission of O'Reilly Media, Inc., the owner of
all rights to publish and sell the same.
Tradução em português autorizada da edição em inglês da obra Learning PHP Design Patterns ISBN 9781449344917
© 2013 William B. Sanders. Esta tradução é publicada e vendida com a permissão da O'Reilly Media, Inc., detentora de
todos os direitos para publicação e venda desta obra.
© Novatec Editora Ltda. 2013.
Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998. É proibida a reprodução desta obra, mesmo
parcial, por qualquer processo, sem prévia autorização, por escrito, do autor e da Editora.
Editor: Rubens Prates
Tradução: Lúcia A. Kinoshita
Revisão gramatical: Naomi Yokoyama Edelbuttel
Editoração eletrônica: Carolina Kuwabata
ISBN: 978-85-7522-343-7
Histórico de impressões:
Maio/2013 Primeira edição
Novatec Editora Ltda.
Rua Luís Antônio dos Santos 110
02460-000 – São Paulo, SP – Brasil
Tel.: +55 11 2959-6529
Fax: +55 11 2950-8869
E-mail: [email protected]
Site: www.novatec.com.br
Twitter: twitter.com/novateceditora
Facebook: facebook.com/novatec
LinkedIn: linkedin.com/in/novatec
VC20130517
capítulo 1
PHP e programação orientada a objetos
Não reze por tarefas iguais aos seus poderes. Reze por poderes iguais
às suas tarefas.
– Phillips Brooks
23
24 Aprendendo padrões de projeto em PHP
Para obter o necessário deste livro, será preciso começar por compreensão e experi-
ência com PHP. Outros livros desta série, Learning PHP 5, de David Sklar, e Learning
PHP, MySQL, and JavaScript, 2nd Edition, de Robin Nixon (O’Reilly), constituem
bons pontos de partida, caso você não tenha nenhuma experiência com PHP. É
claro que você pode ter aprendido PHP a partir de vários outros livros, cursos ou
tutoriais online. O que importa é que você saiba programar em PHP. Além do
mais, lidaremos com PHP 5 e não com versões anteriores, como a última versão
de PHP 4 (PHP 4.4.9). Isso porque praticamente tudo o que precisamos para pro-
gramação orientada a objetos (POO) não havia sido implementado até o PHP 5.
Modularização
O processo de decomposição de um problema em subproblemas menores corres-
ponde ao processo de modularização. Assim como a complexidade de levar você de
sua casa até Timbuktu pode ser modularizada em um conjunto de passos do tipo
sim/não, qualquer outro problema complexo também pode ser modularizado. A
figura 1.1 ilustra esse processo.
Ao olhar para a modularização, você poderá pensar que ela não parece ser tão
difícil. Você está absolutamente certo. Quanto mais complexo o problema, mais
faz sentido modularizá-lo. Desse modo, o raciocínio inicial na POO, longe de ser
complexo, simplifica o que é complexo. Até mesmo o problema de programação
mais desanimador pode ser resolvido usando essa estratégia de dividir e conquistar.
26 Aprendendo padrões de projeto em PHP
Figura 1.1 – Até mesmo o problema mais complexo pode ser dividido em módulos.
Classes e objetos
Uma vez que o problema for modularizado, o que você fará com os módulos?
Conforme visto, dividir um problema complexo pode transformá-lo em vários
subproblemas simples, mas é necessária uma maneira de organizar os módulos e
trabalhar com eles, uns em relação aos outros, para lidar com o problema maior
sendo resolvido. Uma maneira de ver um módulo é encará-lo como uma coleção
de funções relacionadas. Em programação, esses módulos são chamados de classes.
Uma classe é composta de partes chamadas de propriedades e de métodos. As
propriedades são diferentes tipos de objetos de dados, como números, strings, nulos
e booleanos. Em geral, os dados são armazenados na forma de tipos de dados
abstratos, conhecidos como variáveis, constantes e arrays. Por outro lado, métodos
são funções que operam sobre os dados.
Isso não significa que uma classe não possa ter várias responsabilidades, mas
não se esqueça de que dividimos um problema complexo em módulos simples
para que dessa forma tivéssemos vários problemas fáceis de serem solucionados.
Ao limitar uma classe a uma única responsabilidade, não só nos lembramos do
motivo pelo qual modularizamos o problema, mas teremos também uma maneira
mais fácil de organizar os módulos. Vamos dar uma olhada em uma classe com
uma única responsabilidade. Suponha que você esteja criando um site para um
cliente, e como o site será visualizado em diferentes dispositivos, que variam de
desktops a tablets ou smartphones, você quer ter alguma maneira de determinar
o tipo de dispositivo e qual navegador é usado para visualizar sua página na web.
Em PHP é fácil escrever uma classe que disponibilize essas informações utilizando
o array existente $_SERVER e o elemento relacionado, HTTP_USER_AGENT. A classe TellAll
na listagem a seguir mostra uma classe com uma única responsabilidade – prover
informações sobre o agente de usuário que está visualizando a página PHP:
<?php
//Salvo como TellAll.php
class TellAll {
private $userAgent;
$tellAll=new TellAll();
?>
Carregar essa classe por meio de um navegador Safari em um iMac fará a seguinte
informação ser apresentada:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/ 534.57.2 (KHTML, like Gecko)
Version/5.1.7 Safari/534.57.2
Figura 1.2 – A classe Client instancia a classe MobileSniffer e pode usar suas propriedades e seus
métodos.
Se uma classe Client tivesse sido instanciada automaticamente, o Client teria menos
opções para usar as informações de MobileSniffer. Dê uma olhada na listagem a
seguir para ver como criar a classe:
<?php
//Agente de usuário como propriedade do objeto
class MobileSniffer {
private $userAgent;
private $device;
private $browser;
private $deviceLength;
private $browserLength;
$this->device=array('iphone','ipad','android','silk','blackberry', 'touch');
$this->browser= array('firefox','chrome','opera','msie','safari',
'blackberry','trident');
$this->deviceLength=count($this->device);
$this->browserLength=count($this->browser);
}
public function findDevice() {
for($uaSniff=0;$uaSniff < $this->deviceLength;$uaSniff ++) {
if(strstr($this->userAgent,$this->device[$uaSniff])) {
return $this->device[$uaSniff];
}
}
}
public function findBrowser() {
for($uaSniff=0;$uaSniff < $this->browserLength;$uaSniff ++) {
if(strstr($this->userAgent,$this->browser[$uaSniff])) {
30 Aprendendo padrões de projeto em PHP
return $this->browser[$uaSniff];
}
}
}
}
?>
Para algumas pessoas, essas linhas adicionais de código são irritantes, mas eu as
incluo na classe Client como lembrete da importância de se informar erros no
desenvolvimento de aplicações, quando o feedback é essencial. O aprendizado de
POO e de padrões de projeto baseia-se fortemente em tais feedbacks.
Para usar MobileSniffer, o Client instancia essa classe e usa seus métodos, conforme
mostrado na listagem a seguir:
<?php
ini_set("display_errors","1");
ERROR_REPORTING(E_ALL);
include_once('MobileSniffer.php');
class Client {
private $mobSniff;
public function __construct() {
$this->mobSniff=new MobileSniffer();
echo "Device = " . $this->mobSniff->findDevice() . "<br/>";
echo "Browser = " . $this->mobSniff->findBrowser() . "<br/>";
}
}
$trigger=new Client();
?>
A essa altura, você poderá estar pensando: “Eu poderia escrever um algoritmo
melhor para resolver o problema dos dispositivos e navegadores”. Provavelmente
poderia, e de fato é provável que você terá de fazê-lo porque, à medida que novos
dispositivos e navegadores são introduzidos, eles deverão ser incorporados em
um programa que necessite usar informações sobre dispositivos/navegadores.
Contudo, se você preservar a estrutura de dois métodos, findDevice() e findBrowser(),
será possível fazer todas as alterações e melhorias que quiser e o programa maior
não terá falhas. Você deve pensar em um programa muito maior e muito mais
complexo, e pensar em como fazer alterações. Se já teve de revisar um programa
maior, você sabe que uma alteração pode se insinuar por todo o programa e
provocar erros. E então sua depuração se tornará um pesadelo. Uma das princi-
pais funções da POO e dos padrões de projeto está na capacidade de alterar um
módulo sem provocar erros em todo o programa.
E a velocidade?
Praticamente todo programador quer que um programa execute com uma veloci-
dade ótima e, para isso, procuramos os melhores algoritmos. Porém, por enquanto,
devemos focar nossa atenção em outro tipo de velocidade – na quantidade de
tempo necessária para criação e atualização de um programa. Se um programa
executa uma operação em ciclos, a qual acontece 100 milhões de vezes, ajustes
pequenos em velocidade nessa operação são importantes; no entanto, tentar
ganhar alguns microssegundos em uma operação que é executada somente uma
vez pode representar um custo alto em relação ao uso de tempo. Da mesma ma-
neira, ter de revisar todo um programa porque algumas linhas de código foram
adicionadas, representa, igualmente, um alto custo em relação ao uso de tempo.
para ir de um lado para outro do país, voar em um jato funciona muito melhor. A
POO e os padrões de projeto são melhorias em relação à programação sequencial
e procedural, da mesma maneira que voar é uma melhoria em relação a caminhar.
Programação sequencial
A maioria dos programadores começa a fazer programação escrevendo uma ins-
trução após a outra para criar uma série de linhas que executarão um programa.
Por exemplo, o código a seguir é um programa PHP sequencial perfeitamente
funcional e adequado:
<?php
$firstNumber=20;
$secondNumber=40;
$total= $firstNumber + $secondNumber;
echo $total;
?>
A adição de dois números é um problema simples para o PHP e, desde que você
lide com problemas simples, poderá usar soluções simples.
Programação procedural
À medida que os programadores começaram a escrever programas cada vez mais
longos, com tarefas mais complexas, as sequências começaram a ficar confusas,
o que resultava em um código chamado de “macarrônico”. Uma instrução GOTO
permitia aos programadores sequenciais fazer saltos em um programa para com-
pletar um procedimento, o que facilitava a criação de um código emaranhado.
Com a programação procedural, surgiram as funções. Uma função é um pequeno
objeto em que uma operação pode ser chamada para executar uma sequência
por meio de uma única instrução. Por exemplo, o código a seguir é uma versão
procedural do programa sequencial apresentado na listagem anterior:
<?php
function addEmUp($first,$second) {
$total=$first + $second;
Capítulo 1 ■ PHP e programação orientada a objetos 35
echo $total;
}
addEmUp(20,40);
?>
Em vez de olhar para essas afirmações como motivos para não aprender POO e
padrões de projeto, elas se apresentam como razões pelas quais a POO e os padrões
de projeto são tão valiosos. O conhecimento agrega valor a qualquer conjunto de
habilidades. Quanto mais difícil for obter o conhecimento, mais ele será valorizado.
Não espere entender POO e padrões de projeto fácil e rapidamente. Em vez disso,
incorpore-os pouco a pouco em sua programação PHP. Em algum momento você
perceberá o valor. Ao longo do tempo, você desenvolverá mais habilidades e terá
mais compreensão, e se deparará com um projeto no qual poderá reutilizar a maior
parte das estruturas de programa de projetos anteriores. Em um projeto recente
decidi usar um padrão de projeto Strategy. O padrão incluía uma tabela com 105
campos e o cliente queria um determinado conjunto de funcionalidades. Ao usar
um padrão Strategy, cada uma das estratégias era uma classe com um algoritmo
para lidar com um problema razoavelmente comum em PHP – filtrar, atualizar
e apagar dados em um banco de dados MySQL. Levou um tempo para criá-lo,
mas uma vez configurado, alterá-lo era fácil (clientes sempre querem alterações!).
Algum tempo depois, fui solicitado a desenvolver um tipo semelhante de projeto
usando frontend e backend em PHP, com um banco de dados MySQL. Em vez
de começar do zero, simplesmente peguei o padrão Strategy, alterei os algoritmos
e ele estava funcionando de imediato. Recebi o mesmo pagamento, mas tendo
trabalhado de forma inteligente, meu cliente recebeu um software muito melhor
do que receberia, caso eu tivesse trabalhado por mais tempo, de modo menos
inteligente.
Em algum momento, temos que acabar com nossos velhos hábitos e melhorar
nossas habilidades. Nesse momento, muitos programadores estão melhorando
suas habilidades para acomodar dispositivos móveis. Caso não o façam, eles per-
derão muitas oportunidades – em algum momento, suas habilidades poderão
se tornar obsoletas. Ao longo do tempo, sabemos que devemos melhorar nossas
habilidades para incorporar os benefícios da última versão de PHP, as novas
tecnologias ou a direção tomada pelo mercado.
POO e padrões de projeto contêm conceitos que transcendem todas essas mudan-
ças, nos tornam programadores melhores e permitem que nossos clientes recebam
softwares melhores. Tudo começa com um passo inicial. Ao investir tempo agora,
você não ficará brigando com prazos para terminar um projeto no futuro. Além
disso, você sairá do processo como um programador melhor e somente esse as-
pecto é motivo suficiente para aprender POO e padrões de projeto.
Acima de tudo, aprender POO e padrões de projeto representa o prazer de fazer
algo bem-feito.