Durante muito tempo, o Delphi foi sinônimo de Programação Orientada a Objetos (POO) pura. No entanto, com a evolução da linguagem (especificamente a partir do Delphi 2009), ganhamos recursos poderosos que nos permitem adotar um estilo de Programação Funcional.
O recurso mais emblemático dessa mudança são os Métodos Anônimos. Eles não servem apenas para “escrever menos código”; eles mudam fundamentalmente a maneira como podemos arquitetar soluções, permitindo o desacoplamento de lógica e a criação de códigos muito mais seguros e elegantes.
Neste artigo, vamos explorar como tratar código como dados e implementar um padrão robusto para transações de banco de dados que eliminará centenas de linhas repetitivas do seu projeto.
O Que São Métodos Anônimos?
Diferente dos ponteiros de função tradicionais ou dos eventos (of object), um método anônimo é um bloco de código definido inline, que pode ser atribuído a uma variável ou passado como parâmetro para outro método.
A sintaxe baseia-se na declaração reference to:
type
TMinhaProc = reference to procedure(Texto: string);
No entanto, a unidade System.SysUtils já nos fornece tipos genéricos prontos para uso:
TProc/TProc<T>: Para procedimentos (sem retorno).TFunc<Result>/TFunc<T, Result>: Para funções (com retorno).
O “Pulo do Gato”: Variable Capturing (Closures)
A característica mais poderosa dos métodos anônimos no Delphi é a capacidade de capturar variáveis. O método anônimo pode acessar e modificar variáveis do escopo onde ele foi criado, mesmo que esse escopo já tenha deixado de existir na pilha de execução. Isso é conhecido na ciência da computação como Closure.
O Problema: A Repetição do Boilerplate de Transação
Quem trabalha com banco de dados conhece o padrão exaustivo necessário para garantir a integridade dos dados. Em quase todo botão de “Salvar”, vemos algo assim:
// O jeito "velho" e verboso
DM.Connection.StartTransaction;
try
try
// Lógica de negócio complexa...
Table1.Post;
Table2.Post;
DM.Connection.Commit;
except
DM.Connection.Rollback;
raise; // Relança o erro para a UI tratar
end;
finally
// Limpezas eventuais
end;
O problema desse código não é apenas a verbosidade. É o Risco. Se um desenvolvedor esquecer o Rollback no except, ou colocar o Commit no lugar errado, a integridade do banco é comprometida.
A Solução Funcional: Encapsulamento com Callbacks
Podemos usar métodos anônimos para criar um “Wrapper” (envoltório). A ideia é criar um método que sabe como gerenciar a transação, mas não sabe o que será executado dentro dela. O “o que” será passado via método anônimo.
Vamos criar uma classe utilitária para isso:
1. A Implementação do Wrapper
uses
System.SysUtils, FireDAC.Comp.Client; // Exemplo com FireDAC
type
TDBHelper = class
public
class procedure ExecutarTransacao(Conexao: TFDConnection; Acao: TProc);
end;
class procedure TDBHelper.ExecutarTransacao(Conexao: TFDConnection; Acao: TProc);
begin
// Validações iniciais
if not Assigned(Acao) then Exit;
// Inicia a transação
Conexao.StartTransaction;
try
try
// AQUI acontece a mágica: executamos o bloco de código injetado
Acao();
// Se passou por aqui sem erro, comita
Conexao.Commit;
except
// Se deu erro, desfaz tudo
Conexao.Rollback;
raise; // Relança a exceção para quem chamou saber que falhou
end;
except
on E: Exception do
begin
// Log de erro opcional ou tratamento específico
raise;
end;
end;
end;
2. O Uso Elegante
Agora, veja como fica o código no formulário ou na camada de regra de negócios. Não precisamos mais escrever StartTransaction, Commit ou Rollback. Focamos apenas no negócio.
procedure TForm1.BtnSalvarClick(Sender: TObject);
var
ValorTotal: Currency;
ClienteID: Integer;
begin
// Capturando variáveis locais para usar dentro do método anônimo
ValorTotal := 150.00;
ClienteID := 10;
TDBHelper.ExecutarTransacao(FDConnection1,
procedure
begin
// Este código roda DENTRO da proteção da transação
// Note que acessamos 'ValorTotal' e 'ClienteID' (Closure)
ServicoPedido.CriarCabecalho(ClienteID);
ServicoPedido.AdicionarItem('Produto A', ValorTotal);
// Se qualquer linha aqui der erro, o TDBHelper fará o Rollback automaticamente.
end);
ShowMessage('Venda processada com sucesso!');
end;
Vantagens Desta Abordagem
- Segurança: É impossível esquecer de dar Rollback em caso de erro, pois essa lógica está centralizada no
TDBHelper. - Legibilidade: O código de negócio fica limpo, sem a poluição visual dos blocos
try..exceptde infraestrutura. - Manutenibilidade (DRY): Se amanhã você precisar mudar a forma como a transação é tratada (ex: adicionar logs de auditoria ou retries automáticos), você altera em um único lugar, e não em 500 formulários.
- Desacoplamento: A rotina de infraestrutura não conhece a regra de negócio, e a regra de negócio não precisa saber detalhes de baixo nível da transação.
Conclusão
O uso de métodos anônimos aproxima o Delphi de paradigmas modernos encontrados em linguagens como JavaScript ou C#. Ao tratar blocos de código como parâmetros, ganhamos um poder imenso de abstração.
O exemplo da transação é apenas a ponta do iceberg. Você pode usar essa mesma técnica para:
- Executar código em background (
TTask.Run). - Criar sistemas de Log centralizados.
- Implementar padrões de Retry (tentar executar algo 3 vezes antes de falhar).
Dominar métodos anônimos é essencial para escrever o Delphi moderno (“Clean Code”) que o mercado atual exige.
Referências
Descubra mais sobre Régys Borges da Silveira
Assine para receber nossas notícias mais recentes por e-mail.
Dê-nos sua opinião, seu comentário ajuda o site a crescer e melhorar a qualidade dos artigos.