Clique para saber mais...
  Home     Download     Produtos / Cursos     Revista     Vídeo Aulas     Fórum     Contato   Clique aqui para logar | 15 de Novembro de 2025
  Login

Codinome
Senha
Salvar informações

 Esqueci minha senha
 Novo Cadastro

  Usuários
76 Usuários Online

  Revista ActiveDelphi
 Assine Já!
 Edições
 Sobre a Revista

  Conteúdo
 Apostilas
 Artigos
 Componentes
 Dicas
 News
 Programas / Exemplos
 Vídeo Aulas

  Serviços
 Active News
 Fórum
 Produtos / Cursos

  Outros
 Colunistas
 Contato
 Top 10

  Publicidade

  [Artigos]  [Intermediário] - Arquitetura MVC no Delphi
Publicado por rboaro : Terça, Junho 25, 2013 - 07:57 GMT-3 (1115 leituras)
Comentários 5 Comentários   Enviar esta notícia a um amigo Enviar para um amigo   Versão para Impressão Versão para impressão
André Celestino Nada melhor do que desenvolver um sistema utilizando uma boa arquitetura de software, não é? Uma das arquiteturas mais utilizadas por empresas e desenvolvedores de software é o MVC (Model-View-Controller), padrão que fornece organização, padronização e facilidade de manutenção do código. Esse artigo aborda os passos básicos para a elaboração de um projeto arquitetado em MVC no Delphi. Confira!

O objetivo principal deste artigo é mostrar a hierarquia de pastas em um projeto, a alocação das units dentro dessas pastas e a forma como elas se comunicam entre as camadas. Portanto, vou considerar que você já tem conhecimento dessa arquitetura, noções básicas de Orientação a Objetos e experiência com Delphi, ok? Mesmo assim, se você quiser conhecer os conceitos do MVC, leia também este artigo.
Vamos lá! O primeiro passo é criar a pasta raiz do projeto, como “C:\Aplicativo”, por exemplo. Em seguida, criaremos também mais três pastas dentro dela: Model, View e Controller. Essa será a estrutura de subpastas que armazenará nossas units referentes a cada camada. A partir de então, as units criadas deverão ser salvas de acordo com a sua responsabilidade no projeto:
As units das classes de modelagem deverão ser salvas dentro da subpasta Model
Já as units de controle deverão ser salvas dentro da subpasta Controller
Por fim, os formulários deverão ser salvos dentro da subpasta View
O arquivo de projeto (DPR ou DPROJ) deverá ser salvo fora dessas subpastas, ou seja, no diretório raiz da aplicação
Demais arquivos (imagens, arquivos texto, arquivos INI…) opcionalmente podem ser salvos em um diretório próprio, como “Arquivos”

A nomenclatura das units também é importante para facilitar a localização dentro do projeto. Uma boa prática é salvá-las com um prefixo representando o nome da camada seguido do nome de domínio. Por exemplo, se houver o domínio “Cliente”, poderíamos nomear as units da seguinte forma: classeCliente, controleCliente e frmCadastroClientes. Este último recebe o prefixo “frm” por se tratar de um formulário na camada View, embora este prefixo também possa ser utilizado como “form”, “f_” ou até mesmo “visao”.
Alguns desenvolvedores preferem utilizar nomenclaturas em inglês nas units, nomeando-as como classCliente e controllerCliente. Na verdade, o padrão de nomenclatura é relativo de cada desenvolvedor, mas o importante é definir um nome que seja condizente com a camada na qual a unit está alocada.
Ao respeitar essa estrutura de pastas, observe que o Delphi organiza automaticamente a disposição das units dentro de suas respectivas pastas no Project Manager:


Estrutura de pastas exibida no Project Manager do Delphi

A comunicação entre as camadas é realizada por meio da instanciação de objetos das classes. Considerando que temos um domínio de negócio no projeto chamado “Cliente”, poderíamos escrever o bloco de código abaixo para salvar um novo cliente no banco de dados

var
// variáveis das camadas utilizadas na rotina
objetoCliente: TCliente;
objetoControle: TControleCliente;
begin
// instanciação dos objetos
objetoCliente := TCliente.Create; // classe Modelo
objetoControle := TControleCliente.Create; // classe Controle
try
// preenchimento dos dados
objetoCliente.Codigo := StrToIntDef(edtCodigo.Text, 0);
objetoCliente.Nome := Trim(edtNome.Text);
objetoCliente.CPF := edtCPF.Text;

// chamada da rotina para gravação
objetoControle.Salvar(objetoCliente);
finally
// liberação dos objetos da memória
FreeAndNil(objetoCliente);
FreeAndNil(objetoControle);
end;
end;

Atente-se que, ao chamar o método “Salvar” de objControle, os dados do objetoCliente ainda não serão efetivamente gravados no banco de dados. Antes disso, eles passam pela camada Controller, responsável por validar os dados do objeto para evitar que eles sejam transferidos para a camada de acesso a dados (Model) com inconsistências.
Observe que no exemplo acima, um dos atributos da classe “Cliente” é o CPF. Podemos escrever uma função na camada Controller para validar o CPF e, em caso de inválido, abortar a operação de gravação e retornar uma mensagem ao usuário. Essa é uma grande vantagem da arquitetura MVC: durante essa operação de validação não há nenhum acesso à camada de acesso a dados. Na prática, é como se a camada de acesso a dados (Model) ainda não soubesse que o usuário está incluindo um novo cliente. Ela só irá receber o objeto quando estiver validado e consistente. Interessante, não é?

A camada Controle, por sua vez, terá o seguinte código no método “Salvar”:
procedure TControleCliente.Salvar(const objetoCliente: TCliente);
begin
// aqui devem ser escritas as funções de validação

objetoCliente.Salvar(objetoCliente);
end;

Veja que utilizamos o próprio objeto passado por parâmetro para chamar a função “Salvar” da camada Model. Aproveitando a oportunidade, vale ressaltar uma observação importante: muitos desenvolvedores preferem estender a camada Model na arquitetura MVC e criar uma camada exclusiva de acesso a dados, chamada DAO (Data Access Object). Eu confesso que sou um desses desenvolvedores, rsrs.
Ao criar a camada DAO, é possível separar a modelagem de dados (atributos da classe) e os métodos de acesso a dados (Salvar, Alterar, Excluir, etc) em units diferentes. Lógico, neste caso, é necessário criar mais uma subpasta no diretório da aplicação chamada DAO. A introdução dessa camada também irá interferir na camada Controller. Por exemplo, utilizando o código anterior como comparação, a chamada do método “Salvar” é alterada para a seguinte forma:
procedure TControleCliente.Salvar(const objetoCliente: TCliente);
var
objetoDAO: TDAOCliente;
begin
objetoDAO := TDAOCliente.Create;
try
// aqui devem ser escritas as funções de validação

objetoDAO.Salvar(objetoCliente);
finally
FreeAndNil(objetoDAO);
end;
end;

Embora o código fique ligeiramente maior, a compreensão não fica comprometida. A diferença é que, ao invés de chamar a camada Model para persistir os dados, chamamos a camada DAO.
Antes de finalizar o artigo, gostaria de esclarecer uma dúvida comum de desenvolvedores que começam a trabalhar com Orientação a Objetos no Delphi, principalmente desenvolvedores que vieram de outras linguagens, como C++, C# e Java. Essa dúvida é relacionada aos getters e setters, que são métodos de leitura e escrita dos atributos de uma classe.
No Delphi não há getters e setters, mas introduz um modo diferente de manipular os atributos: através de propriedades (property). Em apenas uma linha, é possível declarar a propriedade e suas variáveis de leitura e escrita, como o exemplo abaixo:
type
TCliente = class
private
FNome: string;
public
property Nome: string read FNome write FNome;
end;


Ou então, caso necessário, declarar métodos para leitura e escrita:
type
TCliente = class
private
FNome: string;

procedure SetNome(Valor: string);
function GetNome: string;
public
property Nome: string read GetNome write SetNome;
end;


Legal, não é?
O exemplo contido neste artigo (com alguns incrementos) pode ser baixado neste link.
Pessoal, eu vou ficando por aqui e agradeço a vocês pela visita no SubRotina!
Qualquer dúvida ou dificuldade no desenvolvimento de um projeto em MVC, entre em contato!
Abraços!


Comentários Comentários
   Ordem:  
Comentários pertencem aos seus respectivos autores. Não somos responsáveis pelo seus conteúdos.


por: ronneipeterson (ronneipeterson@gmail.com) : Jun 25, 2013 - 10:44
(Informações sobre o membro | Enviar uma mensagem) http://www.invictos.com.br
Interessante a idéia, a uns anos atrás escrevi dois artigos na revista Active Delphi parecido com essa idéia, os títulos era "Acesso a Banco de Dados Relacional com uso da Orientação a Objeto", o padrão é parecido com o MVC, porém não existe a camada de validação, ela fica junto com a camada de acesso, porém depois de muitos anos usando este conceito passei a ter problemas nas chaves estrangeiras, pois para cada chave estrangeira eu instanciava a classe daquela chave, isso em algumas situações criou instâncias em cascatas, com centenas de objetos, trazendo lentidão e "out of memory" em alguns casos. Gostaria de saber como você tem tratado a situação de chave estrangeira, tem instanciado classes? Ou tem declarado a propriedade apenas como uma string e recebendo apenas a chave primária?

Abraço e Sucesso!
  Edição 112

Revista ActiveDelphi

  50 Programas Fontes


  Produtos

Conheça Nossos Produtos

Copyright© 2001-2016 – Active Delphi – Todos os direitos reservados