PABLO.BLOG.BR
Artigos
Eventos
Livros
Slides
Vídeos
Matérias
Sobre
Contato
Pensando em objetos, não em SQL para construir uma aplicação
Como usar ao máximo a Orientação a Objetos para se comunicar com o banco de dados
Frequentemente pessoas me escrevem perguntando como realizar determinada consulta SQL usando o Adianti Framework, na maioria das vezes envolvendo várias tabelas. Imagino que essa dúvida ocorre por que muitas pessoas estão acostumadas a escrever aplicações de negócio fortemente baseadas em SQL e a grande maioria dos exemplos usando o framework são baseados em objetos, atributos, métodos e seus relacionamentos. Apenas um exemplo demonstra como executar uma query manual usando o framework (a seguir, apontarei qual é). O primeiro software que desenvolvi em PHP, o SAGU (Sistema Aberto de Gestão Unificada), lá pelos idos de 2000 era fortemente baseado em instruções SQL. Escrevíamos SQL para inserir, alterar, excluir dados nas tabelas e também para buscar informações de tabelas diferentes para gerar relatórios. Mas nos dias atuais eu considero essa forma de trabalhar extremamente onerosa, visto que uma simples alteração em uma estrutura de uma tabela central implica em ajustes em dezenas de instruções SQL espalhadas pelo código-fonte, que usam aquela tabela. Além disso, o uso em demasia de SQL não privilegia os conceitos básicos da orientação a objetos como o reuso. Se uma regra de negócio pertence à um objeto (Ex: Cálculo do valor da multa de um título), deve pertencer à ele (na forma de um método), e não estar replicada em diversas instruções SQL ao longo do sistema. O Adianti Framework permite realizar queries manuais facilmente, mas devemos evitar usá-las diretamente. Claro que em alguns casos é necessário, mas não para operações básicas (inserção, alteração, exclusão, listagem). O exemplo (http://www.adianti.com.br/framework_files/tutor/index.php?class=SetupTransactionView) demonstra como executar uma query manual usando o framework. Vamos pensar e uma consulta básica para buscar dados de pessoas e de cidades. Ela ficaria mais ou menos como está listado a seguir: ```sql SELECT p.id, p.nome, p.endereco, c.id, c.nome FROM pessoas p, cidades c WHERE p.cidade_id = c.id ``` O Adianti Framework trabalha com o conceito de um Active Record, que é um objeto que se comporta como um registro do banco de dados, oferecendo métodos básicos para persistência (store, load, delete). Além disso, o Adianti Studio Professional (IDE de desenvolvimento), oferece métodos para geração das classes Active Record já com métodos de relacionamento entre objetos (associação, agregação, composição). Assim, ao manipularmos um objeto, além de possuirmos acesso aos métodos básicos, temos acesso a objetos relacionados a este. É desafiador mudar a lógica de raciocínio para sair do SQL e pensar em termos de objetos, mas é possível. Na figura a seguir temos a figura de um diagrama mostrando um modelo de objetos UML construído no Astah. ![Diagrama de classes](http://www.adianti.com.br/forum/pt/post-images/tutor.png "Diagrama de classes") A partir do Adianti Studio Professional, podemos converter este modelo em PHP, onde o Studio irá gerar as classes de persistência (Active Record), bem como os métodos de relacionamento com demais objetos do sistema. Como vimos, uma classe Active Record oferece métodos básicos de persistência (store, load, delete). Estes métodos são disponíveis por meio da superclasse TRecord, da qual todas Active Record do sistema são filhas. No exemplo a seguir, temos uma classe para manipular uma tabela de pessoas. ```php cidade", automaticamente o método get_cidade() é disparado, retornando a instância (objeto cidade) relacionado. Então, podemos acessar demais informações, como o nome da cidade, ou mesmo o nome do estado vinculado àquela cidade, desde que na classe Cidade, exista o método get_estado(). ```php cidade->nome; print $pessoa->cidade->estado->nome; ``` O Adianti Studio Pro também gera métodos reversos para obter objetos em relacionamentos de associação. No caso de um objeto Pessoa que possui uma associação com Cidade, além de gerar o método para obter a cidade a partir da pessoa, o Studio também gerará um método para obter todas as pessoas de uma cidade, da seguinte forma: ```php add(new TFilter('cidade_id', '=', $this->id)); return Pessoa::getObjects( $criteria ); } } ``` Assim, para obter todas pessoas de uma cidade, bastaria: ```php getPessoas()); ``` A partir do diagrama em anexo (que faz parte das vídeo-aulas: http://www.adianti.com.br/framework-videoaulas), podemos importar o modelo UML pelo Adianti Studio Pro (www.adianti.com.br/studio-pro) e passar a programar diretamente da maneira a seguir, sem a necessidade de implementar tais métodos, que serão gerados automaticamente. ![Diagrama simples acadêmico](http://www.adianti.com.br/forum/pt/post-images/academico.png "Diagrama simples acadêmico") Demonstração do uso de métodos gerados automaticamente pelo Studio Pro: ```php disciplina->nome; print $turma->disciplina->curso->nome; foreach ($turma->getMatriculas() as $matricula) { print $matricula->aluno->nome; print $matricula->aluno->cidade->nome; print $matricula->aluno->cidade->estado->nome; } ``` Além disso, construímos listagens (datagrids) para exibir informações de uma tabela, e frequentemente listamos informações vinculadas, como neste exemplo (http://www.adianti.com.br/framework_files/tutor/index.php?class=CustomerDataGridView). Neste momento, seguidamente as pessoas me escrevem perguntando como fazer Joins entre as tabelas. E eu digo que na maioria das vezes isso não é necessário, basta acessar o objeto associado. Ao construirmos uma datagrid, indicamos os nomes das colunas a serem exibidas na datagrid. Para exibir uma coluna vinculada (pertencente à outra tabela), podemos simplesmente usar a sintaxe indicada no terceiro addQuickColumn() do exemplo a seguir: ```php datagrid = new TQuickGrid; $this->datagrid->addQuickColumn('Código', 'id', 'left', 190); $this->datagrid->addQuickColumn('Nome', 'nome', 'left', 190); $this->datagrid->addQuickColumn('Cidade', 'cidade->nome', 'left', 190); ``` Ao indicarmos "cidade->nome" automaticamente o framework busca o atributo nome da cidade vinculada àquela pessoa. Isso somente é possível se tivermos o método get_cidade(), que irá retornar a cidade vinculada. A próxima dúvida de quem me escreve geralmente diz respeito ao desempenho. Certamente construirmos um SQL com Joins tem desempenho superior à buscar cada objeto relacionado sempre que ele for necessário. Mas para tal questionamento, costumo responder que as listagens no framework são todas paginadas, o que significa que em uma datagrid, estaremos buscando no máximo 10 objetos relacionados por vez, o que é muito pouco. Além disso, caso isto ainda seja um problema ao escalarmos a aplicação com um número de usuários muito grande, recomendo realizar cache de objetos usando o APC (assunto que será abordado em artigo posterior), que apresenta resultados incríveis. Por fim, existe um caso em que nenhuma abordagem anteriormente citada funciona muito bem que é na criação de relatórios. Ao criarmos relatórios geralmente precisamos mesmo cruzar uma quantidade grande de tabelas, e utilizar muitas vezes recursos avançados do banco de dados (subconsultas, pl/sql, joins malucos, dentre outros). Nestes casos, o APC não tem efeito algum, pois ele trata de cache de objetos, não de consultas. Mas mesmo para esse caso, existe uma solução que iremos propor no próximo artigo.
Please enable JavaScript to view the
comments powered by Disqus.