2017-10-21 17:10:56
tags: 

Digitalminds Podcast, o retorno

E depois de um longo, mas longo mesmo, tipo, muito longo inverno, o Digitalminds Podcast volta ao vivo com as participações de Rodrigo Cornelio, organizador do UaiPod, e Karin Voll, do podcast X-Poilers, direto de BH, contando tudo sobre o Uai Pod que rolou nesse sábado 21.

Também presente Gustavo Guimarães, do Podcrastinadores, conversando sobre podcasts, filmes e velharias. É muito bom estar de volta!

Veja no Youtube! ou ouça aqui!

 

2017-10-19 02:58:53
tags: 

Digitalminds LIVE dia 21!

Caríssimos e caríssimas, no LIVE do sábado 21 já temos mais um convidado confirmadíssimo - Gustavo Guimarães, do Podcrastinadores, vai estar com a gente.  Aqui, a chamada. Vejam também que o feed do podcast já está atualizado com essa nova mensagem, assinem!

2017-10-18 10:42:03
tags: 

O Digitalminds Podcast Voltou. Mesmo. Eu juro.

É verdade. O digitalminds Voltou.  É sério. Mesmo. Mas como não basta voltar, tem que fazer alguma coisa completamente bizarra, vamos estar falando com os senhores ao vivo, via Twitter, YouTube e sei lá mais o quê no dia 21 de Outubro, sábado,  às 20h. Tem convidados especiais, também, e uma entrada ao vivo com os podcasters que vão estar lá em BH, no @uai_pod. Tava com saudade? Então aguenta!
Fica ligado no twitter @digitalmindsBR pra saber as novidades. Até lá.

2017-06-21 06:44:14
tags: 

Depois de outro longo, mas longo mesmo, e tenebroso inverno...

Caríssimos leitores - ainda tem alguém aí? Mantendo a minha média de um post a cada quinquênio, sempre pontual, volto ao digitalminds para novamente afirmar radiante: "Estou Vivo!". E, não, não me tornei um ermitão, como fiquei sabendo que alguns acreditam. Foi na verdade somente descaso mesmo. Vocês sabem como é a vida: um dia você está livre como um passarinho, e no outro, te jogam sal na cauda. 

Mas nesses tempos de delações premiadas o que vale é a prova cabal - os áudios! Pois provo que estou vivo nessa divertida entrevista com o Alexandre do Papo Editado - vulgo Sr. A. da podosfera brasileira.

http://editorsenhor-a.com.br/podcast/papo-editado-017-danilo-medeiros/

Confesso que novamente estou sentindo coceira pra voltar a gravar o digitalminds. Por enquanto, volto ao twitter no @digitalmindsBR pra ver se tem alguém que ainda se importa com as bobagens que eu falo.

Abraços a todos. 

2011-03-25 12:45:39
tags: 

Depois de um longo e tenebroso inverno, um vídeo

Pessoal (se é que alguém ainda tem este site zumbi em seus leitores rss):

Eu não morri. É fato. Não poderia estar escrevendo este post-enrolação se efetivamente estivesse morto. Mas como ainda tem gente que comenta no Digitalminds eu resolvi pelo menos postar alguma coisa. Não deixa de ser uma forma de agradecer a vocês, nossos abnegados leitores.

 Em 2009 fiz uma palestra no NAVE, a escola experimental do Oi Futuro no Rio. E até hoje gosto dessa palestra, pois trata-se de um assunto pelo qual sou apaixonado: interfaces.

 Enquanto um novo post de verdade não vem, fica o agradecimento e o link para esse vídeo. 

 http://www.videolog.tv/video.php?id=452453

 Se ainda tem alguém por aí, manda um comentário. 

 Abraços a todos

9 Comentários:

[Ricardo]  Wow.. 3 anos off é tempo hein... Oo welcome back ^^  [REPLY]

[Leocadio]  olá, p@z & bem! o bom filho à web volta!!! claro que não podia deixar de saudá-lo! costumava chamar vc, o GL e o RM de o trio do podcast brazuca! as interfaces e o design aprofundando as relações das pessoas... é por aí. []s livres, @leoc4dio.  [REPLY]

[Alexandre Dutra]  ok...meu leitor de rss achou seu comentário...espero q volte a postar conteúdos relevantes..abracos  [REPLY]

[William]  Sério! Volta a postar sobre orientação a objeto. A cada post seu eu solto um PUTA QUE PARIU! Sério que da pra fazer isso? Conheci seu blog ontem e infelizmente já li e testei as 27 partes. Hmmmmmmmmm (braiiins) Pooosts! haha  [REPLY]

[andre]  poxa, realmente depois de um long tempo.. mas os textos me foram uteis na época que escreveu.. abraços  [REPLY]

[Mauricio]  Tudo bem amigão? Espero que estejas bem. Ver um novo post seu me da uma sensação de nostalgia que chega até doer o coração de saudades dos velhos tempos quando aprendia a programar... seus posts me ajudaram muito quando precisei. Abraços!  [REPLY]

[Vicente]  Muito interessante o vídeo, e muito bom o material sobre OOP. Estou começando agora, ainda estou bem perdido quanto a desenvolvimento de software, mas com os Posts sobre OOP e o vídeo incentivando a inovação, posso ver que tenho que correr atrás da diferença. Obg!  [REPLY]

[Junio]  Muito obrigado. É de grande valia. Paz e saúde para ti.  [REPLY]

[fabiano]  Pô, legal! Tah de volta neh.... abraço!  [REPLY]

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]

2008-03-25 09:06:44
tags: 

Muito trabalho, um mba e mais um infinito de coisas

Pessoal, não tenho aparecido muito por aqui ultimamente - nossa série está novamente emperrada, com jeito de que não vai sair do lugar. Dessa vez, foram vários motivos: trabalho, mais trabalho, um mba e mais um infinito particular de coisas, incluindo a terceira temporada de Lost. 

Se eu prometer que a série vai continuar em breve, vocês ainda acreditam? O plano é esse, o problema é o tempo. Antes que vocês apareçam lá em casa com seus ancinhos e picaretas para o linchamento, já peço paciência novamente e uma boa dose de compaixão para com este seu autor. 

6 Comentários:

[tigo]  Suave Danilo. Acompanho teu blog/vc há alguns anos, acho que desde 2002, e vou continuar assinando teu feed na boa. O intervalo de tempo entre um post e outro é compensado pelo ótimo conteúdo que tu produz. Por mim, fica na boa, suave... =]  [REPLY]

[ms*]  Eu como parte culpada sou super compreensiva... Principalmente se o vazamento do corredor for consertado :-) Hehehehehehe  [REPLY]

[João]  Bom, eu comecei a ler teu blog num feriado que estava moscando no trabalho.. mas agora também ando bem ocupado e mesmo que tivessem novos artigos não conseguiria ler com calma e testar. Mas continuo acompanhando os feeds =)  [REPLY]

[João]  Ahhh.. e Lost já está na 4ª temporada ;-)  [REPLY]

[Cristóferson Bueno]  Opa Danilo, blz? Faz tempo que eu não passo aqui... Acho que ando na mesma levada que vc, trabalho, trabalho, mestrado e coisas pessoais (não é o Lost, mas relativos rsrs), vi a chamada para este post no Web Clip do Gmail ai resolvi, fazer uma visita. So tenho a lamentar sua ausência (justificada) de posts e podcasts é sempre interessante ver seu ponto de vista das coisas, abraço Danilo, até!  [REPLY]

[Joao]  Poxa, mas o Lost já esta na quarta temporada... ta atrasando heim? brincadeira, parabens pela sua seria sobre oop  [REPLY]

2008-01-09 11:15:42

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

                

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

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

Olá amigos. Estamos de volta depois de muita farofa, bacalhau, doce de leite, maionese, pamonha, queijo cavalinha, uma nova geladeira que não chega, livros e muita alegria. Espero que todos tenham passado dias maravilhosos nesse fim-de-ano e que possam ter aproveitado esses dias pra curtir a família e os amigos!

Mas chegou a hora de voltar para o batente. Antes que vocês comecem a mandar os já tradicionais emails "Cadê o 22! Queremos o 22!" eu já estou escrevendo mais um capítulo desta série singela, que procura explicar os conceitos mais enrolados de orientação a objetos em uma linguagem que todos aqui possam facilmente entender. E, pra ser bem honesto, os emails cobrando o 22 na verdade já começaram a chegar, então a hora é essa. Não estou reclamando de vocês de forma alguma, caros leitores! A pressão ajuda! Obrigado a todos que cobram, que agradecem, que mandam correções e puxões de orelha, sua contribuição faz disso aqui um lugar melhor.

Ah, o Natal. Que loucura que é o Natal. Falar sobre oop aqui no Digitalminds sempre é divertido porque eu tenho que bolar metáforas interessantes pra que o assunto não fique chato no primeiro parágrafo.  Então, como não poderia deixar de ser, o artigo de hoje está em clima de Natal. Não, eu não estou maluco, eu sei que o Natal já passou. Mas a segunda semana de janeiro não tem muita coisa interessante pra nos oferecer, a não ser que você conte o Dia de Reis.

O DIA DE REIS! É isso! Meu Deus como pude esquecer! Muito bem, senhores, esqueçam o natal. É hora de falar de Belchior (ou Melchior), Gaspar e Baltazar.
Não, senhores, não estamos falando de Belchior, nem de Gaspar, ou mesmo de Baltazar. Estamos falando de três magos persas, sacerdotes de Zaratrustra, homens sábios que conheciam profundamente a astrologia e que vislumbraram um sinal - na noite do dia 25 de dezembro do ano 1, souberam pelo brilho da estrela de Belém que um Rei nascera. E para comprovar que a wikipedia é sempre uma diversão, veja este parágrafo:

A melhor descrição dos reis magos foi feita por São Beda, o Venerável (673-735), que no seu tratado “Excerpta et Colletanea” assim relata: “Melchior era velho de setenta anos, de cabelos e barbas brancas, tendo partido de Ur, terra dos Caldeus. Gaspar era moço, de vinte anos, robusto e partira de uma distante região montanhosa, perto do Mar Cáspio. E Baltazar era mouro, de barba cerrada e com quarenta anos, partira do Golfo Pérsico, na Arábia Feliz”.

Uau. Sábios, caldeus, Ur, Pérsia. Agora que consegui a atenção total e irrestrita de vocês, futuros reis magos da OOP, e cobri todos de Incenso e Mirra, é hora de falar de uma classe importantíssima que ficou faltando no nosso grande esquema das coisas: a venerável classe ModelCollection.

Lembram que optamos por simplificar as funcionalidades da classe Model, fazendo com que ela realizasse operações somente em registros únicos no banco de dados? Muito bem, senhores, a classe ModelCollection aparece para nos salvar nos casos em que precisamos trabalhar com conjuntos de registros. Aqui é bom repetir o aviso: esta implementação é diferente da utilizada nos frameworks que utilizam o pattern ActiveRecord, como o Cake. Nestes frameworks todas as operações com registros e conjuntos de registros são feitas pela classe Model e suas subclasses. Assim, um objeto da classe model típico destes frameworks tem funções tanto para buscar, editar, salvar e deletar um registro quanto para buscar conjuntos de registros. Isso faz com que o objeto da classe que estamos usando não tenha um mapeamento direto com os dados que estão no banco. Isso me incomoda muito, pois eu gosto de pensar no objeto como uma coisa, uma representação virtual dos dados que estão no banco. Pra mim é estranho usar o modelo para retornar uma lista de registros. A nossa implementação vai claramente mapear um registro no banco a um objeto da classe correspondente, e um conjunto de registros a uma coleção de objetos da classe correspondente. Exemplo: nossa classe Post. Teremos no banco a tabela Posts, com os campos title e text, por exemplo. Para acessar e alterar  o campo de título de um post em nosso framework vamos seguir os seguintes passos:

  1. Criar um novo objeto da classe Post fazendo $post = new Post();
  2. Carregar os dados do registro que queremos alterar com id número $id  usando $post->loadById($id);
  3. Mudar o título usando $post->setTitle("Novo Título!");
  4. Salvar o post com $post->save();
Para criar um novo post, é simples:
  1. Criar um novo objeto da classe Post fazendo $post = new Post();
  2. Mudar o título usando $post->setTitle("Título do Novo Post!");
  3. Mudar o texto usando $post->setText("Texto do Post!");
  4. Salvar o post com $post->save();
Nessa implementação vamos poder acessar as variáveis do objeto usando getters normalmente, por exemplo, $post->getTitle(); Podemos também criar vários atalhos: o construtor do Post pode receber  o Id diretamente e já carregar os dados automaticamente. Podemos implementar a interface ArrayAccess para permitr coisas como print $post['title'] sem nenhuma dificuldade. Enfim. A coisa é boa. Aguardem que vem coisa ótima por aí.
Mas até aí, nenhuma novidade. O que muda é a forma de trabalhar com conjuntos de dados. No Cake, esse trabalho seria feito por funções na classe Post que retornariam Arrays contendo vários ítens. E isso deixa tudo confuso, no final das contas. O que proponho é o seguinte:
  1. Criar um novo objeto da classe PostCollection fazendo $collection = new PostCollection();
  2. Carregar o conjunto de registros usando uma das várias funções disponíveis, por exemplo $collection->loadAll();
Muito simples. E agora temos um objeto da classe PostCollection carregado de registros, com métodos super úteis para manipular os dados, paginar, enfim, uma belezinha. E vamos implementar uma coisa sensacional: a interface iterator, disponível na fantástica biblioteca SPL, proveniente de UR, na Pérsia! Mas isso já é assunto para o próximo episódio. Até lá!


18 Comentários:

[Fabricio]  Ola Danilo, parabéns pelas aulas, será que vc pode disponibilizar este framework, pois estou fazendo um site, e ja queria fazer nesses padrões. Agradeço desde já  [REPLY]

[elomar]  parabéns outra vez! esse foi um dos melhores textos da série, e o sistema de blog promete...  [REPLY]

[Danilo]  Ö Fabricio! Na verdade estamos planejando o framework para depois construí-lo! Por que nao utiliza o Cake? Grande abraco!  [REPLY]

[Danilo]  Valeu Elomar! Obrigado pelos elogios e vamos em frente!  [REPLY]

[Leonardo Alberto Souza]  Não entendi o que que os Reis Magos tinham a ver com isso... mas tá tudo muito bom!! :)  [REPLY]

[danilo]  Hehehe! Valeu Leonardo! Abraço grande!

[leo]  Olá Danilo, gostei muito da serie, mas gostaria que fosse mais frequente, pois cheguei agora e já li os 22 posts, mas tudo bem,, ficarei aguardando novidades, parabens  [REPLY]

[danilo]  Oi Leo! Essa é a grande reclamação do povo aqui... hehehe já já vamos ter mais um capítulo! Grande abraço!  [REPLY]

[leo]  Como funciona o Dispatcher? com .htaccess?  [REPLY]

[danilo]  Exatamente Leo... Abraço grande  [REPLY]

[Leandro]  E daí Danilo, tudo blz? Mesmo não comentando, sempre visito seu blog, no mínimo umas 3 vezes por semana. Gostaria de saber quantos capítulos terá o zenoop. Atualmente estou trabalhando com o Cake, mas acho que esse que está sendo desenvolvido vai ter uma performance melhor, além de no final saber exatamente o que cada coisa faz. Estou aguardando chegar nos finalmente pra poder utilizar em produção.  [REPLY]

[Igor]  Todos estão esperando anciosamente,, não faça isso conosco. vc conhece esse blog? http://www.livrodeengenhariaderequisitos.blogspot.com/ ? abraços  [LINK]  [REPLY]

[putz..]  brother, sua série é show, muito bem explicada, mas as metaforas tornam tediosa a leitura, estamos atras de conteúdo técnico, não bla bla bla, que dia vamos começar a montar efetivamente o projeto ?  [REPLY]

[Renato]  Quando sai o próximo,a parte 23?  [REPLY]

[Marcelo]  Não acredito que acabei de ler... Espero que não demore para continuar a "SAGA MVC" ;-D. Abraço e até o proximo post!  [REPLY]

[Danilo]  Acabou de sair! Abraço grande!  [REPLY]

[TarsisLima]  Olá , vi seu site e achei muito interessante! Estava fazendo uma pesquisa sobre mvc e encontrei este site. Gostaria de tirar uma dúvida,,, tenho classes DAO e VO (ou BEAN) compondo o model, e um controller pra cada model ... e tenho tambem uma classe dispacher " que é aquela que pega o modulo solicitado na url e instancia seu respectivo controller ... algo como index.php?control=noticias&action=listar onde instancio o controller de noticias e chamo o metodo listar que retorna um array de objetos do banco neste modelo consegui fazer um crud (inserir alterar excluir e listar) tranquilamente....  [REPLY]

[TarsisLima]  Olá , vi seu site e achei muito interessante! Estava fazendo uma pesquisa sobre mvc e encontrei este site. Gostaria de tirar uma dúvida,,, tenho classes DAO e VO (ou BEAN) compondo o model, e um controller pra cada model ... e tenho tambem uma classe dispacher " que é aquela que pega o modulo solicitado na url e instancia seu respectivo controller ... algo como index.php?control=noticias&action=listar onde instancio o controller de noticias e chamo o metodo listar que retorna um array de objetos do banco neste modelo consegui fazer um crud (inserir alterar excluir e listar) tranquilamente....  [REPLY]

2007-12-04 02:20:34

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

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

Olá amigos. Em nosso último encontro finalizamos nossa primeira análise das classes principais do MVC: Model, View e Controller. Sei que muitos de vocês estão ansiosos para começar a codificar mas ainda temos bastante mufa pra queimar antes de começar a digitar código php!

Bom, pra começar, um pouco da história do cinema: quem não se lembra de Sean Connery como o policial irlandês em Os Intocáveis ? E de Kevin Spacey, como o bobalhão "Verbal" em Os Suspeitos ? E de Gene Hackman como o xerife mau, muito mal de Os Imperdoáveis ? Muito bem, o que esses três papéis interpretados por estes grandes atores têm em comum? As três interpretações foram premiadas com Oscars de melhor ator coadjuvante. E por quê todo este papo cinematográfico? É que hoje vamos falar de uma classe coadjuvante que é fundamental em nosso quase-framework: nosso amigo Dispatcher.

Muito bem, como já falamos algumas vezes, nosso framework é bastante esperto: ele vai permitir que acessemos métodos de nossos controllers simplesmente interpretando uma URL. Por exemplo, para acessar o método view() do controller BlogPost para ver o post com o id 19 nossa url seria

http://nossoblog.com.br/blogpost/view/19

Ok, mas quem transforma uma coisa na outra? Quem chama o que? Como isso funciona na prática?

Senhores, eu vos apresento a classe Dispatcher, encarregada de interpretar as urls de nossa aplicação e executar os métodos apropriados nos controllers corretos. Ela também vai checar se o controller e o método requisitados realmente existem, e vai apresentar mensagens de erro em caso negativo. Por fim, a classe vai separar corretamente os parametros do request, enviando um array já certinho para o método que foi chamado.

Uma outra função muito interessante de nossa classe Dispatcher vai ser interpretar extensões; sim, amigos, vamos fazer com que a extensão definida na url defina o layout e o template a ser utilizado, seguindo uma estrutura de arquivos pré-determinada. Exemplo: se ao invés da url acima tivessemos alguma coisa como

http://nossoblog.com.br/blogpost/view/19.xml

Nosso framework, ao invés de utilizar o layout em /layouts/default/blogpost/view.php e o template /templates/default/blogpost/view.php utilizaria o layout /layouts/xml/blogpost/view.php e o template /templates/xml/blogpost/view.php. Deu pra sacar o poder? Assim vc pode criar outputs diferentes pra toda a sua aplicação sem nenhum estresse. Bonito demais. Pra colocar o sistema disponível em wap, bastaria fazer um layout e um template, no caso /templates/wml/view.php e /layouts/wml/view.php e utilizar os códigos wml ao invés de html dentro deles. Eu adoro isso.

Você acaba de perceber a beleza de uma solução MVC. A lógica fica totalmente separada da apresentação, o que faz com que seja fácil fazer apresentações totalmente diferentes com o mesmo conteúdo. Sweet!

Vamos então à descrição da classe?

Class Dispatcher

Propriedades

$url

String. Propriedade que irá conter a url requisitada.


$controller

Objeto do tipo Controller. Esta propriedade irá conter uma nova instância do controller requisitado. No nosso exemplo, BlogPost.

$method

String. Método a ser executado no controller requisitado. O método será view(), no nosso exemplo.


$parameters

Array com os parâmetros enviados na requisição via get ou post. No exemplo acima, ele teria uma entrada $parameters["default"]=>"19" já que não nomeamos este parâmetro no request. Poderíamos, se nós fossemos chatos, ter montado a url assim:

http://nossoblog.com.br/blogpost/view/id/19

e aí nosso array seria montado na forma $parameters["id"]=>"19"

O framework vai ser esperto o suficiente pra perceber quando temos só o valor ou o par nome/valor e vai resolver tudo isso pra nós.

Métodos

parseURL()

O método parseURL() interpreta uma URL segundo os padrões combinados e popula as propriedades do nosso Dispatcher. Na prática, ele vai separar os pedacinhos da url, dividindo a string em partes. Em primeiro lugar, ele remove a string relativa ao protocolo (http:// ou https://). Depois, o domínio. Ficamos então com a estrutura

controller/método/parametros.extensao

Aí fica facil separar tudo, não?


parseParams()
O método parseParams() faz o mesmo que a função acima, só que para os parâmetros enviados por get e post. Tudo o que estiver entre um ? e o ponto da extensão será considerado parâmetro get. Também será considerado parâmetro get tudo o que vier depois da action requisitada, no caso de nossos exemplos acima "19" e "id"=>"19". Tudo o que vier no $_POST vai ser incluído também em nosso array $parameters.

Repare que pra simplificar as coisas não vamos considerar a diferença entre get e post em nosso array $parameters; será igual fazer um request por get e post. Juntaremos tudo no array, sem distinção.

9 Comentários:

[Paul]  E o capítulo 22? Nossa, não pode parar! Está muito bom, indico pra todo mundo que tem interesse em aprender OO. Abraços!  [REPLY]

[Ederson Peka]  O último filme é 'Os Imperdoáveis'?! Tá escrito 'Os Intocáveis' de novo... ;-)  [REPLY]

[danilo]  Valeu Peka! Já corrigi. Muito obrigado!

[Tarcísio Sassara]  Apesar de não ter comentado os outros artigos. Estive sempre por aqui acompanhando. "O Zen e a arte cavalheiresca da programação orientada a objeto" será uma ótima referência para quem estiver começando. Parabéns!  [REPLY]

[danilo]  Ô Tarcísio! Muito obrigado! Abraço grande!  [REPLY]

[DGmike]  Boa Danilo, antes de começar a ler a sua serie não conhecia orientação a objetos, hoje estou escrevendo um framework para sites simples, algo como um gerador de sistemas sem muito bafafá como o WordPress ou o Smarty ou até mesmo o CodeIgniter e sim só o que prescisamos no dia-a-dia. Aprendi a usar o SVN, aprendi a usar a orientação a objetos, aprendi a trabalhar com o MVC. o que quero dizer é muito obrigado por essa séria maravilhosa que você está escrevendo... Ah, depois, quando sair a primeira versao do meu framework eu te passo o link :D  [REPLY]

[danilo]  DGMike, muito obrigado. Fico muito feliz de poder ajudar! Grande Abraço!  [REPLY]

[Filipe]  Cheguei aqui através do blog do Tulio Faria (http://www.tuliofaria.net). Comecei a ler a parte 1 e então não parei mais até chegar aqui, confesso que seus artigos parecem capítulos de algum livro do Dan Brown ou episódios de um seriado tipo Prison Break ou Lost. Ganhou um leitor =) E estou no aguardo dos próximos artigos, um tanto quanto impaciente, mas acima de tudo tentando equilibrar o meu lado Zen! Estou estudando o framework CakePHP, o Smarty Engine e o padrão MVC e esses artigos foram de grande valia! Parabéns. Grande abraço!  [REPLY]

[danilo]  Valeu Filipe! Obrigado! Agradeço se ajudar a divulgar! Até a próxima.  [REPLY]

2007-11-22 01:44:13

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

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

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

Olá pessoALL. Estamos aqui mais uma vez pra falar de Orientação a Objetos de um jeito bem prático, utilizando o pattern MVC para exemplificar conceitos importantes. A linguagem escolhida, você provavelmente já sabe, é PHP. Então sinta-se à vontade, sente mais perto da fogueira que já vamos começar nosso papo.

Chegamos a um momento importante de nossa série. Vamos falar hoje do último vértice da tríade MVC, mais especificamente a classe View. Você lembra que deixamos a classe View por último por se tratar do conceito mais simples dos três? Muito bem, chegou a hora de ver se a coisa é tão simples quanto falamos.

Nossa classe base View terá a responsabilidade de imprimir nossas páginas HTML, juntando o conteúdo dinâmico obtido por nossos Controllers ao código que colocamos nos templates que criamos. Portanto, primeiro precisamos definir direitinho o que é um template dentro de nosso framework, já que existem inúmeras definições por aí.

Nossos templates serão páginas php especiais, contendo basicamente html, que vão ser utilizadas por nossa classe View para imprimir as páginas de nossas aplicações MVC na tela. Normalmente nestes templates vão conter todo o html básico da página e comandos PHP para imprimir as informações dinâmicas provenientes do controller, normalmente usando só algumas poucas funções do PHP como echo, print e foreach.

Um exemplo de template talvez deixe isso tudo mais claro. Imagine que já temos tudo pronto em nosso sistema de gerenciamento de blogs, e chegou a hora de fazer o template que mostra um post. O código deste template (muito simplificado, claro) seria algo assim:
<h1><?php echo $this->data['BlogPost']['title'] ?></h1>
<div class="post"><?php echo $this->data['BlogPost']['text'] ?>
</div>

Reparem que não precisamos incluir no template nenhuma informação de tipo de documento (DOCTYPE) ou mesmo a seção <head>. Nossa classe View vai colocar tudo isso automaticamente pra nós, de acordo com definições gerais que vamos colocar em outros arquivos, chamados de layouts. Os layouts são basicamente arquivos HTML sem a seção <body> do html, e servem justamente para que não precisemos ficar repetindo estas informações toda hora. A classe View vai combinar layouts e templates para construir a página. De forma simplificada, portanto, podemos dizer que nossos templates são o corpo do documento html (<body>), e os layouts são o resto. Deu pra sacar?

O que os templates têm de especial? Nada, sinceramente. Especial é o acordo que fazemos para só utilizar html e funções de apresentação dentro deles. Isso é fundamental para que não misturemos lógica (que deve estar toda no controller) e apresentação (que deve estar toda no template). Se você começar a usar outras funções que não echo, print ou foreach (ou alguma outra função de formatação, tipo printf ou number_format) dentro dos templates você vai voltar imediatamente pro inferno.

Alguns caras levaram isso tão a sério que chegaram a criar linguagens especiais só para não usar PHP dentro dos templates. O Smarty, um dos mais poderosos sistemas de template já escritos em php, faz exatamente isso.  Eles criaram tags especiais para cada uma das funções PHP de apresentação, além de terem bolado uma série de outras interessantes. Ao invés de escrever algo tipo


<h1><?php echo $nome ?></h1>


no Smarty você escreveria

 

<h1>{$nome}</h1>

Bem interessante, não? Isso força o programador a utilizar somente os comandos do Smarty, que são somente de apresentação.

Mas veja que desenvolver uma solução como essa dá bastante trabalho: no fundo, toda essa codificação especial precisa ser transformada novamente em PHP alguma hora. Os críticos dizem que isso é desnecessário e prejudica a performance, já que o PHP oferece todas essas funções nativamente. Bem, os caras do Smarty (e de outros template engines que existem por aí) contra-atacam dizendo que todos os templates são compilados e cacheados em PHP, de forma que a diferença de performance é mínima.

Nós não temos aqui a pretensão de escrever um Smarty; o caminho mais simples é usar PHP puro. Este, portanto, é o caminho que vamos seguir.

Vamos à nossa descrição genérica da classe View:

Class View
Propriedades

$data

Array associativo contendo todas as informações dinâmicas de modelos e coleções.

$url

String com a url que está sendo acessada.

$layout

String com o nome do layout a ser utilizado. O Default é nulo, o que irá fazer com que a classe View utilize um layout padrão.

$baseurl

String com a url base do site para facilitar a montagem de links e caminhos de arquivos.

 $variables

Array associativo que pode conter outras variaveis genéricas definidas pelo controller.

 

Métodos

render($action,$layout)

Imprime a ação $action usando o layout $layout. Os defaults são a ação corrente e o layout default.

setVariable($variablename,$value)

Define uma variável para uso no view.

setPageTitle

Define o título da página a ser impressa (na tag <title>)

renderError($error)

Imprime uma página de erro utilizando o layout default para erros.

 


5 Comentários:

[LuRsT]  Opa, tá ficando cada vez melhor, quero começar a colocar as mãos na massa e desenvolver esta aplicação! Parabéns, continua assim!  [REPLY]

[danilo]  Valeu LuRsT!!! Obrigado!  [REPLY]

[Thiago]  Olá, eu não sou profundo conhecedor de PHP, mas conheço algo de MVC e tal. Bateu uma dúvida, olhando sua lista de métodos da classe View. Vc listou que ela tem um método do tipo setVariable... nao tem nenhum getter dessa variavel ? Se nao tem, acessar ela diretamente nao viola o principio de encapsulamento ?

[danilo]  Oi Thiago! Olha, repare que estas variáveis que estamos SETando são variáveis que usamos somente pro output dos dados no template... repare que na verdade estamos chamando de variáveis itens de um array... nesse caso estamos apenas expondo essas "falsas" variáveis para que o view possa imprimi-las ao desenhar a página. Deu pra entender? Não é exatamente um setter no sentido tradicional...  [REPLY]

[Billy]  Danilo !!! Preciso entrar em contato com vc. Saber mais sobre o primeiro Podcast brasileiro !!! Abraços.  [REPLY]

2007-11-13 02:37:51

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

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

Muito bem, caros amigos, voltamos à série que explica os conceitos transcendentais de programação orientada a objetos numa linguagem que todos podem facilmente entender. Este seu autor agradece novamente a todos pelos e-mails e comentários, são eles que nos incentivam a continuar sempre.

No último capítulo começamos a descrever nossas classes, notadamente a classe base Model, de fundamental importância em nosso quase-framework MVC. A fim de continuar nossa tarefa, proponho uma pequena reorganização de nosso estimado acrônimo: gostaria de falar neste artigo da classe base Controller, antes de falar da classe View. O motivo é simples: acredito que vai facilitar o entendimento se deixarmos para falar da classe View depois. Como o PHP é praticamente uma linguagem de construção de templates, posso afirmar de forma geral que todos que já trabalharam com PHP vão entender mais facilmente o conceito de Views.

Vamos lá, então? Vocês ainda se lembram do artigo no qual falamos que a url requisitada para o browser iria definir os modelos e ações a serem realizadas? Muito bem, só pra lembrar, nossas urls terão o seguinte formato:

http://www.meusite.com.br/modelo/acao/parametros

Nosso controller, então, vai saber direitinho em qual modelo aplicar uma determinada ação com certos parâmetros. Um exemplo seria:

http://www.meublog.com.br/blogposts/add/

Nesse caso, primeiramente nosso controller iria instanciar um objeto da classe BlogPost, que é filha da classe Model e já herdou tudo o que precisa para fazer as operações no banco de dados.

Repare que para facilitar vamos utilizar sempre o nome dos controllers no plural - alguns de vocês devem ter estranhado o fato de um controller BlogPostS instanciar na verdade um objeto da classe BlogPost (sem o S). O motivo é bem simples: o controller BlogPosts irá cuidar tanto da criação/edição/visualização/exclusão de um único BlogPost quanto da visualização de coleções de BlogPosts. Quando trabalhamos com um único registro, um único artigo de nosso blog, ele irá utilizar a classe BlogPost. Quando precisarmos trabalhar com coleções ou listas de artigos, como por exemplo uma listagem paginada, ele irá utilizar a classe BlogPostCollection.

Bom, vamos continuar: em seguida, nosso controller de BlogPosts iria executar seu método add. Este método iria checar se existe algum post http de formulário de dados do usuário.

Em caso negativo, ele instancia um objeto da classe View e imprime o template adequado, que claramente será um formulário que submete seus dados para a mesma URL,

http://www.meublog.com.br/blogposts/add

O template adequado, nesse caso, é o arquivo add.tpl, que fica dentro de uma pasta BlogPosts, que por sua vez vai ficar dentro de uma outra pasta Views, em um lugar seguro de nosso servidor que não precisa nem estar disponível publicamente. Repararam como até mesmo a organização dos arquivos é bem resolvida dentro de um framework? Só precisamos criar templates com os mesmos nomes que nossas ações e colocá-los nos folders com os mesmos nomes de nossos controllers para que a mágica aconteça.

Bom, imaginando que o usuário tenha preenchido o formulário acima e o tenha submetido, nosso controller recebe os dados, popula o objeto instanciado da classe BlogPost que está na propriedade $model com os dados que vieram do formulário, faz a validação executando o método $model->validate() e se estiver tudo bem, salva os dados executando $model->save() e mostra uma mensagem de sucesso usando o método flash(). Esse método imprime uma mensagem na tela durante alguns segundos e em seguida redireciona o usuário para outra página qualquer, no nosso caso provavelmente a lista de posts.

Deu pra entender?

Class Controller

Propriedades

$model

A propriedade $model vai armazenar o modelo no qual nosso controller irá operar as ações desejadas. Em nosso exemplo, ele armazenaria uma instância da classe BlogPost.

$modelcollection

A propriedade $modelcollection vai armazenar uma instancia da coleção relacionada ao modelo requisitado a fim de fazer as operações com coleções ou listas. No nosso caso, uma instância da classe BlogPostCollection.

$action

$action vai guardar a ação solicitada. No nosso exemplo, add. Para que a mágica funcione, nosso controller deverá ter um método add(). Para cada ação deverá existir um método correspondente em nosso controller; ações que não existem serão tratadas como erro.

$parameters

A propriedade $parameters guarda todos os parâmetros extras do request. Por exemplo, se estivéssemos vendo uma lista de Posts, poderíamos usar paginação, e o número da página viria como um parâmetro:

http://www.meublog.com.br/posts/list/page=3

$othermodels

$othermodels é uma propriedade que vai nos permitir instanciar objetos de outros modelos que não somente os da classe requisitada no request. Por exemplo, poderíamos querer utilizar as informações do usuário que está adicionando o post a fim de gravar no banco quem fez a última alteração. Assim, precisaríamos também de um objeto da classe User.

$view

Instancia da classe View que irá imprimir na tela os templates correspondentes.

 

Métodos

flash($message,$url,$seconds)

O método flash() mostra o texto de $message durante alguns segundos ($seconds) e em seguida redireciona para a url especificada. Muito útil para mostrar uma mensagem de sucesso ou fracasso de alguma ação.

redirect($url)

O método redirect() é muito simples: ele simplesmente redireciona o processamento para a url desejada.

Por hoje é só, pessoal. Voltamos a qualquer momento com mais orientação a objetos para vocês!

 

 

6 Comentários:

[Elomar França]  Novamente, um ótimo artigo. Só falta saírem mais rápido, pra gente não ter que esperar tanto.... =]  [REPLY]

[danilo]  Valeu Elomar! Tô determinado a escrever toda semana! Abraço grande.  [REPLY]

[Junio]  Muito obrigado pelas informações disponibilizadas, pois estão sendo de grande valia para mim.Obrigado mesmo.  [REPLY]

[danilo]  Ô Junio, é um grande prazer poder ajudar. Grande abraço!  [REPLY]

[Junio]  Boa tarde meu amigo Danilo, obrigado por mais está aula.  [REPLY]

[noivas rj]  muito bom o post  [LINK]  [REPLY]

2007-10-09 04:59:38

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

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

Olá Pessoal, estamos de volta com a série que mostra alguns princípios de programação orientada a objetos precisamente a cada rand (1,32768) dias!

Muito bem, senhoras e senhores. Acho que chegou a hora da gente "objetivar" um pouco e listar aqui nossas classes e seus métodos: até eu, depois de algum tempo sem escrever, me perdi! Já falamos livremente sobre os modelos, controllers e views de nosso quase-framework; agora é importante colocar no papel. Digo, no banco de dados. Enfim, vocês entenderam.

Então vamos começar com a classe Model, base para todos os nossos modelos:

Classe Model

Atributos 

$primarykey

String. Nome da chave primária do banco de dados. O default é id, mas pode ser qualquer nome desde que seja inicializado ao criar o modelo.

$table

String. Nome da tabela à qual o modelo será mapeado. O default é o nome do modelo.

$data

Array. O array $data vai conter os dados do modelo, mapeando cada campo com seu valor.

$fields

Array. Lista dos campos da tabela relacionada ao modelo, associado ao tipo e tamanho de cada campo. O default é obtido diretamente do banco de dados.

$validationstatus

Array. O array $validationstatus contém a situação de validação de cada campo do modelo. O método Validate() popula este array com a situação de cada um dos campos, (true/false) de acordo com as regras de validação de cada um.

 

Métodos

LoadById($id)

Carrega os dados do registro cuja chave primária é $id no array $data do modelo.

Save()

Salva os dados do modelo no banco. Antes executa a função ValidateFields() para garantir que os dados são válidos. Se a chave primária no modelo estiver vazia, ele cria um novo registro. Se estiver preenchida, ele atualiza os dados do registro que contém este id.

DeleteById($id)

Remove da tabela o registro com o id $id. Bem simples. O único perigo aqui é se a gente não configurar corretamente a tabela para lidar com o efeito cascata, ou seja, se a gente deixar alguém apagar um registro que é referenciado por outros registros. Por exemplo, se eu apago um post que tem vários comentários relacionados, precisamos remover todos eles, certo? A boa notícia, pra quem ainda não sabe, é que o banco cuida disso sozinho pra nós.

ValidateFields()

Valida cada um dos campos de acordo com suas regras de validação. Como a classe Model é uma classe genérica, ou melhor dizendo, abstrata, vamos fazer aqui uma validação também genérica, de acordo com as características dos campos da tabela. Assim, vamos validar, por exemplo, se um determinado campo é texto, e se seu tamanho está dentro do tamanho estipulado na descrição da tabela. Para validações mais específicas, vamos reescrever a função ValidateFields() em cada um dos nossos modelos.

Reparem, caros leitores, que nosso objetivo aqui é clareza e simplicidade. Poderiamos ter chamado a função LoadById simplesmente de Load; Mas a idéia é deixar o uso da função realmente claro; Percebam que já na função Save isso já não é necessário pois vamos salvar o estado do modelo no banco, sem a necessidade de nenhum campo específico estar definido. Para salvar um novo registro vamos simplesmente salvar um modelo que tenha sua variável $id vazia.

Uma diferença bastante grande desta proposta em relação ao Cake é a divisão de trabalho: como o Cake usa o pattern ActiveRecord, tem muita coisa dentro da classe Model. Aqui nós estamos dividindo este trabalho com a classe ModelCollection, que irá fazer todo o trabalho de banco de dados quando estivermos lidando com grupos de registros, ou coleções.

That's all, Folks! Mandem seus comentários, dúvidas e xingamentos e até a próxima!

 

18 Comentários:

[Elomar]  Parabéns pelos textos, e não demore tanto com o próximo!  [REPLY]

[danilo]  Valeu Elomar! Grande Abraço!   [REPLY]

[ms*]  Ainda bem que escreveu! Achei que ia perder completamente o moral com a comunidade :-) beijinho, lindo.  [REPLY]

[danilo]  Não posso resistir a um pedido desses... você vai ser canonizada pela comunidade digitalminds, dona ms*! beijo, minha linda.

[LuRsT]  Está a ficar um espectáculo essa série! Quero ver como vamos juntar as classes todas e meter o MVC para melhorar a programação na prática!  [REPLY]

[danilo]  Valeu LuRsT!!! A gente chega lá, agora tá quase!  [REPLY]

[Emiliano ESB]  Coisa fina, hein?  [REPLY]

[danilo]  Valeu Emiliano! Grande abraço!  [REPLY]

[LuRsT]  Ae danilo surgiu uma duvida. Quer dizer que nos usando essa classe model tão dinamica tendo ela feita e pronta, nao so podemos usar no projecto que estamos fazendo como em todos os outros estou certo? A classe model se for bem feita pode ser usada para qualquer coisa?  [REPLY]

[danilo]  Exatamente, meu caro Lurst! Mais que isso: poderemos estendê-la e usá-la para quaisquer dados que quisermos!  [REPLY]

[LuRsT]  Maravilhoso, dai o nome voçê chamar de quase-framework. Eu ainda nao estou entendendo como é que a gente pega num array de qualquer tipo de dados e transforma em algo legivel. Voçê recomenda algum site ou livre que fale sobre MVC assim tão bem como voçê? Abraço  [REPLY]

[Rodrigo Aramburu]  Cara como fica no caso de um objetos contiver um array de objetos como faria para gravar e ler este array em uma tabela separada?  [LINK]  [REPLY]

[danilo]  Olá Rodrigo! Esse caso é chamado de relação "has many" ou "contém itens". A gente chega lá se tiver tempo, mas pra agilizar vc vai precisar saber quais itens um modelo pode conter e fazer automaticamente as operações nesses modelos... Relacionamentos são uma coisa chata de se fazer com objetos, mas tudo já foi resolvido por aí hehehe... abraço!  [REPLY]

[Junio]  Danilo Medeiros, como será a visibilidade, public, protected e private das classes e atributos?  [REPLY]

[danilo]  Oi Junio, na teoria, atributos devem ser sempre privados, e seus valores devem ser acessados/alterados sempre por métodos. Abraço grande!  [REPLY]

[Junio]  Muito obrigado Danilo,sua explicação foi simples e muito valiosa para meu entendimento.Paz e saúde para ti!  [REPLY]

[Guilherme Ventura]  Olá, Acompanho toda a série e queria agradecer, após ler 50 apostilas ensinando orientação a objetos, eu finalmente entendi em 3 Posts ,rs. eu acompanhei a série do MVC, mais me surgiu uma dúvida aparentemente banal : Por onde eu devo começar pra exibir os dados? por exemplo. numa pagina qualquer, qual classe eu devo referenciar para que tudo comece? A view, o controller ou o model ?  [REPLY]

[ivan]  cara, poarabéns vc escreve muito bem. espero que continue a escrever sobre diversos outros assuntos  [REPLY]

2007-09-24 08:23:49
tags: 

The Analog Kid

Nasceu. Quando estiver querendo dar uma pausa, passa lá.
2007-09-13 15:21:32

O Poder da Wikipedia

Eu ainda fico chocado com a quantidade de conteúdo maluco que é gerado na wikipedia.
 
"Natasha, uma cantora de rock, vendeu sua alma ao terrível Conde Vladymir Polanski, chefe dos vampiros, para brilhar na carreira. Mas ele descobre que em encarnações passadas ela era Eugênia, o seu amor, que preferiu ficar com Rocha, a outra vida do Capitão Jonas."
 
Agora "Calada noite preta" não sai da minha cabeça. Maldição.
 
http://pt.wikipedia.org/wiki/Vamp_%28telenovela%29

 

P.S. "O Zen..." vai voltar... prometo... aguentem firme! Grande abraço! 

4 Comentários:

[Ian]  Os artigos científicos são muito bons =)  [REPLY]

[danilo]  Com certeza Ian! Tem de tudo nesse negócio! Grande abraço!  [REPLY]

[Prof. Luís Eduardo]  Sou leitor a bantante tempo de seu "Zen" e fiz uma recomendação de seu blog em meu site. Veja lá se ficou de seu agrado, um abraço  [LINK]  [REPLY]

[danilo]  Valeu Luís! Já comentei lá no Tecnoclasta! Grande abraço!  [REPLY]

2007-08-30 15:17:25
tags: 

Plumage: travesseiros e edredons, em pluma e pena de ganso, com frete grátis

Um grande jabá pra minha mãe querida: compre este mês direto no site da Plumage e receba os maravilhosos edredons e travesseiros na sua casa sem pagar o frete! É só acessar o endereço http://www.plumage.com.br e se preparar pra ter as melhores noites de sono da sua vida!

Quem puder ajudar a divulgar a promoção, dona Sônia agradece!

2007-08-27 10:44:34
tags: 

Blogcamp: Valeu!

Um abraço enorme para os amigos blogcampers! As conversas do sábado foram muito boas, agradeço a todos que deram suas opiniões e inputs para o novo Wasabi, e não vou me esquecer nunca do chope que tomamos no Pinheirinho! (chope este que, por sinal, me impediu de ir no Domingo). Abraços especiais para a Lúcia e o Manoel, nossos mestres de cerimônia, para a Roberta e todos que participaram da discussão comigo na manhã de sábado, para o Juliano pela ótima conversa sobre música e pelo livro. Agradeço também ao Casé, que gentilmente cedeu o maravilhoso espaço da Casa Gafanhoto para nosso evento.

Acho que podemos ainda melhorar na questão formato... o esquema BarCamp é livre, claro, mas acho que a gente precisa preparar mais - tá lá nas regras do barcamp: não tem agenda definida, mas que todos tem que apresentar coisas interessantes pra que todo mundo possa aprender, trocar experiências... Fiquei pensando como seria bom se o Juliano fizesse um resumo de seu livro pra nós, se o Fábio falasse sobre o que aprendeu com o Camiseteria, se o Merigo nos contasse como está monetizando o #9, se a Lúcia nos falasse um pouco do Desabafo de Mãe, o Jeff sobre o Second Life e publicidade... enfim, acho que tivemos muita atitude, mas podíamos ter mais conteúdo.

Não posso também deixar de falar que um dos projetores da Casa Gafanhoto foi furtado e estamos organizando uma vaquinha pra ajudar a repor. Quem puder ajudar e contribuir com qualquer quantia estará ajudando um cara que merece.

Mas valeu. De verdade. Grande abraço pra todos! Veja a cobertura completa aqui.

6 Comentários:

[Roberta]  Aah, agora entendi por que não te vi no domingo. Bom te ver de novo :) Bjs  [REPLY]

[danilo]  Ô Roberta, pois é... a velhice é um problema! Bom te ver de novo também, vê se vem quando rolar aqui! Abraço!  [REPLY]

[Lucia Freitas]  Agora entendi a tua falta. Valeu! A gente se vê no Rio então... quando mesmo? :D bj  [REPLY]

[danilo]  OOO Lúcia! Então, deve ser em Outubro, mas ainda não tá fechado não. Outubro é logo alí, programe-se!

[Tonobohn]  BarCamp Rio eu vou hein! Vai ser uma desculpa pra poder fazer uma visitinha por aí! Abraço meu querido! Prazer revê-lo!  [REPLY]

[danilo]  ôpa demorou Tonobohn ! A Lúcia e a Roberta já confirmaram! Abração  [REPLY]

2007-08-24 06:55:12
tags: 

Novo Wasabi: novidades no Blogcamp Sampa

Amigos,

Tenho estado um pouco sumido por aqui, mas garanto que é por um bom motivo, ou melhor, por vários bons motivos.

Um destes motivos é o Wasabi. Temos muitas novidades neste front, e gostaria muito de poder conversar sobre elas no blogcamp deste fim de semana.

Desde que lançamos o primeiro beta do Wasabi muita coisa aconteceu nessa nossa blogosfera tupiniquim. Naquela época, olhamos para nossa bola de cristal e vimos um futuro no qual acompanharíamos a vida dos nossos amigos simplesmente seguindo sua produção de conteúdo: seus blogs, fotologs, listas de links, podcasts e outros conteúdos, atualizados frequentemente, formariam um rico mosaico de tudo o que acontece com estas pessoas. Trata-se de um conceito difícil de implementar em forma de software, mas se você é um dos beta-testers do Wasabi sabe que nós temos alguma coisa interessante nesse sentido. Sabemos que a coisa ainda está incompleta: como a gente sempre fez o Wasabi como uma experiência, no tempo livre que temos, nunca conseguimos terminá-lo, de fato. Nosso site, diferentemente de alguns outros eternos betas que existem por aí, é beta pq realmente ainda não está pronto. :-)

Um dos motivos pelos quais nunca saímos ativamente atrás de investidores ou mesmo angels é porque não tínhamos um modelo de negócio fechado. Apesar de ser original em vários aspectos, a primeira versão de nosso querido agregador social não oferecia nenhum diferencial que nos deixasse seguros pra montar um business case que fizesse sentido pra nós e para os investidores. Assim, mantivemos o site em beta e fomos novamente olhar na nossa bola de cristal.

O que vimos desta vez foi bem diferente. Se hoje já somos quase 2 milhões de blogueiros só no Brasil, um número que cresce exponencialmente a cada ano, percebemos que no futuro vamos acompanhar não só a vida dos nossos amigos, mas tudo o que acontece no mundo, simplesmente seguindo esta produção de conteúdo. De fato, seguir a produção de conteúdo de todos estes blogs, fotologs, podcasts e sites de links (pra não falar na produção de vídeos e outras coisas que nem imaginamos ainda) é tão interessante que vai nos fazer
conhecer gente nova, fazer novos amigos... E aí percebemos que o conceito fundamental do Wasabi precisava mudar.

Como aumentar ainda mais o alcance desse conteúdo? Como potencializar a sinergia entre os conteúdos gerados por diferentes pessoas? Como fazer que o consumidor encontre conteúdo relevante em blogs que ele ainda não descobriu? E, fundamentalmente, como recompensar quem cria ou seleciona conteúdo de
qualidade?

Bem, amigos, acho que encontramos a resposta para essas perguntas, e encontramos também um modelo de negócios que parece muito interessante, e que você, blogueiro, é quem vai ganhar mais com ele.

No blogcamp que rola neste sábado e domingo, gostaria muito de conversar com todos os participantes sobre essa história, e, mais importante que tudo, saber o que vocês acham, o que gostam, o que não gostam, e como podemos fazer tudo isso realmente acontecer. De nossa parte, já estamos ativamente buscando investidores e desenvolvendo a nova versão.

Até lá!

4 Comentários:

[Avi Alkalay]  WTF é Wasabi? Entrei lá e só tem login.  [REPLY]

[tigo]  Owww Danilo, estou mesmo aguardando inovações no Wasabi.  [REPLY]

[Sergio Lima]  Desta vez vou acompanhar pelso feeds :-( Mas torcendo pra que as conversações sejam ótimas! Sucesso ao wasabi!  [REPLY]

[danilo]  Ô Serjão, você fez falta! Abraço grande e obrigado!  [REPLY]

2007-07-07 07:47:03

São Paulo precisa de doações de sangue

Minha amiga de Barcamp Lúcia Freitas manda um aviso muito importante:

"Desta vez o assunto é sério. A Secretaria de Saúde avisa: a reserva de sangue nos bancos só dá conta do recado até o dia 13, próxima sexta. A razão é simples: as doações caíram, já em junho, de 7 mil para 4.200 - mais de 50%.
Segundo o release da Secretaria é o normal - faz frio, o povo doa menos. Meu convite? Vamos usar os blogs para fazer uma corrente de doação. O assunto grave é aqui em São Paulo, mas tenho certeza de que os bancos de sangue dos outros estados também ficarão gratos com todas as doações que aparecerem."

Doe. Divulgue. Ajude.

1 Comentário:

[Daniel Passos]  O RJ tambem principalmente com o inicio do PAM  [REPLY]

2007-07-03 04:58:16

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

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

Olá pessoal. Obrigado por todos os comentários e emails! Estou tendo um prazer enorme escrevendo essa série, e fico ainda mais feliz quando vejo que realmente tem gente curtindo.

Mas vamos ao que realmente interessa. No nosso último encontro expliquei que existem diferentes formas, ou patterns, para lidar com buscas e coleções de objetos, mas que eu ainda não estava satisfeito com aquilo que conheço. Como já disse em outras oportunidades, aprendi o pouco que sei de PHP nos becos escuros da internet, entre latões de lixo e scripts procedurais escritos por sabe-se lá quem. Não tenho, portanto, nenhuma pretensão de conhecer todos os sutras da programação orientada a objetos. Mas, outro dia, eu tive uma idéia que achei interessante, nada original, mas um pouco diferente das duas implementações que mostrei pra vocês.

Um dos design patterns mais interessantes (e, para mim, mais difíceis de entender) que conheço chama-se Iterator. Devo ter lido as definições e exemplos umas 1000 vezes sem entender direito como usar essa coisa. Pra quem vem de um passado procedural, especialmente usando uma linguagem como o PHP que lida muito bem com arrays, é muito difícil entender o benefício de usar os tais iterators.

Os iterators, juntamente com um outro pattern chamado Collection, vão formar a base do nosso novo desenho. O que estou pensando é relativamente simples: assim como temos a classe base Model, para operações com modelos, quero criar uma classe ModelCollection, que vai cuidar das operações com coleções de modelos. Dessa forma, temos um paralelo interessante: assim como podemos carregar as informações do modelo fazendo $model->load e assim por diante, poderemos carregar as informações de coleções fazendo $modelcollection->load.

O que eu gosto nesse desenho é que tudo fica claramente definido: um $model é sempre um objeto, enquanto que os $modelcollections são sempre coleções de objetos. Uma função de um $model jamais vai retornar uma coleção de objetos; uma $modelcollection jamais vai retornar um objeto (caso uma busca retorne apenas um resultado, ainda assim será uma coleção com apenas um objeto).

Parêntesis: uma das coisas que me deixa maluco no PHP é o fato de você poder misturar absolutamente tudo - uma mesma função pode retornar uma string, um array, um objeto... É o que os estudiosos chamam de loosely typed language, uma linguagem que não exige a definição dos dados usados pelas variáveis. Claro que essa característica pode ser usada para o bem: muitas implementações interessantes usam essa característica para flexibilizar e agilizar o desenvolvimento. Mas com o tempo, depois de passar anos da minha vida tentando decifrar códigos de scripts PHP por aí, eu afirmo categoricamente: tentar entender um script ou classe de alguma outra pessoa escrita em uma linguagem loosely typed é muito mais difícil.

Mas por que esse parêntesis tão grande? Porque no desenho que estou propondo vamos sempre lidar com objetos; Porque as Collections nos oferecem possibilidades muito, mas muito interessantes mesmo pra trabalhar com objetos e coleções de classes diferentes de forma transparente.

Não entendeu? Bom, vamos aos nossos exemplos então. Imagine que temos dois modelos completamente diferentes. Tipo "Post" e "Carro". Logicamente, dentro do nosso desenho, vamos ter os modelos $post e $carro, além das collections $postcollection e $carrocollection. Onde queremos chegar? Bem, como tanto a classe PostCollection quanto a classe CarroCollection são "filhas" da classe ModelCollection temos a certeza que estas subclasses implementam as mesmas funções. E por que isso é lindo? Porque eu posso agora implementar, por exemplo, a classe HtmlHelper, cuja função buildTable aceita qualquer ModelCollection e imprime uma tabela html. Pra usar, basta fazer $htmlhelper>buildTable($postcollection) ou $htmlhelper->buildTable($carrocollection).

Sacaram a beleza? Esse é só um exemplo do que podemos fazer com as collections e os iterators, mas o importante é ver que esse design faz com que qualquer coleção se comporte de forma igual, pra que a gente possa implementar coisas genéricas que funcionam pra qualquer uma delas. A coisa que imediatamente vêm à mente é que essa classe ModelCollection vai ter um método genérico pra fazer paginação, um pra fazer ordenação dos dados, e assim por diante.

Quando nossas classes estiverem prontas, olha só o que vamos precisar fazer pra imprimir uma tabela html:

(controller)

/* A função ModelController::loadPage() carrega a página indicada no $_GET['page'] e no $_GET['pagesize']

já na ordem indicada por $_GET['orderby'] e $_GET['direction'] */

$this->postcollection->loadPage();

(view)

$htmlhelper->buildTable($postcollection); // imprime a tabela

$htmlhelper->createPreviousPageLink($postcollection); //cria o link para a próxima página

$htmlhelper->createNextPageLink($postcollection); //cria o link para a próxima página

E acabou. Não é legal isso?

Até a próxima!

16 Comentários:

[toninho]  ôpa. só agradecendo a iniciativa. tá me salvando e incentivando  [REPLY]

[danilo]  Valeu Toninho!  [REPLY]

[Thiago]  Isso ai Danilão ! Só não deixe agente esfriar !!! Quando vamos começar a codar ? Grande abraços !!!  [REPLY]

[danilo]  Oi Thiago! Olha, segura a onda, ainda demora um pouco, temos que definir muita coisa ainda! Mas esse é o caminho: pensar bastante antes de começar a codar, pra ter menos dores de cabeça depois! hehehe Grande Abraço!  [REPLY]

[Fabiano M]  É... bye bye php de rua. Muito bom, muito bom mesmo!!!   [REPLY]

[danilo]  Valeu Fabiano! Grande abraço.  [REPLY]

[Murilo Adriano]  Olá Danilo, primeiramente quero te parabenizar pelos artigos série que realmente estão ficando bons. E te dizer que estou fazendo um sistema para um site de anúncios de empresas com PHPOOP5 (saindo da marginalidade do "php de rua") e vi no parte 16 que não era só eu quem tinha a seguinte dúvida: de quem é a responsabilidade de buscar? (o $tenista->findAll() lembra?). No meu caso a classe é uma empresa e eu simplesmente não concordava na idéia de uma empresa buscar outras empresas(e foi procurando uma solução cabível que achei seu blog, aproveitei e li a série toda). A solução que...  [REPLY]

[danilo]  Oi Murilo! Pois é exatamente isso: nesse desenho você teria uma EmpresaCollection que colecionaria EmpresaModelos. Eu só não modelaria usando EmpresaBusca: colocaria uma função "load" na colecao, assim como já temos no Modelo. Você faria, então, EmpresaCollection->load() pra buscar no banco, assim como vc já faz EmpresaModelo->load(). Entendeu? Grande Abraço!  [REPLY]

[danilo]  É um problema de semantica chato esse! É por isso que eu prefiro usar "load", ou "carregar", pois estamos "preenchendo" o modelo com dados... então, talvez ficasse melhor usar EmpresaCollection->loadByCondition("NumeroEmpregados >100") e EmpresaModelo->loadById(35). Aqui estamos dizendo "Carregue uma coleção com todas as empresas cujo numero de empregados seja maior que 100". Deu pra entender? Abraço grande.   [REPLY]

[Murilo Adriano]  Olá novamente Danilo. Obrigado pela resposta tão rápida! Olhe só, ontem eu tinha comentado apenas imaginando como seria a implementação. Após comentar eu fui modelar o UML para ter uma idéia de como as classes irão ficar dispostas. Resultado: bani o EmpresaBusca e implementei as buscas no EmpresaModelo mesmo. Construí também uma classe chamada EmpresaLista (que é mais ou menos uma collection de empresas com um modelo de iterator bastante simples). Olhe só minha idéia: $modelo = new EmpresaModelo; $lista = $modelo->buscarPorCategoria(5); //Retorna um objeto do tipo EmpresaLista com...  [REPLY]

[danilo]  Oi Murilo, então esse é exatamente o padrão ActiveRecord... Minha questão com ele é que o modelo pode retornar uma lista de objetos ou um objeto... Mas é uma ótima implementação, se faz sentido pra você vá em frente! Vou fazer um novo post sobre isso pra tentar levar essa discussão pra frente. Abraço grande e obrigado!  [REPLY]

[danilo]  Acho que a diferença que estou propondo é que as funções nunca retornam objetos, só TRUE or FALSE. A função $model->loadById(5) retornaria TRUE se os dados do registro com id 5 fossem carregados corretamente no objeto. Assim sempre estamos operando no próprio objeto, e não passando objetos por aí... Sacou?  [REPLY]

[Murilo Adriano]  Então, será sempre uma lista. Mesmo se for com 1 ou zero elementos será uma lista. Assinei seu feed e vou aguardar ansiosamente os próximos posts. Valeu.  [REPLY]

[danilo]  Entendo, Murilo. Este realmente é o padrão do Active Record, talvez com a diferença de retornar, no caso do Cake, um array, e não um objeto da classe lista. O que não gosto é justamente o fato de vc pedir para o modelo uma lista. Vou escrever mais sobre isso. Grande Abraço e boa sorte!  [REPLY]

[Junio]  Legal?-Excelente a idéia, principalmente sua forma didática de transmitir conhecimento.Paz e saúde para ti!  [REPLY]

[Friv Games]  thanks all for sharing  [LINK]  [REPLY]

2007-06-05 04:32:35

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

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

Olá amigos, estamos de volta. Semana de muitas emoções pra quem gosta de Tênis: Roland Garros é sempre uma festa. Este seu humilde autor confessa que, em sua tenra juventude, chegou a disputar alguns torneios; Lembro-me claramente de ganhar uma cesta com catchup, mostarda, mini-pepinos, azeitonas e mais alguns outros enlatados da empresa patrocinadora de um dos torneios de que participei. Minha melhor colocação, 3o colocado. Pensando bem, acho que fiz bem em não seguir a carreira.

Mas, deixando Jankovics, Vaidisovas, Sharapovas e Ivanovics de lado por alguns momentos, quero voltar nossa atenção novamente para os modelos do MVC. Muito bem amigos, hoje vamos tentar definir o que todos os nossos modelos devem minimamente fazer. Nosso objetivo hoje é listar os métodos da nossa classe Model, a classe base para todos os modelos que criarmos. Não tenho a pretensão de fazer um estudo teórico detalhado; dentro de nossa filosofia PHP de Rua® o que estamos buscando é somente o básico, o essencial.

Então, caros amigos, quais seriam estas funções essenciais, compartilhadas por todos os modelos que vamos criar? Lembrando nossas conversas anteriores, o modelo é um ajudante, uma classe que só existe para ler e gravar informações em nosso banco de dados, e sua estrutura de dados será sempre mapeada à estrutura de uma tabela que existe no BD.

Por exemplo, se criarmos um modelo Tenista, que possua as variáveis $id$nome$ranking, é certo que teremos uma tabela que guardará esta informação, que pra facilitar (nomes têm poder, lembrem-se disso) chamaremos de Tenistas. Essa tabela terá, minimamente, os campos id, nome e ranking. Sacou?

Estamos, de fato, mapeando uma classe à uma tabela, e instâncias da classe a registros da tabela. Essa técnica é chamada de ORM, Object-Relational Mapping. A coisa é mais interessante ainda: como estamos falando de OOP, em algum de nossos métodos vamos bolar um jeito de fazer esse mapeamento da forma mais simples e genérica possível, pra que não tenhamos que criar queries sql específicas para cada novo modelo que criamos.

Vejam a beleza dessa solução, caros leitores! Quando terminarmos a classe Model, qualquer novo objeto de uma classe que a estenda poderá ser salvo ou lido direto do banco sem precisar que nós façamos uma query específica!

Sendo assim, creio que já ficou bastante claro que precisamos das funções save() e load() em nosso modelo-base. A gente não precisa gastar muitos neurônios pra perceber que também precisamos da função delete() além da função __construct() que todos as classes já nos oferecem para criar novos objetos.

Nesse ponto começa uma saudável polêmica: onde devem ficar as funções para buscar objetos? Se eu quiser pegar todas as tenistas que estão no banco, pra quem eu devo pedir? Em alguns frameworks MVC, como o CakePHP, estas funções ficam na classe Model mesmo. Então vocë encontra funções como findAll(), findById(), findByName() e coisas assim, dentro da classe Model.

Pra ser muito sincero, eu acho meio esquisito pedir pra uma tenista buscar as outras tenistas. É assim que fica no CakePHP:

$tenista = new Tenista();

$todasastenistas = $tenista->findAll();

Cara, eu acho isso muito esquisito. A semantica da coisa, sabe? Acho que é um pouco de preciosismo, eu sei. Adoro o Cake, estou realmente impressionado com sua facilidade de uso, mas acho o design da classe model um pouco confusa.

Outros frameworks e ORMs fazem diferente. Criam uma classe só pra fazer isso. Um gnomo, lembram-se? Então, o cara faz o seguinte:

$gnomo = new DbManager();

$todasastenistas = $gnomo->findAll('tenista');

 Nesse caso, a classe DbManager tem todos os tais métodos pra retornar arrays buscados no banco. Hm. Acho um pouco melhor, mas ainda acho estranho não termos uma classe mais esperta, que possamos estender para criar comportamentos diferentes caso a gente precise. A resposta está próxima, caros amigos. Mas não posso perder a chance de continuar no próximo capítulo, não é mesmo?

Até a próxima.

16 Comentários:

[Walter]  O primeiro padrão é o Active Record, enquanto o segundo é o DataMapper(?). Confesso que a princípio a semântica do primeiro parece meio esquisita mesmo. Ainda não sei por qual optar, embora esteja namorando o SQL Alchemy (Python)  [REPLY]

[Emiliano ESB]  Maravilha!!! Também partilho da mesma opinião   [REPLY]

[Renan Reis]  Os artigos estão ótimos, finalmente alguém resolveu escrever sobre código de qualidade com PHP. Parabéns pela série!  [REPLY]

[Renato Elias]  Engraçado você postar sobre tenista, roland garros, bem quando eu acabei de terminar um projeto de scout, veja se vc gosta: http://www.datatennis.com foi feito em phpontrax, bem parecido com o cake que você cita, abraços  [REPLY]

[Thiago]  A série realmente está muito boa, pena é o grande intervalo entre os posts :( Grandes abraços e sucesso ... você merece !!  [REPLY]

[Filipe Boldo]  Ótima epopéia cavaleiresca, com direito a gnome e tudo (rs). Está sendo muito agradável e proveitoso ler esses artigos, parabéns mesmo! Abraço, até mais!  [REPLY]

[Fabiano M.]  Muito bom, continuo acompanhando. Eu estou iniciando no mundo framework com cakePHP, mais jah olhei outros. Falando sobre OOP, na parte sobre interface, kara eu acho muito confuso ainda interfaces, tanta volta para um resultado. Estou ainda meio perdido em compreender interface. Mas agradeço por poder aprender mais por aqui no seu blog. Valeu!!!  [REPLY]

[Pagelkopf]  Parabens pela série, lendo ela eu descobri porque meu ultimo projeto em PHP não funcionou, eu sentei e comecei a digitar sem o minimo de planejamento. Ta sendo realmente muito proveitosos seus artigo. No final vai dar até pra fazer um livro.  [REPLY]

[Fabiano M.]  Tenho acompanhado o blog DigitalMinds, muito bem explicado os conceitos. Moro no Rio, como até hoje não encontrei nenhum curso PHP bom, tenho aprendido na web muito do que sei hoje. Iniciando em OOP, DigitalMinds sem dúvidas é um dos melhores conteúdos online. Como estamos no mundo dos 64Bits, bem q a 32Bits poderia ser 32²Bits. :) Valeu, abraço!  [REPLY]

[LuRsT]  Estou a adorar sua serie cara, continue assim, graças a ela eu começei a estudar OOP em php. Abraço cá de Portugal ;)  [REPLY]

[danilo]  Valeu Walter! Abraço grande!  [REPLY]

[Luiz]  Opa, to ansioso para continuar a aprender! Cadê o resto!? hehe, ok, ok, sei que o tempo é curto! Obrigado por gastar um pouco compartilhando conhecimento! Abraços.  [REPLY]

[danilo]  Valeu Luis! O próximo artigo já tá quase pronto! Aguarde só mais um pouco! hehehe Grande abraço.  [REPLY]

[danilo]  Um grande abraço pra os gajos daí Lurst!  [REPLY]

[danilo]  Fabiano, interface é um contrato. Se uma classe utiliza uma determinada interface, ela é obrigada a ter aquelas funcões. E isso é muito, muito importante, pq se vc sabe que uma classe implementa uma determinada interface, você já sabe do que ela é capaz sem precisar saber como ela faz. Faz sentido? Grande abraço!

[Fabiano]  Oq houve com os comentários???   [REPLY]

2007-05-02 05:25:23

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

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

Olá meus caros. De volta. "Que você viva em tempos interessantes". Esta antiga maldição chinesa (!?) explica muito bem a sensação que toma conta deste seu humilde autor. Muito a fazer, muito a compreender, pouco tempo. Desculpas à parte, retorno à esta série para falar mais um pouco sobre Exceptions, um conceito fundamental que talvez ajude alguns de vocês a poupar um tanto desse tão precioso tempo; afinal, como bem disse Benjamin Franklin, o tempo perdido nunca mais será encontrado.

Muito bem, senhores, o que faz nossas Exceptions tão especiais? Para entender, precisamos pensar na forma como gerenciamos erros em nossas aplicações. Ou melhor, precisamos pensar na forma como lidamos com erros em nossas vidas. Talvez isso complique as coisas, mas falar sobre a vida sempre é mais interessante, não?

Joãozinho trabalha numa fábrica de automóveis. (é um exemplo, ok? Não quero entrar em discussões morais sobre trabalho infantil, capitalismo, revolução industrial, etc e tal. Tudo bem, é um exemplo estúpido. Podemos ir em frente?) Joãozinho aperta parafusos na linha de montagem, e sua supervisora é a Mariazinha. O chefe da Mariazinha é o Aristides, que fica lá em cima no escritório.

Bom, você sabe que numa fábrica todo tipo de problema pode acontecer. Alguém pode esquecer de mandar o parafuso para o Joãozinho, o parafuso que foi mandado pode estar com defeito, o próprio Joãozinho pode vacilar e não apertar o parafuso... Sabe lá o que pode acontecer. Diante desse cenário, como você faz para gerenciar todos os erros que podem acontecer? Dá uma lista de IFs infinita para o Joãozinho para que ele mesmo resolva tudo? "Se o parafuso estiver com defeito, corra até a sala do Aristides e aperte o botão para parar as máquinas". "Se você dormir no ponto e não apertar o parafuso, corra até a sala do Aristides e aperte o botão para parar as máquinas", e assim por diante? Hmm... não sei se vocês estão entendendo, mas já está dando preguiça só de pensar em fazer essa lista. E a preguiça, amigos, é o nosso sentido-aranha, é nosso superpoder psiônico que avisa quando alguma coisa está esquisita no ar. Imagina se a Mariazinha tiver 50 funcionários sob sua supervisão, vai ter gente correndo pra tudo o que é lado, a sala do Aristides vai ficar totalmente destruída, e produção que é bom nada.

Apresento-lhes, então, as Exceptions, e seus companheiros inseparáveis Try, Catch e Throw. Vamos olhar para o problema acima de um outro ângulo. Imagine se a gente pudesse dizer o seguinte pro pessoal da fábrica:

Olha, Joãozinho, você vai tentar apertar o parafuso. Qualquer problema que você tiver, escreve num papel, amassa até virar uma bola e arremessa pra Mariazinha. A Mariazinha pega a bola, e se não for um problema que ela saiba resolver, amassa de novo e arremessa pro Aristides. Se ele também não souber resolver, a gente para a linha de produção na hora.

Tentar... Pegar... Arremessar... Vocês... sacaram? (se você viu Warriors, na versão legendada, está rolando no chão de rir nesse momento). [Agora relendo esse artigo me parece claro que o criador deste conceito gostava muito de baseball, ou cricket] Se vocês ainda não sacaram, vamos escrever um pouco de (pseudo)código:

/*
* Created on 02/05/2007
*
*/

class Apertador {

    function apertarParafuso(){

        echo "parafuso apertado!";

    }

    function oopa($descricao){

        echo "Apertador: oopa! Deu pau! Segura aí supervisor!";
        throw new Exception($descricao); // amassa e joga a bolinha pra cima!

    }

}



class Supervisor{

    function mandaApertar(){

        try {

            $joaozinho = new Apertador();

            $joaozinho->apertarParafuso();

            $joaozinho->oopa("Parafuso com defeito");

        }

        catch (Exception $e){
            echo "Supervisor: xi! Exception! Não sei o que fazer! Toma aí chefe!";
            throw $e; // peguei a bolinha, mas não sei o que fazer com ela... manda pra cima!

        }

    }

}



class Chefe{

    function vamosTrabalhar(){

        try {

        $mariazinha = new Supervisor();

        $mariazinha->mandaApertar();

        } catch (Exception $e) {
            
            echo "Chefe: Para tudo! Quero saber o que aconteceu aqui!"
		echo $e;
            die("Parando as máquinas!");

        }

    }

}


// Muito bem, agora a gente contrata o Aristides:


$aristides = new Chefe();

$aristides->vamosTrabalhar();

?>

 

Rode esse script e veja o resultado. Que interessante! Basta o Joãozinho mandar o erro pra cima que todos na cadeia (as classes que chamam a classe Apertador, neste caso) recebam aquela Exception, graças ao uso do comando Try. Tudo o que roda dentro de um bloco Try é monitorado, e caso uma Exception seja "jogada" ou "arremessada" pra cima o controle vai para o bloco Catch imediatamente abaixo.

Perceba também que ao gerarmos uma Exception, ela já é criada com um monte de informações importantes automaticamente: em qual arquivo e linha que o erro aconteceu, um Trace completo passando por todo o código até o Catch que "pegou" aquela Exception e muito mais. Para ver um bom resumo, basta mandar imprimir a variável que contém a Exception; mas você também pode acessar as propriedades do objeto separadamente usando métodos como $e->getMessage(), $e->getLine(), $e->getFile() entre outras. Não é bom isso?

Com as exceptions nosso trabalho passa a ser somente colocar os Throws nos locais onde erros acontecem, deixando o tratamento desses erros para classes mais acima na hierarquia. Mesmo que você não trate estas Exceptions com blocos Try/Catch a coisa funciona: você pode deixar a exception subir na hierarquia até chegar ao topo, pois toda exception que chega ao topo sem ser "pega" gera um erro fatal. Então, caros amigos, vocês podem trabalhar inicialmente só colocando throws no código, e, ao final, refinar o tratamento distribuindo blocos try/catch pelas classes da hierarquia. Muito bonito.

Mas tem uma coisa ainda mais bonita. Sim, amigos, a classe Exception pode ser estendida. É uma classe como outra qualquer. Isso quer dizer que no nosso caso você poderia criar a exception DefeitoParafusoException, que já conteria a mensagem de erro e mais outras informações que você necessita sem precisar nunca mais digitar. Exemplo:

 

class DefeitoParafusoException extends Exception {
     function __construct(){
        parent::__construct();
        $this->message = "Defeito no parafuso!";
    } 
} 

 

Sacaram? Agora toda vez que você criar uma nova Exception do tipo DefeitoParafusoException a mensagem já será colocada por default na variável $this->message da Exception em questão! Imagine o que você pode fazer com isso. Mas ainda tem mais. Imagine agora que você não quer parar a produção simplesmente por causa de um parafuso com defeito. Muito bem, então vamos fazer com que os Supervisores comecem a "Pegar" este tipo de Exception para não incomodar o chefe:

 

 class Supervisor{

    function mandaApertar(){

        try {

            $joaozinho = new Apertador();

            $joaozinho->apertarParafuso();

            $joaozinho->oopa("Parafuso com defeito");

        }

        catch (DefeitoParafusoException $e){
            echo "Supervisor: é só um maldito parafusinho, diabos! Continuem!";
        }
        
        catch (Exception $e){
            echo "Supervisor: xi! Exception! Não sei o que fazer! Toma aí chefe!";
            throw $e; // peguei a bolinha, mas não sei o que fazer com ela... manda pra cima!

        }

    }

}

 

pra ver isso funcionando, precisamos alterar a função Apertador::oopa() para mandar uma DefeitoParafusoException:

 

 function oopa(){

        echo "Apertador: oopa! Deu pau! Segura aí supervisor!";
        throw new DefeitoParafusoException(); // não precisa mais da descrição...
} 

 

E pronto. Vocês perceberam que podemos utilizar vários blocos de catch um embaixo do outro? Essa é a beleza desta solução. Podemos começar com um tratamento de erros bem genérico, e depois ir especializando com novas subclasses, sempre lembrando de colocar as subclasses mais específicas, neste caso a DefeitoParafusoException nos blocos anteriores, deixando o catch genérico (Exception $e) por último.

Por hoje é só, pessoal, dúvidas, reclamações, elogios e doações são bem-vindas. Grande abraço a todos.

 

6 Comentários:

[Emiliano ESB]  Dúvidas: N/A; Reclamações: N/A; Elogios: Excepcional trabalho, nobre Danilo; Doação: Opa! qual conta?  [REPLY]

[danilo]  Muito obrigado, Emiliano! Fico emocionado em saber que tem alguém realmente disposto a ajudar! Um dos meus sonhos é transformar essa série em um e-book muito bem feito, acho que só aí me sentiria bem em aceitar sua doação! hehehe Grande Abraço!

[Emiliano ESB]  Cara, tenha certeza de que com a linguagem que utiliza nesta série, você pode sonhar ainda mais alto! Mas um ebook ja é um ótimo próximo passo! :)  [REPLY]

[Fabiano M.]  Muito bom, estou acompanhando desde o início.

[Lucas Vasconcelos]  Diego, a série está fantástica! A metáfora que você usou para exemplificar o uso de exceptions não poderia ser melhor. Parabens!  [REPLY]

[leo]  Mais um post muito bom,, gosto muito do seu trabalho é como ler um livro estilo senhor dos aneis sobre poo... continue assim  [REPLY]

2007-03-27 08:17:10

BarcampSP: valeu

Gostei muito do BarcampSP. A idéia é legal: sair daquele velho esquema tradicional das palestras e conferências, abrindo a participação para todos os presentes. Claro que esse modelo depende das pessoas que estão ali, o que às vezes pode decepcionar uns e outros; Mas eu gostei, e boto fé que a coisa vai continuar crescendo. 

Veja mais sobre o evento aqui e aqui.

7 Comentários:

[Marco Gomes]  Também achei super fera! Foi bom demais trocar idéia com tanta gente fera, tenho certeza que o evento pode crescer muito.  [LINK]  [REPLY]

[Tarcísio Sassara]  agora posso dizer que conheci o cara que fala de gnomos como eles fossem velhos amigos.  [REPLY]

[danilo]  Grande Tarcísio! Prazer conhecer você, cara! Grande Abraço!  [REPLY]

[Sergio Lima]  Que tal um Barcamp -RJ ? Ia ser legal!  [REPLY]

[Mário]  Graaande Danilo! Foi um prazer conhecer você, rapá! Muito sucesso por aí!!  [REPLY]

[danilo]  Valeu Mário! Igualmente, grande abraço!  [REPLY]

[marcelo toscano]  Muito bom mesmo ... principalmente sobre startups .... gostei muito  [REPLY]

2007-03-16 10:11:23

Mais uma jóia da Web 2.0: Gliffy

Gliffy é uma ferramenta web para desenho de diagramas e gráficos de forma colaborativa. Muito interessante. Confira no endereço http://www.gliffy.com.

2 Comentários:

[joaojose]  Muito legal!! Isso vai ser uma grande ferramenta para desenvolvimento! A web esta revlucionando  [REPLY]

[Neto]  Conheço e achei ele bem interessante!  [REPLY]

2007-03-15 03:25:34
tags: 

Encontro vocês no BarCamp Sampa

É isso aí pessoal, já vi que alguns de vocês também vão estar em Sampa no próximo fim-de-semana, então não vamos deixar de nos encontrar! Já fiz algumas sugestões de temas no grupo, tem muita gente boa e assunto pra falar. 

3 Comentários:

[Jean]  a gente se ve la entao... ou nao ja que eu nao faco a menor ideia de como você é! :D  [REPLY]

[Tarcísio Sassara]  Espero que o evento seja construtivo. Nos vemos lá, se isso for possivel!  [REPLY]

[marcelo toscano]  legal você ir agente se vê lá então.  [REPLY]

2007-03-04 03:21:08

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

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

Estamos de volta, caríssimos leitores. Mais uma vez agradeço pelos comentários e emails. No último artigo nós fechamos o conceito de controllers, e vimos alguns exemplos práticos de como usá-los. Nos artigos anteriores, definimos as outras partes do MVC, models e views (ou templates). Tudo isso sem escrever uma só linha de código.

Bem, depois de tanto tempo sem digitar um único if, alguns de vocês começam a manifestar uma patologia cientificamente conhecida como "fome de código", ou "Síndrome da abstinência de programação". Os sintomas são variados: suor nas mãos, digitação de códigos procedurais aleatórios, criação randômica de scripts, e, nos estágios mais avançados da doença, envio de emails e comentários para o site deste autor bradando palavras de ordem "Código! Queremos código!".

Para todos que estão desesperados para colocar a mão na massa, uma pequena história Zen talvez ajude a acalmar o espírito:

"Um monge perguntou a seu mestre:

– Mestre, quanto tempo vai demorar para que eu atinja a iluminação?

O mestre respondeu:

– Dez anos.

O discípulo respondeu, agitado:

– Mas e se eu trabalhar duro, estudar todos os sutras, praticar dez horas por dia, quanto tempo vai demorar?

– Nesse caso, respondeu o mestre, vai levar 20 anos."

Se existe uma coisa que é fundamental em OOP é paciência. É praticamente impossível fazer alguma coisa que funcione bem usando essa filosofia de trabalho simplesmente abrindo o seu editor e digitando código. Paciência, esse é o caminho.

Mas é necessário desenhar TODO o sistema, cada detalhe, cada vírgula? Certamente não. Mas como saber qual é o momento de parar de desenhar e começar a programar de fato? Ah, jovem monge, nós saberemos. Acredite, nós saberemos. Chegará a hora em que não teremos mais dúvidas, que vamos olhar nosso desenho do sistema e vamos dizer "é, acho que agora já dá pra começar". Ao longo dos anos muitas metodologias e processos foram criadas para tentar desvendar este mistério. Mas só o próprio desenvolvedor, em seu íntimo, sabe quando está pronto. Por mais documentação que um sistema já possua, por mais discussões que se tenha, por mais diagramas e casos de uso e o que for, sempre existe o momento da iluminação, quando tudo aquilo a que fomos submetidos simplesmente "clica" e começa a fazer sentido. Todas as nossas questões sobre como o sistema funciona começam a ser respondidas claramente, e não há mais nenhuma pulga atrás de nossas orelhas.

É, talvez essa seja uma boa definição: a hora de começar a programar é a hora em que não encontramos nenhuma pulga atrás de nossas orelhas. E nesse momento, ainda tenho algumas quando penso em nosso Digitalminds Blogging Engine. Por exemplo: Já sabemos quais são as classes principais que vamos usar, e como vamos usá-las. Mas ainda não sabemos quais métodos e variáveis elas vão apresentar. Qual a vantagem de termos as superclasses Model, View e Controller se não encontrarmos métodos e variáveis que efetivamente facilitem nosso trabalho de criar um sistema? Isso, caros leitores, é precisamente o que vamos fazer nos próximos artigos. Mas ainda nesse artigo quero tentar responder a uma outra questão que está na minha cabeça: Será que não precisamos de mais nenhuma classe nessa história toda?

Bom, eu sempre costumo dizer que a preguiça é uma das minhas grandes virtudes; ela já me ajudou a resolver inúmeros problemas e a ganhar muito tempo pra fazer o que realmente importa na vida, ou seja, nada. De qualquer modo, o que quero dizer com isso é que sim, acredito que teremos algumas outras classes nos ajudando a fazer coisas repetitivas ou chatas demais.

A primeira coisa que me vem à cabeça é "o que fazemos se um erro acontecer?". Sim, amigos, erros vão acontecer, e nós precisamos estar prontos para lidar com eles de uma forma civilizada. E quem já escreveu um sistema qualquer em linguagem procedural sabe como é chato fazer tratamento de erros. São tantas possibilidades, tantas combinações de erros, tantos ifs e tantos switches que só os mais corajosos acabam fazendo tratamento de erro de uma forma realmente completa.

Mas os criadores da programação orientada a objeto, em sua infinita sabedoria, olharam para nós mortais com piedade e com o som de mil trombetas bradaram "Que se criem as Exceptions!" E então, o mar turbulento do tratamento de erros se abriu, e o povo programador pôde passar em paz. Os criadores do PHP, em sua razoável e confusa sabedoria, olharam para nós, os loucos que usam essa linguagem idiossincrática, e também bradaram "Que se criem as Exceptions em PHP5!". E em um segundo, tudo o que já foi feito em PHP para tratamento de erros se tornou obsoleto e bizarro.

O conceito de Exception, senhores, é uma das coisas mais impressionantes que já foram criadas. E, como todo conceito mais complexo de OOP, é muito difícil de entender, justamente por ser uma coisa relativamente simples. Entendeu? Certamente não. Então fique ligado e não perca o próximo artigo.

Grande abraço pra todo mundo.

 

11 Comentários:

[ms*]  Legal :-) Quem não programa ainda assim pode levar a lição da paciência...  [REPLY]

[Thiago]  Paciencia .... paciencia ... to louco pra colocar esses gnomos pra trabalhar ... mas ... tenhamos paciencia ...  [REPLY]

[Emiliano ESB]  Malditos Erros!!! Que assim seja Senhor dos Gnomos! 10 anos ta bom pra mim!  [REPLY]

[Cristóferson Bueno]  Opa Danilo, blz? Cara como sempre sua saga Tolkie do programação está ótima, mas em seu mar de conhecimento e algumas palávras rebuscadas você escorregou : ) idiosincrático é com SS rsrs idiossincrático. E sim, PHP é idiossincrático, mas eu gosto :D  [REPLY]

[Cristóferson Bueno]  E como sempre quem atira pedra no telhado dos outros tem o próprio telhado feito de vidro :) eheheh como PHP é uma linguagem portanto, PHP não é idiossincrático e sim idiossincrática mas com SS rsrs... até!  [REPLY]

[danilo]  Valeu pela revisão Cristóferson! Grande abraço!  [REPLY]

[Thiago]  Danilão, não esqueceu dos nossos Gnomos guardados em algum lugar não né ?  [REPLY]

[Filipe]  Pô cara, cadê a parte 15??? É o melhor estudo de OOP que eu já vi! ;-)  [LINK]  [REPLY]

[Filipe]  Pô cara, cadê a parte 15??? É o melhor estudo de OOP que eu já vi! ;-)  [LINK]  [REPLY]

[danilo]  Ô Pessoal, desculpa, é realmente falta de tempo... Mas assim que tiver um tempinho prometo que continua! Grande Abraço a todos!  [REPLY]

[Cyro]  Dude! we are lost... !!!! Cara, cadê a prox parte...??  [REPLY]

2007-02-26 07:06:40

Produção Web: Subverta sua forma de trabalhar com arquivos

Vamos fazer um teste rápido: você montou uma página html muito legal, o css já está fechado, tudo está validando, acessível, etc. e tal. Nesse exato momento, o seu cliente liga e faz um pedido infame:    

— Olha, vamos precisar colocar esses 15 logos na página, mas precisamos que você coloque um em cada parágrafo, ok?

Bom profissional que você é, aceita resoluto a solicitação do cliente e insere uma a uma as imagens na página, transformando a sua linda criação em uma quase-árvore-de-natal feita de símbolos e logotipos que não têm absolutamente nada a ver uns com os outros. Pra que a coisa fique minimamente interessante, você perde mais 45 minutos ajustando o css, mexendo no tamanho das imagens, enfim, fazendo o rejunte e o acabamento.

Considerações estéticas à parte, a página eventualmente fica pronta e você pede a aprovação do cliente. Então, caro amigo, o inesperado acontece:

— Olha, ficou poluído demais. Pode voltar atrás.

O que?! Voltar atrás?

É aqui que entra nosso teste: nessa momento de tensão, caro leitor, o que você faria:

Opção 1: aceita, emburrado, e recomeça de imediato a corrigir o código, removendo uma a uma cada modificação feita. Depois, precisa revisar tudo novamente pra ver ser não ficou nenhum erro, se o layout está igual ao original (mas peraí, eu detonei o original!)

Tempo total: 30 minutos.

Opção 2: aceita, levemente aborrecido, e começa a procurar os arquivos de backup que você havia feito antes de alterar os arquivos. Depois, precisa revisar tudo novamente pra ver se realmente tudo está certo, se aquele “salvar como” foi feito com todas as últimas alterações, se aquela modificação de texto que a menina pediu por telefone estava incluída.

Tempo total: 7 minutos.

Opção 3: aceita, com um sorriso cativante no rosto, e clica com o botão direito do mouse no ítem “TortoiseSVN->Exibir histórico”, escolhe a revisão anterior, e clica com o botão direito novamente “Reverter para essa revisão”. Pronto.

Tempo total: 5 segundos.

Muito bem, meu amigo, minha amiga, o que este teste mostra para nós? Se você respondeu opção 1 ou opção 2 você precisa de um sistema de controle de versão. Fato.

Um sistema de controle de versão guarda diferentes versões de um mesmo documento em um repositório e é capaz de fazer operações com elas. Assim, é possível não só voltar a uma versão anterior de um arquivo instantaneamente, mas também comparar e ver exatamente as diferenças entre duas versões, linha a linha. Mais que isso, duas ou mais pessoas podem trabalhar ao mesmo tempo em um arquivo texto, combinando as partes alteradas quando terminarem. Não é feitiçaria, é tecnologia!

Existem várias soluções para controle de versão disponíveis no mercado. Uma das mais populares é a chamada Subversion, ou simplesmente svn.

O Subversion usa uma interface de linha de comando, mas graças à bondade da comunidade open-source já foi desenvolvida uma interface gráfica para Windows chamada TortoiseSVN que é bem mais fácil de usar. Faça o download da aplicação e da tradução para o português brasileiro no endereço

http://tortoisesvn.net/downloads

Observação: Para quem usa mac, existe o SvnX. É um pouco confuso, mas talvez ajude:

http://www.apple.com/downloads/macosx/development_tools/svnx.html

Depois de instalar o TortoiseSVN (será necessário reiniciar o Windows), você já pode criar seu primeiro repositório:

- crie uma pasta nova para conter seu repositório

- clique com o botão direito do mouse nessa pasta e escolha “TortoiseSVN->Criar repositório aqui”.

Pronto, já temos um repositório. Você não vai trabalhar nessa pasta: os repositórios svn guardam os arquivos num formato proprietário que não pode ser usado; Para trabalhar, é preciso fazer um “checkout” do repositório em outra pasta, ou, em português, “Obter” os arquivos do repositório:

- crie uma pasta para guardar seus arquivos de trabalho;

- clique com o botão direito e escolha “SVN Obter”

- Agora é necessário digitar no campo “URL do Repositório” a url do repositório que você criou. Como trata-se de um folder no sistema de arquivos, use o prefixo file:/// antes do caminho da pasta. Exemplo: file:///C:meurepositorio

- clique OK

Pronto. A partir de agora, os arquivos desta pasta poderão ser “Submetidos” clicando com o botão direito sobre ela e selecionando “TortoiseSVN->Submeter” . Uma janela se abrirá e você vai poder selecionar os arquivos que deseja submeter.

Dica importante: nunca apague ou renomeie um arquivo obtido de um repositório subversion pelo Windows; sempre use o menu do TortoiseSVN. Quando isso acontece, o banco de dados interno do subversion fica perdidinho e você pode ter algumas surpresas.

Para saber mais não deixe de ler o livro “Controle de Versão com Subversion”, que já está parcialmente traduzido para o português no endereço

http://svnbook.red-bean.com/

Nos próximos posts da série, vou mostrar como usar um repositório online do Dreamhost.

Divirtam-se!

11 Comentários:

[Rodrigo Maia]  Muito bom, vou novamente fazer os testes com esse software. A primeira vez que entrei em contato com ele nem sabia do que se tratava. Estou aguardando o uso dos servers da dreamhost. t+  [LINK]  [REPLY]

[Felipe Tonello]  Estou ancioso para saber usar o svn pelo Dreamhost. Parabéns Danilo, continue assim! Abraços  [REPLY]

[Renato]  Cara, muito legal essa dica, já aguardo ansioso o do Dreamhost, abração.  [REPLY]

[Andre]  se você pudesse comentar alguma coisa sobre como o controle de versão trabalha com multi-usuários em rede, seria bastante interessante. valeuz  [REPLY]

[Rozen]  Esse Subversion serve pra qualquer tipo de arquivo, tipo, um arquivo do Flash ou CorelDraw?  [REPLY]

[danilo]  Oi Rozen, funciona sim com todos os tipos de arquivos binários, mas, é claro, não é possível fazer comparações ou diffs. Mas ele guarda as versões dos arquivos sem problemas. Só cuidado porque para cada versão é uma cópia do arquivo... abraço  [REPLY]

[Rozen]  Valeu pela dica! Eu ainda faço controle de versão inteiramente manual, ou seja, fazendo uns backup de vez em quando, e isso sempre gera vacilos. Mas essa tarefa já vinha pedindo pra ser automatizada. Sua dica foi um achado para mim, pois não conhecia essa ferramenta. Vou aprender a usá-la. Agora, arquivos do Corel realmente é melhor fazer o controle manual, senão não vai ter HD que chegue :), mas do Flash e linguagem de programação, vai ser muito últil.  [REPLY]

[Anderson Sá]  Aqui na empresa onde eu trabalho, usamos o "CA Harvest Change Manager". Funciona bem, porém ele é bem conplexo, pois trabalha em rede com muitos acessos simultâneos. Inclusive, ele simula os abientes de "Desenvolvimento", "Aceite", "Piloto" e "Produção". Eu só recomendo se a empresa for grande e houver tempo para personalizá-lo.  [REPLY]

[Felipe Vaz]  Fala Danilo! Grande série! Só uma obs: quando vc versiona arquivos binários no SVN ele só envia as diferenças, sei lá como -- controlo desde IA a layouts de Photoshop com o SVN e os commits são minúsculos. Perfeito pra recuperar aquele layout em que seu estagiário deu um flatten.  [REPLY]

[danilo]  Valeu Felipe, tem razão! Abraço!  [REPLY]

[danilo]  Olá Rozen, o Felipe acaba de me corrigir: ele não duplica os arquivos não, somente as modificações binárias! Grande abraço!  [REPLY]