Padrões de projeto em Delphi: Implementações dos padrões GOF na prática

Arquitetura - DevSpace

Última atualização em 9 de agosto de 2022 por Willian Tuttoilmondo

Como implementar padrões de projeto em Delphi de maneira simples e prática

Uma das maiores discussões sobre o uso do Delphi em novos projetos é a capacidade (ou não) da ferramenta implementar novas tecnologias ou padrões vistos em outras linguagens que implementam a orientação a objetos de maneira mais rígida, como Java ou C#. Sim, é possível aplicar padrões de projeto em Delphi de uma maneira bem simples e rápida, diminuindo o custo de manutenção e, principalmente, o tempo de resposta de novas implementações.

Uma fórmula básica – e que funciona muito bem – é a implementação de 3 padrões em conjunto: Facade, Singleton e Abstract Factory. Com este conjunto, é possível resolver 95% dos problemas relacionados ao desenvolvimento de um novo projeto, ampliando as chances de sucesso e longevidade de uma aplicação ou sistema. Não adianta querer implementar padrões de projeto em Delphi para sistemas legados e construídos de maneira errada, pois seria como “colocar remendo de tecido novo em roupa velha”.

Mas, para que possamos explorar o máximo dessa característica do Delphi, é preciso entender: você precisa atualizar seu IDE! Desenvolvedores que ainda estejam presos ao Delphi 7 terão muitas dificuldades para alcançar esse objetivo. Alguns recursos importantíssimos, como Generics, por exemplo, surgiram apenas com o Delphi 2009. Isso sem mencionar que, para o complemento deste artigo, o qual será publicado em outra oportunidade, será necessário utilizar o novo Datasnap, que apareceu no Delphi 2010.

Mas, antes disso, comecemos “pelo começo”.

Entendendo o padrão Facade

Facade nada mais é do que a implementação de uma classe que encapsula outras classes em si para a resolução de um problema. Quando um desenvolvedor Delphi cria um DataModule ou um formulário, ele está, mesmo que não saiba disso, implementando Facade. Dentre os padrões de projeto em Delphi, este é o mais comum de todos.

Para implementarmos este padrão em uma aplicação Delphi, precisamos nos ater ao fato de que, invariavelmente, outros objetos estarão aninhados em um objeto que fará a interface entre o usuário e o algoritmo que resolverá o problema. Esses objetos aninhados nunca poderão ser acessados diretamente, mas isso não significa que não poderemos acessar sua instância através do objeto de Facade. Apesar disso, é fortemente recomendado que apenas o objeto Facade tenha acesso aos objetos aninhados. Um exemplo muito simples pode ser visto aqui:

Como pode ser visto neste exemplo, da coleção de padrões de projeto em Delphi, o Facade é o mais simples de se implementar. A classe TCalculadora encapsula instâncias das classes TSoma, TSubtracao, TMultiplicacao e TDivisao. Como resultado disso, os métodos Soma, Subtrai, Multiplica e Divide podem ser acessados apenas através de uma instância de TCalculadora. Assim, a interface entre o usuário e os objetos que implementam os cálculos é feita através dessa única instância “visível” a ele, permitindo que o usuário faça uso de um único objeto para resolver algum problema.

Como funciona uma Abstract Factory

Como foi citado lá no início do artigo, para implementar padrões de projeto em Delphi, principalmente uma Abstract Factory, é necessário utilizar uma versão mais atualizada do IDE. Isso se deve ao fato de que é necessário utilizar uma implementação de Generics presente no Delphi à partir da versão 2009. Para isso, utilizaremos uma instância de um TObjectDictionary<TKey,TValue>.

Para facilitar as coisas, as classes TSoma, TSubtracao, TMultiplicacao e TDivisao terão um ancestral comum: a classe TOperacao. Uma das determinações da implementação de uma Abstract Factory em Delphi implica em fazer com que todos os construtores e destrutores sejam os mesmos em todas as classes controladas por ela.

Como queremos facilitar futuras implementações evolutivas de nosso sistema, devemos dividir nossas classes em diversas units. Assim, cada classe estendida de TOperacao poderá efetuar seu registo na Abstract Factory.

Com a classe TOperacao implementada, podemos implementar nossa Abstract Factory.

Antes de continuarmos, vamos a alguns esclarecimentos:

  • Para facilitar a indexação do nosso dicionário, a chave foi estabelecida como string;
  • Como queremos que a factory retorne um objeto concreto, o tipo armazenado no dicionário é um TOperacaoClass;
  • Implementamos um método para registro de classes na factory, o que facilitará novas implementações;
  • E implementamos um método para obtermos um objeto concreto através de sua chave.

Apesar do conceito parecer complexo, vimos que sua implementação é extremamente simples. Dentre as implementações de padrões de projeto em Delphi, o padrão Abstract Factory é, com certeza, um dos mais úteis em termos de arquitetura.

Eis que surge o Singleton

Outro dos padrões de projeto em Delphi que implementamos sem perceber é o Singleton. Toda vez que implementamos uma instância única de um objeto, como a instância do formulário principal de uma aplicação ou a conexão com o banco de dados, estamos implementando Singleton. Mas, para que nossa aplicação seja realmente eficiente, precisamos fazer com que a classe que abrigará o Singleton gerencie sua própria instância.

No nosso caso, queremos que nossa factory se comporte como Singleton. Para tanto, vamos fazer uma pequena implementação na nossa classe TFactory.

Para que nossa factory possa controlar sua própria instância, criamos uma variável para abrigá-la e a retornamos através do método estático Instance. Sendo assim, ao invocarmos TFactory.Instance, o método verificará se já há uma instância dela nesta variável. Se não houver, ela será criada pelo próprio método. E, como resultado, este entregará a instância que consta na variável FFactory.

E lá vamos nós…

Como já implementamos nossa factory, podemos implementar nossas classes para as quatro operações básicas.

Até aqui, nada demais. Mas, claro, para compreender completamente o que está sendo abordado neste artigo, você precisa ter um bom conhecimento sobre orientação a objetos com Delphi. Mas, mesmo assim, vamos aos esclarecimentos:

  • A seção initialization de cada unit garante que a própria classe fará seu registro na factory assim que for linkada em tempo de compilação;
  • Ao efetuarmos o registro de cada classe na factory, garantiremos que uma instância dela estará disponível a cada unit que invocá-la em sua cláusula uses e;
  • Essa mágica toda só é possível se adicionarmos todas as units, tanto da factory quanto das classes, ao projeto.

E, com a implementação destes 3 padrões de projetos em Delphi, seremos capazes de dar uma aplicação prática a eles.

Ah, meu primeiro programa usando padrões de projeto em Delphi

Como todo bom artigo que se preze, aqui também teremos um exemplo prático da utilização dos fontes que já vimos. E, como não poderia deixar de ser, nosso “projeto” será uma “calculadora”! Não vou entrar em detalhes sobre como criar um projeto, formulários, componentes, etc., pois acredito que todos saibam o que estão fazendo a esse respeito. Se você ainda não está familiarizado com isso, sem problemas. Mas recomendo outras leituras antes de você continuar.

Bem, vamos direto ao assunto. Veja abaixo como ficará o formulário principal da nossa aplicação:

Padrões de projeto em Delphi

Para demonstrar a flexibilidade da implementação destes 3 padrões de projeto em Delphi, o ComboBox de operações será preenchido dinamicamente durante a criação do formulário. Então, essencialmente, nossa aplicação terá apenas 2 métodos no formulário principal: um para preencher o ComboBox e limpar os Edits e outro no botão Efetuar que, como é de se esperar, fará a operação.

E, abaixo, está o código fonte do formulário principal:

Como se trata de um artigo mais didático, o código fonte do formulário está bem detalhado – incluindo a variável bufOperacoes, desnecessária, pois poderíamos acessar o array de chaves registradas na factory diretamente, mas achei mais elegante demonstrar essa funcionalidade no código.

Abaixo, seguem imagens do nosso programa em operação:

Padrões de projeto em Delphi

Padrões de projeto em Delphi

E assim, construímos nosso primeiro programa utilizando padrões de projeto em Delphi.

E como ficam as implementações?

Como gosto de frisar, este modelo de implementação é o ideal para sistemas que trabalham de maneira evolutiva, onde os desenvolvedores podem evoluir a aplicação sem muita intervenção na interface com o usuário. Aplicando estes padrões de projeto em Delphi, você terá uma aplicação incrivelmente simples e com alta capacidade de manutenção, totalmente desacoplada e, claro, que pode se manter por muito mais tempo do que os modelos “tradicionais”.

E, para demonstrar essa maravilha, vamos desenvolver apenas mais uma classe e vamos adicioná-la ao projeto, sem escrever mais uma linha de código sequer no formulário principal.

Ao adicionarmos esta classe ao nosso projeto e recompilarmos a aplicação, ela já poderá ser utilizada, sem qualquer outra implementação.

Padrões de projeto em Delphi

Padrões de projeto em Delphi

Finalizando…

Com todas as evoluções ocorridas na linguagem e o no IDE, é impossível pensar em desenvolvimento de aplicações sem pensar na implementação de padrões de projeto em Delphi. Uma das aplicações mais viáveis e, claro, mais interessantes de se fazer é utilizando o Datasnap em APIs restful, onde posso ter apenas um único endpoint para receber minhas solicitações e efetuar minhas operações, facilitando a vida de quem vai desenvolver a aplicação cliente (que pode ser você mesmo).

E, para uma próxima oportunidade, exploraremos esse modelo de desenvolvimento em uma API RESTful utilizando DataSnap no Delphi Sydney.

Ah, o código fonte deste artigo pode ser baixado aqui, na íntegra.

Até mais!

Sobre Willian Tuttoilmondo 12 Artigos
Arquiteto de software com mais de 25 anos de experiência em desenvolvimento de software, especialista em desenvolvimento multicamadas utilizando Embarcadero Delphi e NodeJS para o back-end e o próprio Delphi para o front-end. Usuário Linux desde 1998, é evangelista PostgreSQL, banco de dados no qual é especialista. Ocupa hoje a posição de arquiteto de software na TOTVS, a maior empresa de tecnologia do Brasil, além de ser sócio fundador da LT Digital Labs, empresa especializada em desenvolvimento e treinamentos.

1 Trackback / Pingback

  1. Construindo APIs RESTful nível 3 com Delphi e Datasnap

Faça um comentário

Seu e-mail não será publicado.


*