Arquitetura MVC no Delphi

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!

Estrutura do projeto

O objetivo principal deste artigo é mostrar a estrutura 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 “view”.

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

Comunicação entre as camadas

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:

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:

Camada DAO

No exemplo acima, 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, haha.

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:

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.

Conclusão

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 é necessário utilizar getters e setters. A ferramenta 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:

Ou então, caso necessário, declarar métodos para leitura e escrita:

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 blog!
Qualquer dúvida ou dificuldade no desenvolvimento de um projeto em MVC, entre em contato!

Abraços!


 

André Celestino