Blog Como criar métodos encadeados com Fluent Interface?

Como criar métodos encadeados com Fluent Interface?

Como criar métodos encadeados com Fluent Interface? post thumbnail image

A Fluent Interface é um padrão de design que permite encadear métodos para criar um código mais legível, parecido com uma linguagem natural. Esse padrão é particularmente útil em cenários complexos, como o de configuração e emissão de documentos fiscais, onde diversos parâmetros precisam ser definidos antes de uma ação ser executada.

Neste artigo, exploraremos como implementar esse padrão em Delphi, aplicando-o a um caso real: a emissão de uma Nota Fiscal Eletrônica (NF-e). A implementação demonstrará como utilizar métodos fluentes para configurar dados obrigatórios, como emitente, destinatário e itens da nota, finalizando com a validação e geração da NF-e.

Implementação de Fluent Interface para NF-e

Vamos imaginar um cenário de emissão de uma NF-e, onde precisamos configurar diferentes aspectos: emitente, destinatário, itens e tributos. Abaixo está a implementação com métodos fluentes.

A Classe Principal TNFeBuilder

Exemplo de Uso:

Saída do XML Gerado

Explicando o Código: Conceitos Aplicados

O padrão Fluent Interface utiliza uma técnica simples, porém poderosa, para possibilitar o encadeamento de métodos: retornar a própria instância da classe (Self). Isso permite que cada método execute sua operação e, ao mesmo tempo, devolva o controle ao objeto que iniciou a sequência. Aqui estão os principais conceitos aplicados no código:

  1. O Uso de Self para Encadeamento

No código, cada método que modifica ou configura a classe termina com a seguinte linha:

O Self é uma referência para a própria instância do objeto que está executando o método. Quando o método retorna essa instância, é possível continuar chamando outros métodos sem sair do contexto do objeto. Isso cria o efeito de “fluidez” que caracteriza o padrão Fluent Interface.

Exemplo prático:

No método SetEmitente, configuramos o emitente e retornamos a instância:

Ao encadear chamadas, como em:

2. Manutenção do Estado Interno do Objeto

Cada método modifica o estado interno do objeto (TNFeBuilder), atualizando os atributos privados. Isso assegura que os dados sejam acumulados à medida que os métodos são encadeados.

Exemplo:

O método AddItem adiciona um item à lista interna e recalcula o total:

Ao encadear múltiplos itens:

Os itens são adicionados à lista interna FItens, e o total é atualizado após cada adição.

3. Retorno Diferente no Último Método

O último método no encadeamento (GerarXML) não retorna a instância da classe. Em vez disso, ele retorna um resultado final (uma string com o XML). Essa abordagem permite finalizar o fluxo com o dado esperado, sem interromper o padrão fluente.

Exemplo:

Essa distinção garante que, enquanto os métodos de configuração e processamento retornam a instância para continuar o encadeamento, o método final entrega o resultado da operação.

4. Vantagens do Fluent Interface

  • Legibilidade: O código resultante é claro, com métodos que se comportam como frases descritivas.
  • Manutenção: As configurações são aplicadas no mesmo objeto, centralizando o estado e reduzindo variáveis temporárias.
  • Encapsulamento: Todos os detalhes de implementação são ocultos. O desenvolvedor interage apenas com os métodos necessários.
Comparação:

Sem Fluent Interface:

Com Fluent Interface:

Encadeamento Avançado com Retorno à Classe Pai

Vamos avançar um pouco mais? E se quisermos ter outras classes para preenchimento?

O conceito de encadeamento avançado com retorno à classe pai resolve um problema recorrente em APIs fluentes: a necessidade de navegar entre configurações de componentes subordinados sem perder o contexto do objeto principal. Esse modelo é especialmente útil em cenários onde partes específicas de uma configuração (como itens em uma nota fiscal) têm regras ou estruturas próprias, mas ainda precisam fazer parte de um contexto maior, representado pela classe pai.

Motivo para Fazer Isso

A abordagem de retornar à classe pai é necessária quando:

  1. Modularidade: Partes do sistema, como itens, tributos ou pagamentos, possuem lógica própria e precisam ser organizadas em classes separadas para melhorar a coesão. Isso evita que a classe principal fique sobrecarregada com responsabilidades que poderiam ser delegadas.
  2. Encadeamento Natural: Para que a API fluente seja contínua e legível, os métodos de uma classe subordinada (como AddItem) precisam retornar ao fluxo principal ao final de suas operações. O uso de um método como &End permite retornar à classe pai sem quebrar o padrão fluente.
  3. Reuso de Componentes: Com componentes subordinados encapsulados em classes específicas (como TItens), é possível reutilizá-los em diferentes contextos, sem necessidade de replicar lógica na classe principal.
  4. Hierarquia de Configuração: No exemplo de emissão de NF-e, as configurações possuem uma hierarquia natural: o cabeçalho pertence ao documento principal, enquanto os itens e seus detalhes pertencem a uma parte específica dessa estrutura. Essa hierarquia deve ser refletida no design das classes.

Vantagens do Retorno à Classe Pai

  1. Legibilidade e Fluidez: O código gerado é mais próximo de uma linguagem natural. Desenvolvedores podem configurar diferentes partes do objeto sem perder o encadeamento ou criar blocos confusos.Exemplo:

Esse fluxo é muito mais legível do que manter todas as configurações em uma única classe.

Encapsulamento: Cada componente, como TItens, gerencia seu próprio estado e lógica, sem expor detalhes à classe principal. Isso melhora o design orientado a objetos, facilitando a manutenção e extensão do código.

Organização Modular: Com as classes subordinadas, a lógica específica fica isolada. Por exemplo, a lógica para adicionar itens à nota fiscal está completamente encapsulada em TItens. A classe principal (TNFeBuilder) foca em tarefas de alto nível, como gerar o XML.

Extensibilidade: Esse design facilita a adição de novos componentes ou funcionalidades. Caso seja necessário adicionar tributos ou pagamentos à NF-e, bastaria criar novas classes subordinadas e vinculá-las ao fluxo principal.

Menor Acoplamento: A classe subordinada (TItens) mantém uma referência à classe pai, mas o oposto não é verdadeiro. Isso reduz o acoplamento e melhora a flexibilidade do código.

Melhoria de Testabilidade: Componentes encapsulados podem ser testados isoladamente. Por exemplo, a funcionalidade de adicionar itens e calcular o total pode ser testada diretamente em TItens, sem interferir na lógica da classe principal.

Resumo

O encadeamento avançado com retorno à classe pai não é apenas uma questão de melhorar a legibilidade. Ele reflete boas práticas de design orientado a objetos, dividindo responsabilidades, reduzindo o acoplamento e tornando o código mais modular e testável. Em sistemas complexos, essa abordagem oferece uma combinação poderosa de flexibilidade, clareza e escalabilidade, essencial para aplicações robustas e fáceis de manter.

Vamos a um exemplo prático:

1. Classe TItens para Gerenciar os Itens

2. Classe TNFeBuilder para a NF-e

3. Implementação dos Métodos

Métodos da Classe TItens

4. Exemplo de Uso

Saída do XML Gerado

Explicando o Funcionamento

  • Retorno à Classe Pai (&End):
    A função &End da classe TItens retorna a instância da classe TNFeBuilder, armazenada em FParent. Isso permite continuar o encadeamento no objeto principal após configurar os itens.
  • Referência Cruzada:
    A classe TItens conhece sua classe pai (TNFeBuilder), mas o oposto não ocorre diretamente. Isso garante encapsulamento, permitindo que TItens administre apenas os dados relacionados aos itens.
  • Legibilidade:
    Esse modelo de encadeamento dentro de encadeamentos melhora a organização e torna o código mais expressivo e próximo da linguagem natural.

Participe da Comunidade no Telegram

🚀 Quer continuar essa discussão e trocar ideias com outros desenvolvedores? Junte-se à nossa comunidade no Telegram! Lá, você pode comentar sobre o que achou deste artigo, tirar suas dúvidas e compartilhar suas experiências com Delphi e ainda discutir ou tirar suas dúvidas sobre os mais variados temas em uma comunidade com mais de 1.000 desenvolvedores.

🔗 Clique aqui para entrar na comunidade

Te vejo lá!

Conclusão

O padrão Fluent Interface, combinado com o uso de Self, é uma ferramenta poderosa para criar APIs legíveis e práticas. No exemplo de emissão de NF-e, os métodos encadeados simplificam a configuração e emissão, proporcionando um fluxo natural. Ao dominar esse padrão, você melhora significativamente a qualidade e a clareza do código, beneficiando todo o ciclo de desenvolvimento.

Deixe sua resposta

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

Posts Relacionados