Clique aqui para ler esse artigo em PDF.
POO
MVC (Model-View-Controller)
Aplique esse poderoso padrão em suas aplicações cliente/server
A grande maioria dos programadores Delphi desenvolve seus sistemas utilizando o modelo Cliente/Servidor, dividindo assim teoricamente seu sistema em duas camadas: interface e banco de dados.
É muito comum vermos no código de um formulário a construção de sentenças SQL e validação de regras de negócio, tudo muito RAD, já que é neste ponto que o Delphi se destaca. É possível construir rapidamente um cadastro e sua manutenção utilizando Delphi, porém um sistema completo não é composto apenas por cadastros. Muita lógica está envolvida.
Além disso existe outro fator que muitos não atentam: a vida do sistema. Por quanto tempo ele vai rodar. Se você quer desenvolver um sistema que tenha uma vida longa tem que pensar no tempo e custo das manutenções que ocorrerão.
Nessa hora que surgirão os problemas em se utilizar o RAD sem pensar na arquitetura do sistema. É muito fácil construir uma aplicação arrastando componentes, gerar os eventos no formulário e dentro deles mesmo acessar banco de dados, SQL e etc. O difícil será reutilizar rotinas, regras de negócio e aplicação de testes, que juntos garantem uma facilidade na adequação dos sistemas para as necessidades dos usuários.
Agora você pode estar se perguntando, por onde começo? A primeira coisa a se fazer é pensar que seu software é composto por camadas e não apenas por formulários, relatórios e um banco de dados. Vamos explorar um pouco as camadas que um sistema pode ter.
Camadas
Em um sistema com boa arquitetura encontramos algumas divisões lógicas que visam facilitar a manutenção e adição de novos recursos. Essas camadas podem ser vistas na Figura 1.
Figura 1. Camadas lógicas de um software
Para tornar a explicação sobre as camadas mais intuitiva quero que imagine seu sistema. Com toda certeza nele você possui um formulário de cadastro. O seu formulário representa a camada de apresentação do seu sistema, isto porque é nela que os dados são apresentados. Se seu sistema é cliente/servidor, a sua camada de domínio, de base dados e até mesmo serviços podem ser representadas pelos Data Modules existentes e seus componentes de acesso ao banco de dados. Por último temos a camada global que pode ser representada pelo seu conjunto de funções e procedimentos públicos.
Continuando com o paralelo a um sistema comum, desenvolvido por um programador Delphi, nos formulários nós fazemos acesso direto aos Data Modules, aos ClientDataSets, geramos SQL, tudo sem preocupação alguma, ou seja, nós misturamos o que seriam nossas camadas sendo que o correto é separar as camadas.
Quando essas camadas se misturam é dito que existe um acoplamento entre elas. No momento que você insere código SQL em evento OnClick de um botão o acoplamento foi realizado. Seu formulário que é sua camada de apresentação, está fazendo acesso direto aos recursos do que seria sua camada de dados. Isso impede a reutilização da lógica contida no formulário. Tudo isso dificulta a manutenção do seu sistema porque você terá SQL espalhado por todo código e não apenas centralizado em uma área.
Outra prática que é muito comum é de se criar os eventos e dentro deles escrever um código tão longo que para entender o que está sendo feito é quase como ler um livro. Consequentemente a rotina ali dentro poderia ser quebrada em classes ou funções.
Quando uma rotina faz mais do que foi projetada a fazer é dito que existe uma baixa coesão nela. A baixa coesão é outro problema para a boa manutenção do seu software. Então, como podemos separar as camadas sem, contudo uni-las? Pensando nessa solução alguns arquitetos de software criaram os padrões de projeto. Os padrões são de uma forma simplificada, como uma receita de bolo a ser seguida. Eles expõem o problema e mostram como solucioná-lo.
O problema apresentado neste artigo é como separar a interface do sistema do restante da aplicação. Como torná-la independente. A solução já existe, foi desenvolvida na forma de um padrão de projeto chamado MVC – Model View Controller, este é o foco do nosso artigo.
Utilizando o padrão em um exemplo
Nosso primeiro aplicativo de exemplo será simples, porém irá mostrar como iniciar o desenvolvimento utilizando o padrão MVC e fazer uso de interfaces.
Constará apenas de uma tela principal que irá chamar um formulário que permite ao usuário realizar multiplicações. Aqui utilizo o Delphi 2007, contudo, o exemplo pode ser reproduzido também no Delphi 5, 6, 7, 2005 e 2006 sem problema algum e para iniciarmos, inicie um novo projeto Win32.
Para separar a camada de apresentação o MVC cria três partes distintas, o Model, a View e o Controller. Podemos defini-los da seguinte forma:
· Model – É a representação da informação que a aplicação utiliza, que no nosso exemplo é o cálculo de multiplicação e os números que serão calculados.
· View – É a representação gráfica do Model. Por exemplo, um formulário expondo as informações de um cliente. Uma View está sempre ligada a um model e sabe como exibi-lo ao usuário. E para um determinado Model podem existir várias views. Além disso também pode ser composta por várias Views. Aplicando isso ao exemplo, a view é nosso formulário que irá permitir ao usuário digitar o valores e efetuar sua multiplicação.
Controller – É responsável em mapear as ações do usuário em ações do sistema, por exemplo se um botão ou item de menu é clicado é ele que deve definir como a aplicação responderá. No nosso exemplo é o controller que irá fazer com que ao clicar no botão “calcular” o cálculo seja feito.
Colocando a mão na massa
Vamos iniciar criando as partes básicas definidas pelo padrão, o Model, a View e o Controller. Adicione uma unit ao projeto renomeando-a para “MVCInterfaces.pas”. Nela adicione as seguintes interfaces, conforme listagem Listagem 1.
Listagem 1. MVC
type
TModelChangedEvent = procedure of object;
IModel = interface
['{FDF18F94-0430-4C48-BE64-F4516C4C1011}']
procedure Initialize;
function GetOnModelChanged: TModelChangedEvent;
procedure SetOnModelChanged(value:
TModelChangedEvent);
property OnModelChanged: TModelChangedEvent read
GetOnModelChanged write SetOnModelChanged;
end;
IView = interface" [...] continue lendo...