Fluent Interface no Delphi

Boa noite, pessoal!
Sejam bem-vindos à “quinta temporada” de artigos! Dessa vez não fiz a pausa, já que fiquei ausente um bom tempo há alguns meses.
Antes de retornar aos assuntos envolvendo Engenharia de Software, decidi apresentar uma série de pequenos artigos sobre Delphi. Neste primeiro artigo, o assunto é Fluent Interface!

 

Já ouviu falar em Fluent Interface? Trata-se de um padrão de desenvolvimento de software que permite o encadeamento de métodos para facilitar a escrita e leitura do código. Em outras palavras, é uma técnica que possibilita chamadas seriais dentro do escopo de um mesmo objeto. Um dos propósitos deste padrão é aproximar o código-fonte de uma linguagem natural, como se estivéssemos codificando uma “frase”.

 

Exemplo 1

Sem delongas, apresentarei um exemplo pequeno como introdução deste assunto.
Suponha que seja necessário importar alguns dados, como nomes de cidades, que estejam em um formato fora do padrão semelhante ao texto abaixo:

" Rio+de+janeiro "

Durante essa importação, deseja-se aplicar três regras:

  • Remover os espaços em branco no início e no final do texto;
  • Converter as letras para maiúsculas;
  • Substituir um caracter (“+” por espaço).

Como você escreveria este código? Com Trim, UpperCase e StringReplace, certo?

var
  Cidade: string;
begin
  Cidade := ' Rio+de+janeiro ';
  Cidade := Trim(Cidade);
  Cidade := UpperCase(Cidade);
  Cidade := StringReplace(Cidade, '+', ' ', [rfReplaceAll]);
end;

Embora o código acima seja válido, há uma maneira de melhorá-lo. Nas versões mais recentes do Delphi, é possível usar Fluent Interface para “encadear” estes três métodos:

var
  Cidade: string;
begin
  Cidade := ' Rio+de+janeiro ';
  Cidade := Cidade.Trim.ToUpper.Replace('+', ' ', [rfReplaceAll]);
end;

Bem melhor, não? Todo o código fica em apenas uma linha sem comprometer a leitura. Na verdade, pode-se dizer que o código tornou-se mais legível, não acham?

 

Exemplo 2

Dessa vez, imagine que seja preciso copiar as 10 primeiras letras de um texto e verificar se existe a palavra “INFO”. Vejam só:

var
  Texto: string;
begin
  Texto := 'StatusInfoJunho2018LogProcessamento';
 
  if Copy(Texto, 1, 10).ToUpper.Contains('INFO') then
    ShowMessage('Existe a palavra INFO!');
end;

Fácil, hein? 🙂

 

Fluent Interface na RTL

Agora que vocês já conhecem o Fluent Interface, certamente encontrará algumas aplicações na própria RTL do Delphi. A classe TStringBuilder é um exemplo clássico:

var
  StringBuilder: TStringBuilder;
begin
  StringBuilder := TStringBuilder.Create;
 
  StringBuilder
    .Append('Atalhos do Sistema:')
    .AppendLine.AppendLine
    .Append('F1 - Ajuda').AppendLine
    .Append('F4 - Relatórios').AppendLine
    .Append('F10 - Opções');
 
  ShowMessage(StringBuilder.ToString);
 
  StringBuilder.Free;
end;

O código acima produz o seguinte resultado:

 

Desenvolvendo classes com Fluent Interface

Ao invés de apenas consumir este recurso, também podemos criá-lo em nossas classes. Para isso, basta que as suas funções retornem o próprio objeto. Na classe de exemplo abaixo, responsável por armazenar colunas de uma instrução SQL, foi aplicado o Fluent Interface no método AddColumn:

type
  TSQLBuilder = class
  private
    FColumns: TStringList;
  public
    function AddColumn(const aColumn: string): TSQLBuilder;
  end;
 
{ TSQLBuilder }
 
function TSQLBuilder.AddColumn(const aColumn: string): TSQLBuilder;
begin
  FColumns.Add(aColumn);
  result := Self; // retorna a própria instância
end;

Como a função retorna o próprio objeto (Self), podemos utilizar a classe dessa forma:

var
  SQLBuilder: TSQLBuilder;
begin
  SQLBuilder := TSQLBuilder.Create;
 
  SQLBuilder
    .AddColumn('Codigo')
    .AddColumn('Nome')
    .AddColumn('Cidade')
    .AddColumn('UF');
 
  { ... }
end;

 

Espero que tirem bom proveito deste recurso, pessoal.
Grande abraço e até logo!


 

7 comentários

  1. Boa noite, André,

    Recurso muito interessando e útil, e por coincidência, hoje tive que usar o “Trim” e “UpperCase” para um tratamento… graças a você, e por mais um ensinamento, é mais uma melhoria que irei aplicar no meu sistema.
    Parabéns e grande abraço.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.