Você está na página 1de 15

30/11/2019 MVC no Delphi: separação de camadas

www.devmedia.com.br
[versão para impressão]
Link original: https://www.devmedia.com.br/mvc-no-delphi-separacao-de-camadas/30143

MVC no Delphi: separação de camadas


O artigo apresenta a teoria do padrão MVC. Através de um exemplo que
tem por finalidade registrar produtos, clientes e itens vendidos, o MVC é
posto em prática e até mesmo a camada de persistência é desenvolvida,
sendo empregado o framework Aurelius.

Por que eu devo ler este artigo:O artigo apresenta a teoria do padrão MVC, que é largamente utilizado para
separar a camada lógica da camada de apresentação.

Através de um exemplo que tem por finalidade registrar produtos, clientes e itens vendidos, o MVC
é posto em prática e até mesmo a camada de persistência é desenvolvida, sendo empregado o
framework Aurelius para a tarefa de salvar os dados em um banco de dados relacional.

Também são explicados conceitos importantes relacionados à orientação a objetos, como a


agregação e composição.

A programação orientada a objetos apresenta muitas vantagens na hora de desenvolvimento de


uma aplicação, e também, durante sua vida útil, pois por meio dela se torna possível escrever
códigos com funções reutilizáveis, economizando muito código, além de deixar o código fonte
melhor organizado, facilitando a vida do desenvolvedor.

No entanto, o sistema de armazenamento de dados mais utilizado atualmente no mercado são os


bancos de dados relacionais, estes que por sua vez não são compatíveis com as classes de um
sistema orientado a objetos.

Para essa incompatibilidade damos o nome de impedância e para resolver este problema foram
concebidos os frameworks ORM (Object Relational Mapping – Mapeamento Objeto Relacional),
estes frameworks desempenham o papel de trazer as classes do sistema para o mesmo nível dos
bancos de dados relacional.

O ORM é utilizado para fazer a abstração do banco de dados e por meio dele é possível fazer
consultas ou persistências no banco sem que seja necessário, por parte do desenvolvedor,
escrever códigos SQL, pois estes são feitos pelo próprio framework.

Outra vantagem de utilizar ORM na hora de desenvolver é a liberdade do programador para utilizar
qualquer banco de dados, ou até mesmo qualquer componente de conexão.

https://www.devmedia.com.br/view/print.php?idcomp=30143 1/15
30/11/2019 MVC no Delphi: separação de camadas

No caso específico do Aurelius, por meio dos adapters (será explicado mais adiante) a aplicação
em si fica completamente isenta de particularidades com o sistema de armazenamento de dados,
ou seja, se futuramente for necessário modificar o BD, basta mudar a classe do Adapter e deixar
que o framework faça a adaptação do outro sistema de armazenamento de dados.

Para o desenvolvimento de aplicações utilizando ORM em Delphi foram criados diversos


frameworks, entre eles podemos destacar o Aurelius, DORM, entre outros.

Neste artigo vamos estudar com mais detalhes a persistência de objetos utilizando o framework
Aurelius, que é uma ferramenta brasileira, inicialmente criada como um trabalho de conclusão de
curso e mais tarde, com melhorias, foi incorporado a gama de produtos da TMS.

O Aurelius faz a conexão no BD por meio do padrão Adapter, este que, por sua vez, consiste em
criar uma camada intermediária que expressa componente que, por algum motivo, pode estar fora
da arquitetura de sua aplicação, ou seja, se futuramente ocorrer alguma mudança na classe
adaptada, basta executar as devidas alterações na classe Adapter e o sistema já está pronto para
funcionar normalmente.

Utilizando as classes chamadas de domínio, indicamos todas as características necessárias para


atender os determinados requisitos de seu sistema, para este processo é dado o nome de
mapeamento, que é uma importante etapa do desenvolvimento de um software, pois é nessa fase
que são definidas as características das classes de domínio do sistema e as características do
banco de dados da aplicação.

Para desempenhar esse trabalho, o Aurelius disponibiliza recursos como, por exemplo, o
Automapping, onde é feito o mapeamento de forma automática, bastando seguir os padrões de
nomenclaturas de classes e atributos como, por exemplo, TClass e FField. Existe também o
mapeamento por Custom Attributes, onde são colocadas tags do nome de cada campo, bem como
o da tabela e assim por diante, conforme as necessidades do sistema.

Entendo a arquitetura MVC

Uma vez com a conexão feita e as classes mapeadas, é hora de iniciar o desenvolvimento
utilizando o padrão MVC, empregando as camadas model, view e controller. Para a view, que é a
camada de apresentação do sistema, uma boa prática é fazer o protótipo da tela. Na seção Links
está disponível o download da instalação de software que auxilia nessa importante tarefa.

Nessa camada não pode conter nenhuma regra de negócio ou de banco de dados, salvo quando é
utilizado o componente para fazer o databinding. Mais adiante abordaremos esse conceito com
mais detalhes.

Nessa arquitetura temos também a camada Model, que é responsável pela comunicação com o
banco de dados e concentração da regra de negócio, ou seja, nela estão contidos todos os
métodos que utilizam acesso ao banco de dados.

Por fim, a camada Controller é a que controla as ações entre as camadas Model e View. Por ela
passa todo o fluxo de dados para fazer a transição entre essas duas camadas. O Controller
https://www.devmedia.com.br/view/print.php?idcomp=30143 2/15
30/11/2019 MVC no Delphi: separação de camadas

funciona como um “porteiro”, fazendo a mediação da entrada, convertendo-a em comandos para o


Model ou View. A Figura 1 ilustra o funcionamento da arquitetura MVC.

Figura 1. Modelo MVC

Documentação

Quando se inicia um projeto sem antes ter um planejamento e uma documentação adequada, é
muito comum o retrabalho durante as etapas de desenvolvimento, acarretando o atraso de entrega
do projeto. Portanto, é preferível gastar no início um tempo pensando sobre o comportamento do
sistema diante das regras de negócio, fazendo o protótipo de todas as telas do sistema.

Para este artigo vamos desenvolver uma aplicação utilizando o Delphi XE2 e o framework Aurelius
na sua versão 2.0. Como documentação vamos desenvolver um diagrama de classes para nos
auxiliar no mapeamento das mesmas e fazer o protótipo das telas, para utilizarmos como apoio no
desenvolvimento do sistema e expressar todas as regras de negócio antes do desenvolvimento
propriamente dito.

Diagrama de classes

Para exemplificar o funcionamento do Aurelius na persistência de dados, vamos utilizar um


exemplo clássico de um sistema de vendas onde temos a classe TVenda que compreende todas
as informações necessárias para realizar uma venda, a classe TItenVenda que será salva na
classe TVenda uma lista de itens contidos na venda.

Teremos também as classes TProduto e TCliente que fazem parte das classes TVenda e
TItenVenda, respectivamente. Nessas classes vamos poder observar como é feita uma
persistência simples com o Aurelius, sem relacionamentos nem listas Já nas classes TVenda e
TItemVenda será possível exemplificar como é a persistência de dados quando estamos utilizando
uma lista ou um relacionamento nas classes de domínio.

A Figura 2 exibe o diagrama de classes para a nossa aplicação teste.

https://www.devmedia.com.br/view/print.php?idcomp=30143 3/15
30/11/2019 MVC no Delphi: separação de camadas

Figura 2. Diagrama de classes da aplicação exemplo

No diagrama temos as classes com os devidos relacionamentos, que são muito importantes para
que não cometamos erros na hora de fazer o mapeamento das classes. No diagrama podemos
observar a classe TVenda se relacionando com as demais classes. Temos um relacionamento de
agregação (ver BOX 1) entre as classes TVenda e TCliente e TItemVenda e TProduto. Também
podemos observar um relacionamento de composição (ver BOX 2) entre a classe TVenda e
TItemVenda.

BOX 1. Agregação

Podemos definir uma agregação quando em uma relação Parte-Todo perdermos o Todo e ainda
faz sentido manter a parte no banco de dados, vejamos um exemplo na relação entre as tabelas
TCliente e TVenda, conforme a Figura a.

Figura a. Relacionamento entre as tabelas TCliente e TVenda

https://www.devmedia.com.br/view/print.php?idcomp=30143 4/15
30/11/2019 MVC no Delphi: separação de camadas

Os clientes são partes integrantes em uma venda, porém não dependem exclusivamente de uma
venda para existirem no banco de dados, ou seja, faz sentido manter um cliente no banco de
dados sem que este participe de uma venda, pois pode ser que este cliente desempenhe outros
papéis dentro do sistema, quando temos esse tipo de relação, é dado o nome de Agregação. Para
representar a agregação utilizamos a seta “vazia” (em branco).

BOX 2. Composição

É uma relação mais forte, ou seja, neste caso em uma relação Parte-Todo, não faz sentido manter a parte no
banco de dados quando não tem mais a todo, ou seja, a parte depende exclusivamente da existência do todo
para ela também existir, vejamos um exemplo de composição entre as classes TVenda e TItemVenda,
conforme a Figura b.

Figura b. Composição entre as classes TVenda e TItemVenda


Os itens são parte integrantes de uma venda, logo, uma venda é feita com base nos seus itens, no
entanto se a venda não existir, não faz sentido manter o item dessa venda no banco de dados,
note que estamos falando de item da venda, e não de produto, o produto é uma agregação com
TItemVenda. Para representar a composição utilizamos a seta “cheia” (pintada).

Com base no diagrama de classes podemos criar as telas de nossa aplicação, lembrando que as
telas criadas como protótipo servem apenas para nortear o desenvolvimento, podendo haver
alterações na aplicação real.

Na Figura 3 podemos conferir o protótipo da tela de cadastro de produtos. Temos apenas os


campos que servirão de entrada para os dados dos produtos.

https://www.devmedia.com.br/view/print.php?idcomp=30143 5/15
30/11/2019 MVC no Delphi: separação de camadas

Figura 3. Tela de cadastro de produtos

De forma semelhante, na Figura 4 vemos o cadastro de Clientes.

Figura 4. Tela de cadastro de clientes

Já a Figura 5 apresenta a tela de venda, com maior complexidade porque nela teremos todas as
classes sendo envolvidas.

https://www.devmedia.com.br/view/print.php?idcomp=30143 6/15
30/11/2019 MVC no Delphi: separação de camadas

Figura 5. Tela de cadastro de clientes

Agora que toda a documentação necessária para o desenvolvimento está feita, estamos prontos
para iniciarmos o desenvolvimento do sistema propriamente dito. Não vamos exemplificar aqui
como é o código do mapeamento e conexão com o banco de dados, posto que isso já foi mostrado
em um outro artigo (ver seção Links).

Desenvolvendo as camadas para o cadastro de clientes

Agora é hora de observar na prática como os “porteiros” da arquitetura MVC funcionam. Nos
controladores estão contidos métodos que fazem a interface entre o modelo e a camada de
apresentação como, por exemplo, as funções que fazem o binding dos dados da view para o
model, e vice-versa.

O binding consiste em simplesmente fazer a transição de dados entre as camadas e pode ser feito
com o componente que o Aurelius nos disponibiliza, o AureliusDataSource. No entanto, para este
artigo vamos fazer o binding sem utilizar este componente, dessa forma, os conceitos serão
melhores fixados.

A Listagem 1 apresenta a função BindInModel, que consiste em obter os dados da view e passar
para o modelo. BindInModel é chamada no controlador do cadastro de clientes, depois de
preencher todos os campos. Ela retornará um objeto com as informações, pronto para ser utilizado
na função para persistir no banco de dados.

Listagem 1. Função BindInModel do controlador do cadastro de cliente

https://www.devmedia.com.br/view/print.php?idcomp=30143 7/15
30/11/2019 MVC no Delphi: separação de camadas

01 function TClienteController.BindInModel() : TCliente;


02 var
03 cliente : TCliente;
04 clienteModel : TClienteModel;
05 begin
06 cliente := TCliente.Create;
07 cliente.Nome := CadastroClienteF.edtNome.Text;
08 cliente.CPF := CadastroClienteF.edtCPF.Text;
09 cliente.Telefone := CadastroClienteF.edtTelefone.Text;
10 Result := cliente;
11 end;

Observe que na linha 03 temos a declaração da variável TCliente, ou seja, do domínio. Na linha 06
a classe TCliente é instanciada na variável cliente. Já entre as linhas 07 e 09 são feitas as
transições, ou seja, a obtenção das informações digitadas nas caixas de texto e passadas para o
objeto cliente e por fim, na linha 10 é dado o retorno na função, passando o objeto que recebeu as
informações da view.

Agora que temos um objeto com todas as informações carregadas da tela, podemos persistir no
banco este objeto, utilizando a função Salvar, como mostra a Listagem 2.

Listagem 2. Função Salvar do controlador do cadastro de cliente

01 function TClienteController.Salvar(cliente : TCliente): boolean;


02 var
03 clienteModel : TClienteModel;
04 begin
05 clienteModel := TClienteModel.Create;
06 if clienteModel.SaveOrUpdate(cliente) then
07 Result := True
08 else
09 Result := False;
10 end;

Na linha 03 temos a declaração da variável do model que é instanciado na linha 05 e na linha 06


temos a chamada da função SaveOrUpdate do modelo do cadastro de clientes. No modelo é feita
de fato a persistência do objeto no banco de dados.

Como é uma função booleana, tanto a SaveOrUpdate do modelo como a Salvar do controlador, se
a transação ocorreu com sucess,o é atribuído True ao retorno da função, possibilitando a exibição
de uma mensagem, mostrando sucesso ou falha na gravação dos dados. A Listagem 3 mostra
como a View utiliza o Controller.

Listagem 3. Chamada das funções no controller

https://www.devmedia.com.br/view/print.php?idcomp=30143 8/15
30/11/2019 MVC no Delphi: separação de camadas

01 procedure TCadastroClienteF.BtnSalvarClick(Sender: TObject);

02 var
03 cliente : TCliente;
04 begin
05 clienteController := TClienteController.Create;
06 cliente := clienteController.BindInModel;
07 clienteController.Salvar(cliente);
08 end;

Na linha 03 podemos observar a declaração da variável do tipo TCliente que receberá da função
BindInModel os dados digitados pelo usuário na tela, como está sendo exemplificado na linha 06.
Na linha 07 temos a chamada da função Salvar, onde passamos o objeto cliente que será
persistido no banco de dados.

Listagem 4. Persistindo o objeto cliente no banco de dados

01 function TClienteModel.SaveOrUpdate(cliente: TCliente): Boolean;


02 begin
03 try
04 FObjectManager.SaveOrUpdate(cliente);
05 Result := True;
06 except
07 Result := False;
08 end;
09 end;

Observe que na linha 04 da Listagem 4 temos o atributo FObjectManager que foi criado na hora
de fazer a conexão com o banco de dados, onde temos um RegisterMapping. Este recebe todas as
classes de domínio que as registra na conexão, e o ObjectManager tem a função de gerenciar o
objeto.

É por meio dele que persistimos ou recuperamos dados do BD, passando o objeto como parâmetro
e chamando a função SaveOrUpdate. Com isso temos a persistência de um objeto simples
utilizando o Aurelius.

Desenvolvendo as camadas para o cadastro de produtos

O cadastro de produtos, assim como o cadastro de clientes, é simples e não envolve nenhuma
relação entre tabelas, portanto vamos apenas conferir como ficarão as funções e suas chamadas,
assim como no cadastro de clientes. A Listagem 5 mostra a função BindInModel que mantém sua
função principal de transpor as informações da View para o Model.

Listagem 5. Função BindInModel do controlador do cadastro de produto

https://www.devmedia.com.br/view/print.php?idcomp=30143 9/15
30/11/2019 MVC no Delphi: separação de camadas

01 function TProdutoController.BindInModel() : TProduto;


02 var
03 produto : TProduto;
04 begin
05 produto := TProduto.Create;
06 produto.Descricao := CadastroProdutoF.edtDescricaoProduto.Text;
07 produto.Valor := StrToFloat( CadastroProdutoF.edtValorVenda.Text);
08 produto.ValorCompra:= StrToFloat(CadastroProdutoF.edtValorCompra.Text);
09 produto.Quantidade := StrToInt(CadastroProdutoF.edtQtd.Text);
10 Result := produto;
11 end;

A Listagem 6 apresenta a função Salvar, bem semelhante ao que foi feito para um cliente.

Listagem 6. Função Salvar do controlador do cadastro de produto

01 function TProdutoController.Salvar(produto : TProduto): boolean;


02 begin
03 if ProdutoModel.SaveOrUpdate(produto) then
04 Result := True
05 else
06 Result := False;
07 end;

A Listagem 7 exibe o SaveOrUpdate do model relativo ao Produto, seguindo o mesmo padrão


exibido para o model do Cliente.

Listagem 7. Persistindo o objeto produto no banco de dados

01 function TProdutoModel.SaveOrUpdate(produto: TProduto): Boolean;


02 begin
03 try
04 FObjectManager.SaveOrUpdate(produto);
05 Result := True;
06 except
07 Result := False;
08 end;
09 end;

Desenvolvendo as camadas para o cadastro de venda

Neste momento chegamos a um exemplo mais complexo, onde teremos uma persistência que
envolve relacionamentos de agregação e composição entre tabelas, além de um exemplo
utilizando uma lista.

https://www.devmedia.com.br/view/print.php?idcomp=30143 10/15
30/11/2019 MVC no Delphi: separação de camadas

Poderemos também conferir como funciona a busca no banco de dados, por meio das funções que
carregam tanto a combo de clientes como a combo de produtos.

Nessa tela temos um grid em memória para armazenar todos os itens da compra, além das listas
que a partir delas serão carregadas as combos e também os itens da venda.

Assim como nas outras telas, aqui teremos os métodos BindInView, Salvar do controller e Salvar
do model, além das chamadas a partir da view, porém, temos algumas diferenças. No método que
faz o bind no modelo teremos que passar a lista de itens para que estes possam ser inseridos na
venda, e também, temos que passar como parâmetro o objeto cliente para marcar qual foi o cliente
que efetuou a compra.

A Listagem 8 apresenta o método BindInModel.

Listagem 8. Função BindInModel do controlador da venda

01 function TVendaController.BindInModel(ListaItens :
02 TObjectList<TItemVenda>; cliente : TCliente) : TVenda;
03 var
04 venda : TVenda;
05 begin
06 venda := TVenda.Create;
07 venda.Data := Now;
08 venda.Items := ListaItens;
09 venda.Cliente := cliente;
10 venda.DataPagamento := Now;
11 venda.Valor := StrToFloat(VendaF.edtQtd.Text);
12 Result := venda
13 end;

Observe que ela é bem parecida com as outras listagens que fazem o BindInModel, no entanto,
nesta temos os dois parâmetros: uma lista que contém todos os itens da venda e é do tipo
TItemVenda, e um objeto que guarda as informações do cliente que efetuou a compra.

Estes parâmetros são passados pela view, pois é nela onde serão definidos o cliente e os itens da
venda. Na linha 06 podemos observar o objeto venda, que é do tipo TVenda, ser instanciado. Já
entre as linhas 07 e 11 temos a atribuição de cada valor em seu devido campo, com destaque para
linha 08.

Nela é feita a atribuição dos itens da venda para a venda, note que basta passar a lista carregada
com os itens da venda para o determinado atributo do objeto venda. Agora atente para a linha 09,
onde atribuímos o objeto cliente na venda atual.

Note que, uma vez a classe mapeada, basta ir atribuindo os objetos com o devido tipo para cada
tributo.

https://www.devmedia.com.br/view/print.php?idcomp=30143 11/15
30/11/2019 MVC no Delphi: separação de camadas

Depois de ver como é o funcionamento do BindInModel, quando temos relacionamentos entre


classes envolvidas, vamos conferir o código da função Salvar (Listagem 9), ainda no controller.

Listagem 9. Função BindInModel do controlador da venda

01 function TVendaController.Salvar(venda : Tvenda): boolean;


02 begin
03 VendaModel.SaveOrUpdate(venda);
04 end;

Essa é a função que ainda é acionada por meio da view e recebe o objeto que a função
BindInModel retornou. Essa função chama o método SaveOrUpdate no modelo da venda, método
este que faz a persistência deste objeto que é passado como parâmetro.

Agora que já sabemos como são as funções no controlador da venda, vamos ver como é feita a
chamada dessas funções pela view. A Listagem 10 apresenta como a view faz inserção de um
item na venda.

Listagem 10. Adicionar um produto na venda

01 procedure TVendaF.BtnInserirClick(Sender: TObject);


02 var
03 item : TItemVenda;
04 i : real;
05 begin
06 item:= TItemVenda.Create;
07 item.Produto:= ListaProdutos.Items[CMBProduto.ItemIndex];
08 item.Quantidade:= StrToInt(edtQtd.Text);
09 ListaItens.Add(item);
10 ADItemVenda.Open;
11 ADItemVenda.Insert;
12 ADItemVendaProduto.AsString:=
ListaProdutos.Items[CMBProduto.ItemIndex].Descricao;
13 ADItemVendaQuantidade.AsInteger:= StrToInt(edtQtd.Text);
14 ADItemVendaValor.AsFloat:=
ListaProdutos.Items[CMBProduto.ItemIndex].Valor;
15 ADItemVendaSubTotal.AsFloat:=
ListaProdutos.Items[CMBProduto.ItemIndex].Valor *
StrToInt(edtQtd.Text);
16 ADItemVenda.Post;
17 i := 0;
18 for item in ListaItens do
19 i := i + (item.Quantidade*item.Produto.Valor);
20 edtValor.Text := FloatToStr(i);
21 end;

https://www.devmedia.com.br/view/print.php?idcomp=30143 12/15
30/11/2019 MVC no Delphi: separação de camadas

É declarada uma variável do tipo TItemVenda na linha 06, que é instanciada, ou seja, sendo
preparada para receber os dados de cada item da venda. Nas linhas 7 e 8 são atribuídos os
valores para os atributos de TItemVenda e na linha 09 este objeto é adicionado na lista de itens
que mais tarde será atribuída no atributo Itens do objeto venda.

Entre as linhas 10 e 16, são inseridos os dados do item em um dataset em memória, pois temos
uma Grid para alimentar. Ela servirá para o usuário visualizar todos os itens da venda.

Entre as linhas 17 e 19 é feito um laço percorrendo a lista de itens para que seja somado o valor
total da venda naquele momento, e este valor é atribuído ao edtValor na linha 20. A cada item
inserido este valor é recalculado.

Agora, vamos ao botão que tem o papel de finalizar a venda, e também, chama as funções do
controlador da venda (Listagem 11).

Listagem 11. Finalizar venda

01 procedure TVendaF.BtnFinalizarClick(Sender: TObject);


02 var
03 venda : TVenda;
04 begin
05 venda := VendaController.BindInModel(ListaItens, ListaClientes.Items[CMBCliente.ItemIndex]);
06 VendaController.Salvar(venda);
07 end;

Note que neste lugar o código é igual para qualquer caso. Na linha 05 tem uma variável do tipo
TVenda, que foi declara na linha 03, recebe a objeto que a função BindInView do controller retorna
e é utilizada na linha 06 durante a chamada da função Salvar no controller. Vamos conferir agora
como é feita a função Salvar (Listagem 12) no modelo da venda.

Listagem 12. Salvar no modelo

01 function TVendaModel.SaveOrUpdate(venda : TVenda): Boolean;


02 begin
03 try
04 FObjectManager.SaveOrUpdate(venda);
05 Result := True;
06 except
07 Result := False;
08 end;

Observe que uma vez que o objeto está devidamente carregado, basta executar o comando
SaveOrUpdate do ObjectManager. Dessa forma, esse objeto será persistido no banco de dados.

No entanto, para realizar uma venda, temos que carregar os clientes e os produtos do banco de
dados. Para isso, vamos a view ver como é a chamada dos métodos no controller e logo em

https://www.devmedia.com.br/view/print.php?idcomp=30143 13/15
30/11/2019 MVC no Delphi: separação de camadas

seguida, vamos até o controller e verificar como é feita a comunicação com o model. A Listagem
13 mostra o momento em que as listas de Cliente e Produto são carregadas no evento OnShow.

Listagem 13. Chamada das funções para carregar as listas da view

01 procedure TVendaF.FormShow(Sender: TObject);


02 begin
03 ListaClientes := VendaController.BuscaClientes;
04 ListaProdutos := VendaController.BuscaProdutos;
05 ListaItens := TObjectList<TItemVenda>.Create;
06 PopulaComboCliente;
07 PopulaComboProduto;
08 end;

Observe que as listas serão disparadas para carregar assim que o formulário de venda aparecer
na tela. Entre as linhas 03 e 05 temos as chamadas das funções do controller que fazem a
interface com o model, passando dessa forma para ele o encargo de carregar as listas. Logo em
seguida, nas linhas 06 e 07 temos duas chamadas de funções locais que servem para carregar as
combos, ou seja, as listas carregadas são utilizadas para carregar a combo.

Logo, temos as listas como espelhos das combos, o que facilita nosso trabalho. A Listagem 14
apresenta o método BuscaProdutos do controller que foi utilizado pela view.

Listagem 14. Carrega lista de produtos no controller

01 function TVendaController.BuscaProdutos(): TObjectList<TProduto>;


02 begin
03 Result := VendaModel.BuscaProdutos;
04 end;

Sua funcionalidade é delegada ao método BuscaProdutos de VendaModel (Listagem 15) que é


quem realmente realiza o acesso ao banco de dados.

Listagem 15. Chamada das funções para carregar as listas da view

01 function TVendaModel.BuscaProdutos: TObjectList<TProduto>;


02 begin
03 Result := FObjectManager.CreateCriteria<TProduto>.AddOrder(
TOrder.Asc('DESCRICAO')).List;
04 end;

Na linha 03 a consulta no banco de dados é feita por meio de um objeto Criteria do Aurelius. Esse
objeto representa uma busca a ser realizada e no exemplo citado queremos todos produtos para
serem exibidos na combo, apenas adicionamos uma ordem. A ordem é representada pelo objeto
TOrder.Asc('DESCRICAO'). Além de ordenação, podemos adicionar um filtro para trazer
informações iguais às passadas por parâmetro, que é definido por Eq e seu uso seria Eq(‘nome da
propriedade’, ‘filtro’).
https://www.devmedia.com.br/view/print.php?idcomp=30143 14/15
30/11/2019 MVC no Delphi: separação de camadas

Claro que cada tipo de filtro tem seus parâmetros, para isso, é válido ler a documentação do
Aurelius. Podemos também fazer a consulta por Id, que será exemplificada na Listagem 16,
utilizando a classe TProduto.

Listagem 16. Busca por Id utilizando o Aurelius

01 function TVendaModel.BuscaProduto(id: integer): TProduto;


02 begin
03 Result := FObjectManager.Find<TProduto>(Id);
04 end;

Veja que é muito simples executar a busca por Id utilizando o Aurelius por meio do método Find do
ObjectiManager, passando o tipo que será consultado e o Id do registro, que automaticamente o
Aurelius fará a busca no banco de dados. Por fim, vamos conferir como é a função no model para
buscar a lista de Clientes (Listagem 17).

Listagem 17. Busca da lista de clientes utilizando o Aurelius

01 function TVendaModel.BuscaClientes: TObjectList<TCliente>;


02 begin
03 Result := FObjectManager.CreateCriteria<TCliente>.AddOrder(
TOrder.Asc('NOME')).List;
04 end;

Observe que o procedimento é exatamente o mesmo de buscar a lista de produtos, porém dessa
vez, os tipos buscados são o TCliente.

Ao aplicar o padrão MVC vemos as funcionalidades do sistema bem separadas, cada uma sem
seu próprio lugar. Isso facilita manutenção e entendimento do código porque podemos encontrar
com facilidade as funcionalidades, que estão organizadas de acordo com seu papel. Até mesmo a
parte de persistência ficou centralizada no framework Aurelius, isolando a aplicação de qualquer
conhecimento de banco de dados. Isso garante a independência em relação a que banco de dados
utilizar.

Links

Manual do Aurelius
http://www.tmssoftware.com.br/aurelius/doc/aurelius_manual.pdf

Artigo Mapeamento ORM com o TMS Aurelius


http://www.devmedia.com.br/mapeamento-orm-com-o-tms-aurelius-revista-clubedelphi-magazine-
151/28233

https://www.devmedia.com.br/view/print.php?idcomp=30143 15/15

Você também pode gostar