2008-08-23 03:55:02
tags: 

O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 27)

Para ver os artigos anteriores desta série, clique aqui.

Olá meus caros amigos. Depois das decepções do salto com vara, do pentatlo moderno, do hóquei na grama, do salto triplo, do badminton, do baseball, do basquete, do bmx, do badminton, do taekwondo, do karatê, do salto em altura, do revezamento 4x100m, dos 800m, do tiro, do nado sincronizado, da ginástica rítmica e artística, da luta greco-romana, luta livre, esgrima, do arco e flecha, do boxe, da canoagem, do cliclismo, do softball, do levantamento de peso, do tênis, do triatlon, do tênis de mesa, do remo, do handball, do trampolim e finalmente, do futebol, voltamos aqui pra falar do que o brasileiro realmente entende: OOP, o famoso esporte da programação orientada a objetos.

Nas últimas semanas estivemos vendo alguns recursos que já vem na caixa do PHP quando você compra: as bibliotecas SPL são um bom exemplo. Mas o PHP é igual às olimpíadas: quanto mais popular é a necessidade, mais chance de entrar na instalação padrão do PHP. E uma das funcionalidades mais importantes em qualquer sistema é a conectividade com sistemas de banco de dados.

Pra isso, os nossos amigos discípulos do Boerger desenvolveram uma camada de abstração chamada PDO. Pra gente entender o que é PDO, portanto, precisamos entender primeiro o que é uma camada de abstração, correto?

Muito bem, caros leitores, nesse momento preciso contar uma verdade dura para vocês: o mundo lá fora é feio e sujo. Sim, acreditem! Não existem padrões, cada programador reinventa a roda a cada dia para provar que é o melhor! Bancos de dados, por exemplo: eu que sou um desconhecedor completo do assunto conheço pelo menos 10 sistemas gerenciadores de banco de dados, todos eles muito bons e com características próprias bastante singulares. A única coisa que tenho certeza que todos têm em comum é a capacidade de executar alguns comandos SQL de forma similar.

Uma camada de abstração para sistemas de banco de dados faz com que seu código use os mesmos métodos para acessar informações em qualquer um dos bancos de dados disponíveis. Assim, você poderia até mudar de sgbd sem ter que mudar seu código, e tudo funcionaria perfeitamente.

Claro que alguns bancos de dados não fazem as mesmas coisas que outros; alguns são mais poderosos, com mais possibilidades, outros mais simples. Portanto, uma boa camada de abstração tenta disponibilizar somente as funcionalidades que podem ser utilizadas de forma universal, ou, em alguns casos, emular as funcionalidades mais avançadas que não estão disponíveis nos bds mais simples.

Enfim, vocês sacaram?

A sigla PDO significa PHP Data Objects. Com os tais PDOs a gente tem uma forma padronizada e orientada a objetos para acessar os bancos de dados mais legais do planeta. E ganha de brinde um monte de funcionalidades interessantes. Veja um exemplo de conexão:

<?php
try {
    $meuObjetoPDO = new PDO('mysql:host=localhost;dbname=teste', $usuario, $senha);
    foreach($meuObjetoPDO->query('SELECT * from produtos') as $produto) {
        print_r($produto);
    }
    $meuObjetoPDO = null;
} catch (PDOException $e) {
    print "Deu zebra: " . $e->getMessage() . "
";
    die();
}
?>
    

 

O código acima abre uma conexão MySql e faz um select na tabela Produtos, que retorna um objeto PDO com os dados e um monte de outras propriedades. Qual a grande vantagem? Lembra como a gente fazia para acessar um bd em php? Tinhamos que usar os comandos Mysql:

<?php
$minhaconexao = mysql_connect('localhost', 'usuario', 'senha')
    or die('Erro de conexão: ' . mysql_error());
echo 'Beleza! Conectado!';
mysql_select_db('teste') or die('Não consegui selecionar o bd...');

// Performing SQL query
$query = 'SELECT * FROM produtos';
$resultado = mysql_query($query) or die('Erro na Query: ' . mysql_error());

// Printing results in HTML
while ($produto = mysql_fetch_array($resultado, MYSQL_ASSOC)) {
print_r($produto);
}

// Free resultset
mysql_free_result($resultado);

// Closing connection
mysql_close($minhaconexao );
?>
    

Até aí, já dá pra ver que usar PDO é mais fácil, mas ainda está faltando o nocaute: seu chefe chega pra você e diz, "ô fulano, vai mudar o bd, troca aí pra Oracle!".

Usando PDO, vc simplesmente troca a primeira linha e tá tudo pronto. No segundo caso... prepare-se para mudar um milhão de linhas.

Abraço grande e até semana que vem!

12 Comentários:

[Junio]  Bom dia Danilo, obrigado pelas aulas de OOP em PHP, estão sendo de grande valia para meu estudos e futuramente estarei no mercado de trabalho escrevendo PHP de forma limpa.Abraços!!  [REPLY]

[Quinhone]  Parabéns, esse material de oop é de grande valia, e se você autorizar gostria de colocar no meu blog para mais pessoas terem acesso, e se possível, vc me passar o link da parte 1 e 2, pq consegui só da 3ª em diante. Um grande abraço e obrigado.  [REPLY]

[Junio]  Porque apagaste o meu comentário passado?  [REPLY]

[Reginaldo Sousa]  A saga acabou? rs.. fico sempre na expectativa de uma nova estória. Parabéns pelos posts  [REPLY]

[patrick]  Parabéns pela serie de artigos sobre OPP, deixou um gostinho de quero mais.   [REPLY]

[Rodrigo]  clicando no link p/ ve todos os posts só aparece até o post 8, os mais antigos 1 a 7 não aparecem. Algum problema?  [REPLY]

[Dermeval]  Gostei desse artigo, principalmente essa parte >> cada programador reinventa a roda a cada dia para provar que é o melhor, porque é simplesmente a pura verdade  [REPLY]

[Compujob]  Muito bom! Convido para visitar o blog da Compujob que também sempre traz novidades sobre tecnologia, cultura e informação.  [LINK]  [REPLY]

[Otavio]  Danilo Medeiros, o homem que mais entende de música na minha opinião.... essa pinóia é mais velha que eu e vc juntos,,,,, a MichelSoft já implementava, outros SDKs e RADs tb..... isso é letter soup !! Grande Abraço  [REPLY]

[Dri Viaro]  oi, passei pra conhecer o blog, e desejar bom fds. bjss aguardo sua visita :)  [REPLY]

[Reginaldo Sousa]  Não vai mais continuar a série? Abraços.  [REPLY]

[Rogerio]  Gostaria de saber se ainda tem continuação destes artigos, pois são otimos  [REPLY]

2008-08-16 04:18:50
tags: 

O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 26)

Para ver os artigos anteriores desta série, clique aqui.

Ah, as olimpíadas. Atletas abnegados que se dedicaram durante anos para tentar a glória. Toda uma vida de treinos e sacrifícios é colocada à prova em frações de segundos. Um mísero erro, e toda a preparação vai por água abaixo.

A vida destes atletas, meus caros, guardadas as devidas proporções de massa muscular e gordura corporal, é parecida com a vida dos programadores. Um mísero erro, e todo o banco de dados vai pro saco. Um segundo a mais de performance perdida, e o servidor não aguenta o tranco. Portanto, meus atléticos leitores, ao celebrar as olimpíadas e virar a noite para ver aquele jogaço de hóquei na grama feminino não se esqueça: parte do solo sagrado do olimpo também é sua!

Ruminâncias sem nexo à parte, hoje quero mostrar mais uma jogada da biblioteca SPL pra vocês. Lembram-se do nosso carrinho de compras? Bem, respeitáveis atletas, preciso dizer que ele não aguentou a pressão na final e se enrolou todo. Explico: do jeito que construímos este carregador de objetos, ele falha miseravelmente se a gente simplesmente incluir o mesmo objeto mais de uma vez. Experimente. Duplique a linha abaixo e veja o carrinho se comportar de forma muito estranha, listando o mesmo item duas vezes. Cartão vermelho.

Pra dizer a verdade, já existe um cara na SPL que faz essa função de carrinho de compras (e, claro, de qualquer outro conteiner de objetos que você quiser) de forma muito mais esperta. É a classe SplObjectStorage.

Uma coisa que essa classe faz é exatamente controlar os objetos que nela são guardados para evitar que o mesmo objeto seja incluído duas vezes. Mais do que isso, ela controla também updates; se você alterar o objeto e adicionar novamente à coleção a classe automaticamente atualiza os dados pra você. Ippon!

Veja só que beleza:


class CarrinhoDeCompras extends SplObjectStorage {

    // nosso carrinho de compras é, no fundo, um array de objetos da classe Item...
    private $carrinho = array();
    
    //coloca um Item no carrinho
    //usando type hinting, viu o Item antes da variavel? Isso diz que essa função só aceita objetos da classe Item...
    
    public function adicionaItem(Item $item){
    
     $this->attach($item);
    
    }
    
    //detona tudo no carrinho
    
    public function esvaziaCarrinho(){
    
     unset ($this->storage);
    
    }
    
    // ué cade o resto todo? Não precisa cara. A classe SplObjectStorage já traz tudo de brinde: ArrayAccess, Iterator e muito mais!
    
// uma inclusão boa pra nos aqui: que tal colocar a logica de impressao do carrinho logo aqui?
    public function __toString(){

     foreach($this as $item) { // <- $meucarrinho é um array? é um objeto? como???
        $string .= "
" . "Código: " . $item->getCodigo() . " Descrição: " . $item->getDescricao() ." Preço: " . $item->getPreco() . " Quantidade: ". $item->getQuantidade();
        $total += $item->getPreco() * $item->getQuantidade();
     }

     $string = $string . "
" . "O total da sua compra é: " . $total;
    
     return "
" . $string . "
";
    }


}


class Item {

    private $codigo;
    private $descricao;
    private $preco;
    private $quantidade;
    
    public function __construct($codigo,$descricao,$preco,$quantidade){
     $this->codigo = $codigo;
     $this->descricao = $descricao;
     $this->preco = $preco;
     $this->quantidade = $quantidade;
    }
    
    public function getCodigo(){
    
     return $this->codigo;
    
    }
    
    public function getDescricao(){
    
     return $this->descricao;
    
    }
    
    public function getPreco(){
    
     return $this->preco;
    
    }

    public function getQuantidade(){
    
     return $this->quantidade;
    
    }
    
    public function setQuantidade($quantidade){
     $this->quantidade = $quantidade;    
    }


}

//Muito bem, agora vamos la!


$meucarrinho = new CarrinhoDeCompras();

//aqui, pra provar nosso ponto, vamos ter que instanciar os objetos em variaveis pra poder tentar adicionar novamente o mesmo objeto

$item1 = new Item('1','Caneta Bic Azul','1.00','10');
$item2 = new Item('2','Caneta Bic Vermelha','1.50','5');
$item3 = new Item('3','Caneta Bic Quatro Cores','3.50','15');

$meucarrinho->adicionaItem($item1);
$meucarrinho->adicionaItem($item2);
$meucarrinho->adicionaItem($item3);


print $meucarrinho;

// agora a prova!

$item1->setQuantidade(30);
$meucarrinho->adicionaItem($item1);

print $meucarrinho;


?>

É isso aí pessoal! Até a próxima!

1 Comentário:

[Alexandre]  Gostaria de deixar aqui os meus parabéns pelo excelente blog e também fazer uma sugestão: a de publicar uma postagem aqui informando sobre a existencia do "Portal das Video Aulas", um site que reuni diversas video-aulas gratuitas, que vão desde aulas de inglês, até como tocar violão... com o objetivo de democratizar o acesso ao conhecimento no Brasil. O endereço do site é www.portaldasvideoaulas.com.br   [LINK]  [REPLY]

2008-08-09 03:58:25
tags: 

O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 25)

Para ver os artigos anteriores desta série, clique aqui.

Respeitável público! Senhoras e Senhores! Rapazes e Raparigas de todo o Brasil! Com vocês, no palco do Circo Orientado a Objeto Ringling Bros. PHP, o fantástico mago transformador de objetos, o rei das interfaces spl, o grande Rasmussen! Vejam como ele transforma qualquer objeto em um array com apenas algumas linhas de código!


class CarrinhoDeCompras implements ArrayAccess, Countable {

    // nosso carrinho de compras é, no fundo, um array de objetos da classe Item...
    private $carrinho = array();
    
    //coloca um Item no carrinho
    //usando type hinting, veja o Item antes da variavel $item abaixo. Isso diz que essa função só aceita objetos da classe Item...
    
    public function adicionaItem(Item $item){
    
     $this->carrinho[] = $item;
    
    }
    
    //detona tudo no carrinho
    
    public function esvaziaCarrinho(){
    
     unset ($carrinho);
    
    }
    
    /*
    Aqui entram as funções obrigatórias da interface ArrayAccess e Countable.
    ArrayAccess: offsetExists, offsetGet, offsetSet, offsetUnset
    Countable: count
    Lembre-se: as interfaces exigem que voce use exatamente estes nomes para as funções!
    */


    //Existe o item numero $indice? offsetExists responde:

    public function offsetExists($indice) {

     return isset($this->carrinho[$indice]);

    }


    //Me dá ai o ítem $indice:

    public function offsetGet($indice){

     return $this->carrinho[$indice];

    }


    //Muda o item numero $indice para esse item aqui ó

    public function offsetSet($indice,$item) {

     if ($indice){

        $this->carrinho[$indice] = $item;

     }

     else {

        throw new Exception('Precisamos do indice para inserir o item no lugar certo...');

     }
    }
    
    
    // detona o item número $indice
    
    public function offsetUnset($indice) {
    
     unset($this->carrinho[$indice]);
    
    }
    
    
    // conta o numero de itens (obrigatório pela interface countable)
    
    public function count(){
    
     return count($this->carrinho);
    
    }
    
}


class Item {

    private $codigo;
    private $descricao;
    private $preco;
    private $quantidade;
    
    public function __construct($codigo,$descricao,$preco,$quantidade){
     $this->codigo = $codigo;
     $this->descricao = $descricao;
     $this->preco = $preco;
     $this->quantidade = $quantidade;
    }
    
    public function getCodigo(){
    
     return $this->codigo;
    
    }
    
    public function getDescricao(){
    
     return $this->descricao;
    
    }
    
    public function getPreco(){
    
     return $this->preco;
    
    }

    public function getQuantidade(){
    
     return $this->quantidade;
    
    }


}

//Muito bem, agora vamos la!


$meucarrinho = new CarrinhoDeCompras();
$meucarrinho->adicionaItem(new Item('1','Caneta Bic Azul','1.00','10'));
$meucarrinho->adicionaItem(new Item('2','Caneta Bic Vermelha','1.50','5'));
$meucarrinho->adicionaItem(new Item('3','Caneta Bic Quatro Cores','3.50','15'));

//Agora, caros amigos, a mágica:

$total = 0;
        for($i=0; $i<count($meucarrinho); $i++) { //<- $meucarrinho é um array? é um objeto? como???
         print "Código: " . $meucarrinho[$i]->getCodigo() . " Descrição: " . $meucarrinho[$i]->getDescricao() ." Preço: " . $meucarrinho[$i]->getPreco() . " Quantidade: ". $meucarrinho[$i]->getQuantidade();
         $total += $meucarrinho[$i]->getPreco() * $meucarrinho[$i]->getQuantidade();
}

print "O total da sua compra é: " . $total;

?>

Muito bom, não? Mas antes que vocês saiam por aí contando pra todo mundo que descobriram como se faz o truque, experimentem usar este objeto dentro de um foreach. Não rolou, certo? Você tem alguma idéia do porque? Muito bem, caro aprendiz! Você precisa implementar a interface Iterator, que falamos na semana passada, para que este objeto realmente se transforme em um Array completo!

Até semana que vem!


1 Comentário:

[João]  Estes artigos estão show, com sua ajuda estou virando um mago em OOP :)  [REPLY]

2008-08-02 02:52:05
tags: 

O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 24)

Para ver os artigos anteriores desta série, clique aqui.

Caríssimos amigos, aqui estamos de volta. Na nossa última conversa, começamos a falar destes fantásticos seres mitológicos, os Iterators. Espero que nossos exemplos tenham ajudado a entender o conceito básico por trás deste Design Pattern tão importante.

Mas agora chegou a hora de aproveitar. Nosso caro Sr. Marcus Boerger, quando criou as extensões SPL, nos deu muita coisa de brinde. Não só temos agora interfaces padronizadas para um grande número de implementações de patterns, como ganhamos também uma série de classes prontas para usar. E quando falamos de iterators, temos muita coisa boa, meus amigos! Veja o exemplo abaixo:

 
	try{
$file = new SplFileObject( "/digitalminds/texto.txt" );
$numlines = 0;
foreach ($file as $line){
$numlines ++;
}
$linenum = rand(1,$numlines);
$file->seek($linenum);
//essa linha vai ser enviada por email
mail('danilo@digitalminds.com.br', 'Assunto aqui!', $file->current());
} catch (Exception $e) {
echo $e->getMessage();
}
?>

 

Veja a beleza do que está acontecendo: ao instanciar o objeto SplFileObject, tenho prontinho um iterator que posso jogar diretamente num foreach para contar as linhas, imprimí-las, ou, usando a função $file->seek() posso pegar uma linha específica do arquivo e, no caso particular acima, enviá-las por email pra mim mesmo.

Vocês repararam que eu nem sequer pedi pra abrir o arquivo? Tá tudo pronto. E tem muito mais: esta classe tem quase 100 outros métodos que servem pra escrever no arquivo, ver as propriedades, pegar o diretório no qual ele está... experimente fazer nesse exemplo aí de cima um

print_r(get_class_methods($file) );

pra ver todos os métodos disponíveis. Ou, clique aqui e desça o scroll até a lista de funções.

E não é só isso, meus caros: vocês conseguem imaginar o que as classes DirectoryIterator, RecursiveDirectoryIterator, SimpleXMLIterator e SplFileInfo podem fazer? E que todas elas, ao serem instanciadas, te dão um objeto que funciona direitinho em um foreach ou um while? Entenderam o lance?

Muito bem. Divirtam-se com seus novos amigos. Na semana que vem, vamos aprender como transformar qualquer objeto em um array. Abraços a todos.

 

2008-07-26 04:50:57
tags: 

O Zen e a arte cavalheiresca da programação orientada a objeto (Parte 23)

Para ver os artigos anteriores desta série, clique aqui.

Ah, os iterators. Iterators, meus amigos. Como vários outros conceitos desta enigmática arte da programação orientada a objeto, os iterators são quase incompreensíveis para gente como eu - cujo único treinamento foi nas ruas, entre códigos incompreensíveis, brigas de puxar cabelo e gambiarras que mais pareciam aquelas geringonças que os vilões de desenho animado inventam para eliminar seus inimigos (quase sempre sem sucesso, é claro).

Ainda não posso dizer que entendo os iterators em toda sua grandeza. Seus significados ocultos ainda me deixam perplexo de tempos em tempos. Mas que exercícios intelectuais fascinantes eles podem nos proporcionar! Que enigmas incríveis eles nos reservam, que tesouros escondidos!
Se você ainda está lendo, acho que consegui prender sua atenção com estas baboseiras. Vocês jovens precisam de um pouco de nonsense pra prestar atenção nas coisas. Enfim. Iterators.
Pra resumir: Iterators "pegam" uma coleção de objetos e permitem que você faça operações com cada um eles. Vou dar um exemplo, porque esse conceito sempre foi pra mim muito difícil de entender. Digamos que você seja um comerciante libanês. Na sua lojinha, que fica ali na S.a.a.r.a., você vende tudo, desde açafrão em pó até relógio digital. Depois de comer 15 esfihas, folha de uva, coalhada seca, arroz com lentilha e 3 caftas no Cedro do Líbano, você resolve fazer uma contagem do estoque. Sabe como é, nesses dias de hoje, não dá pra confiar. Aí você chama o seu gerente de eletrônicos, o Sr. Salim e fala o seguinte:

- Ô Salim! Pra cada relógio aí do estoque faz o seguinte: vê se o ponteiro tá mexendo, depois vê se tá arranhado e aí coloca na caixinha de novo. Depois você me diz quantos estão bons!

Muito bem. Qual é o grande problema deste approach, caro Amir? Qualquer comerciante libanês sabe - se eu tenho que dizer tudo o que o Salim tem que fazer, pra que diabos eu tenho um gerente? E se eu tiver 15 gerentes, imagina o tempo que eu vou perder pra explicar pra cada um como ver se o produto está bom?
O que você quer, meu caro amigo mercador, é perguntar quantos estão bons, e o seu gerente te responder, independentemente de qual linha de produtos ele gerencie. Sem que você precise explicar tudo toda hora.
Deu pra sacar a diferença? Agora, um exemplo muito prático que todo mundo usa pra explicar a utilidade dos iterators em php:
Imagine que você tem um site que pega dados de três tipos de fontes diferentes: arrays, banco de dados e diretórios no servidor. Assim:


/* array */
foreach ( $relogios as $relogio) {
     // faz alguma coisa com $relogio
}

/* MySQL */
while ( $tempero = mysql_fetch_array($result) ) {
     // faz alguma coisa com $tempero
}

/* Diretorio */
while ( false !== ($brinquedo = readdir($dir)) ) {
     // faz alguma coisa com $brinquedo
}

?>

Olha para esses caras aí em cima. Não dá pra sentir que tem alguma coisa parecida entre eles? Então, imagine que você quer pegar o nome de cada um desses caras aí em cima e imprimir na tela. Isso mesmo, você quer pegar o nome tanto dos relógios que estão no array, quanto dos temperos que estão no banco de dados e ainda dos brinquedinhos que são arquivos em um diretório no servidor.
O que você faz, meu caro? Coloca dentro de cada loop um print()? De jeito nenhum! Imagina se amanha você quiser mudar o formato da impressão, vai ter que mudar 3 vezes! Ou pior, imagine se a sua loja tiver 469 tipos de produto, o que é bem comum nessas lojas - Vai colocar 469 prints? Ah, já sei - você pensou que pode simplesmente fazer uma função para imprimir e colocar dentro de cada loop! Cuidado! meu caro, você está flertando com o diabo! Você está se afastando do sagrado caminho da OOP! Comece a colocar código que não é realmente a função da classe dentro dela e em breve você estará deitado numa cama de pregos, tostando lentamente no fogo do inferno!
A solução, meus caros amigos, é muito bonita. Senhores, apresento-lhes os Iterators!

$itens['brinquedos'] = new MeuDirectoryIterator($briquedos_diretorio); // aqui a fonte de dados é um diretório
$itens['relogios'] = new MeuArrayIterator($relogios_array); // aqui a fonte de dados é um array
$itens['temperos'] = new MeuMysqlIterator($temperos_query); // aqui a fonte de dados... ah, você já entendeu.

foreach($itens as $iterator){
    
     foreach($iterator as $item){
         print $item->getName();
     }

}
?>

Não é fantástico? Que magia existe nessas classes que permite tanta padronização? Vocês entenderam o que está acontecendo? Eu não preciso me preocupar com a forma dos dados! Vale tudo! Diretórios, arrays, resultados do Mysql, e se a gente quisesse, poderíamos incluir aí XML, YAML, enfim, vale tudo! Como assim! Isso é genial! Nunca mais vou repetir código novamente! No próximo capítulo da nossa série, vamos construir as classes MeuDirectoryIterator, MeuArrayIterator e MeuMysqlIterator e conhecer em detalhes este sensacional truque. Até lá, caro Amir!

3 Comentários:

[Fabiano M]  Muito bom! OOP, começo a sentir a arte de programar... Os ninjas. rs  [REPLY]

[Danilo]  Valeu Fabiano! Abraço grande e parabéns pelo site!  [REPLY]

[Emiliano]  Não li ainda, mas é um satisfação saber que mais um capítulo foi escrito!!!  [REPLY]