
Índice
Introdução
Neste post, vamos explorar técnicas para gerenciamento de dependências em Delphi de maneira eficaz em Delphi e introduzir o uso da injeção de dependência (Dependency Injection – DI) na linguagem.
O gerenciamento de dependências é um aspecto crucial na arquitetura de software, especialmente em projetos complexos e de larga escala. Em Delphi, um gerenciamento eficaz de dependências pode fazer a diferença entre um código robusto, manutenível e extensível, e um código frágil, difícil de entender e modificar.
Técnicas para Gerenciar Dependências de Maneira Eficaz
1. Modularização
A modularização consiste em dividir o sistema em módulos independentes e bem definidos. Cada módulo deve ter uma responsabilidade clara e ser o mais independente possível dos outros. Em Delphi, isso pode ser feito utilizando units e pacotes.
Exemplo:
// Unit para lógica de negócio unit BusinessLogic; interface uses DataAccess; type TBusinessLogic = class private FDataAccess: TDataAccess; public constructor Create(ADataAccess: TDataAccess); procedure ExecuteBusinessRule; end; implementation constructor TBusinessLogic.Create(ADataAccess: TDataAccess); begin FDataAccess := ADataAccess; end; procedure TBusinessLogic.ExecuteBusinessRule; begin FDataAccess.GetData; // Implementação da regra de negócio end; end.
2. Uso de Interfaces
O uso de interfaces ajuda a reduzir o acoplamento entre componentes do sistema. Em vez de depender diretamente de implementações concretas, dependa de interfaces. Isso facilita a substituição de implementações e a realização de testes unitários.
Exemplo:
// Interface para acesso a dados unit DataAccessInterface; interface type IDataAccess = interface ['{00000000-0000-0000-0000-000000000000}'] procedure GetData; end; implementation end.
3. Factory Pattern
O padrão de projeto Factory é usado para criar objetos sem expor a lógica de criação ao cliente. Isso permite que o código cliente dependa de abstrações (interfaces) e não de implementações concretas.
Exemplo:
// Implementação da fábrica unit DataAccessFactory; interface uses DataAccessInterface, DataAccess; type TDataAccessFactory = class public class function CreateDataAccess: IDataAccess; end; implementation class function TDataAccessFactory.CreateDataAccess: IDataAccess; begin Result := TDataAccess.Create; end; end.
Introdução ao Uso de Injeção de Dependência em Delphi
A injeção de dependência (DI) é uma técnica para alcançar a Inversão de Controle (IoC) entre classes e suas dependências. Em vez de uma classe criar suas dependências diretamente, elas são fornecidas (injetadas) a ela. Isso aumenta a modularidade e facilita os testes unitários.
1. Injeção de Dependência Simples
A injeção de dependência pode ser feita manualmente, passando dependências através de construtores ou métodos.
Exemplo:
// Implementação de uma classe que utiliza DI unit BusinessLogic; interface uses DataAccessInterface; type TBusinessLogic = class private FDataAccess: IDataAccess; public constructor Create(ADataAccess: IDataAccess); procedure ExecuteBusinessRule; end; implementation constructor TBusinessLogic.Create(ADataAccess: IDataAccess); begin FDataAccess := ADataAccess; end; procedure TBusinessLogic.ExecuteBusinessRule; begin FDataAccess.GetData; // Implementação da regra de negócio end; end.
2. Uso de Containers de Injeção de Dependência
Containers de injeção de dependência automatizam a criação e injeção de dependências. Um exemplo popular em Delphi é o Spring4D.
Configuração do Spring4D
Para utilizar o Spring4D, primeiro adicione a biblioteca ao seu projeto Delphi.
uses Spring.Container, Spring.Services, DataAccessInterface, DataAccess, BusinessLogic; procedure ConfigureContainer; begin GlobalContainer.RegisterType<TDataAccess>.Implements<IDataAccess>; GlobalContainer.RegisterType<TBusinessLogic>; GlobalContainer.Build; end;
3. Uso do Container em Código
Depois de configurar o container, você pode resolver (criar) instâncias de classes com suas dependências automaticamente injetadas.
Exemplo:
var BusinessLogic: TBusinessLogic; begin ConfigureContainer; BusinessLogic := GlobalContainer.Resolve<TBusinessLogic>; BusinessLogic.ExecuteBusinessRule; end;
Exemplo Completo Passo a Passo
Claro! Vamos melhorar o código para que ele funcione como um exemplo completo e claro de uso de Injeção de Dependência (DI) em Delphi, utilizando a biblioteca Spring4D.
Passos
- Instale a biblioteca Spring4D disponível no seguinte link: https://bitbucket.org/sglienke/spring4d/src/master/
- Criar a Interface de Acesso a Dados (
DataAccessInterface.pas
). - Implementar a Classe de Acesso a Dados (
DataAccess.pas
). - Implementar a Classe de Lógica de Negócio (
BusinessLogic.pas
). - Configurar o Contêiner de Dependências.
- Executar o Código.
Código Completo
DataAccessInterface.pas
unit DataAccessInterface; interface type IDataAccess = interface ['{E50F5D4A-EC2D-4D38-BD68-5E7A47D4A2C2}'] procedure GetData; end; implementation end.
DataAccess.pas
unit DataAccess; interface uses Vcl.Dialogs, DataAccessInterface; type TDataAccess = class(TInterfacedObject, IDataAccess) public procedure GetData; end; implementation procedure TDataAccess.GetData; begin //recuperar dados do banco de dados ShowMessage('Data retrieved from the database.'); end; end.
BusinessLogic.pas
unit BusinessLogic; interface uses Vcl.Dialogs, DataAccessInterface; type TBusinessLogic = class private FDataAccess: IDataAccess; public constructor Create(ADataAccess: IDataAccess); procedure ExecuteBusinessRule; end; implementation constructor TBusinessLogic.Create(ADataAccess: IDataAccess); begin FDataAccess := ADataAccess; end; procedure TBusinessLogic.ExecuteBusinessRule; begin FDataAccess.GetData; // Implementação da regra de negócio ShowMessage('Business rule executed.'); end; end.
Configuração do Contêiner de Dependências e Execução
Crie um novo projeto de Windows VCL Application – Delphi e adicione os arquivos acima. No formulário principal do projeto (.dpr
), configure o contêiner e execute a lógica de negócio:
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Spring.Container, DataAccessInterface, DataAccess, BusinessLogic; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private procedure ConfigureContainer; { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ConfigureContainer; begin GlobalContainer.RegisterType<TDataAccess>.Implements<IDataAccess>; GlobalContainer.RegisterType<TBusinessLogic>; GlobalContainer.Build; end; procedure TForm1.Button1Click(Sender: TObject); var BusinessLogic: TBusinessLogic; begin try ConfigureContainer; BusinessLogic := GlobalContainer.Resolve<TBusinessLogic>; BusinessLogic.ExecuteBusinessRule; except on E: Exception do ShowMessage(E.ClassName+ ': '+ E.Message); end; end; end.
Explicação do Código
- Interface de Acesso a Dados (
DataAccessInterface
):- Define a interface
IDataAccess
com um métodoGetData
.
- Define a interface
- Classe de Acesso a Dados (
DataAccess
):- Implementa a interface
IDataAccess
. - Método
GetData
simula a recuperação de dados de um banco de dados.
- Implementa a interface
- Classe de Lógica de Negócio (
BusinessLogic
):- Recebe uma implementação de
IDataAccess
via injeção de dependência. - Método
ExecuteBusinessRule
usaIDataAccess
para obter dados e executa uma regra de negócio.
- Recebe uma implementação de
- Configuração do Contêiner de Dependências:
- Registra
TDataAccess
como a implementação deIDataAccess
. - Registra
TBusinessLogic
para ser resolvida pelo contêiner. - Constrói o contêiner.
- Registra
- Execução:
- Configura o contêiner de dependências.
- Resolve uma instância de
TBusinessLogic
a partir do contêiner. - Chama
ExecuteBusinessRule
para demonstrar a injeção de dependência em ação.
Este exemplo demonstra como configurar e usar injeção de dependência em Delphi com a biblioteca Spring4D, proporcionando um código mais modular e testável.
Veja abaixo a ilustração do projeto:

Código fonte do exemplo
Você pode fazer o download do exemplo do projeto através do repositório do github:
https://github.com/Gisele-de-Melo/Gerenciamento_de_Dependencias
Conclusão
O gerenciamento eficaz de dependências é fundamental para manter um código Delphi robusto e de fácil manutenção. A modularização, o uso de interfaces, o padrão Factory e a injeção de dependência são técnicas poderosas que ajudam a alcançar esse objetivo. A injeção de dependência, em particular, promove a inversão de controle e facilita a substituição de implementações, além de tornar os testes unitários mais simples e eficazes.
A implementação dessas técnicas pode exigir um esforço inicial, mas os benefícios a longo prazo em termos de manutenibilidade e extensibilidade do código compensam amplamente esse investimento. Ao aplicar essas práticas, você estará preparado para desenvolver sistemas Delphi mais flexíveis, modulares e fáceis de testar e manter.