Se você ainda não ouviu o termo, vai ouvir logo logo. Interfaces fluentes dizem respeito às interfaces do seu sistema, à sua API. Isso significa os seus métodos, classes, e propriedades. Fluente quer dizer que elas funcionam de maneira que, quando você as lê, entende o que elas querem dizer, elas soam como uma frase. Seus nomes são fluentes.

Há alguns frameworks que usam muito isso. Recentemente tem se falado muito em Fluent Interfaces para NHibernate, onde o código para mapeamento é feito desta forma, substituindo os chatos xml de configuração do NH. Fica assim (tirado do blog do NH):

public class PostMap : ClassMap<Post>
{
    public PostMap()
    {
        Id(x => x.Id);
        Map(x => x.Title);
        Map(x => x.Body);
        Map(x => x.PublicationDate);
        HasMany<Comment>(x => x.Comments)
            .Component(c =>
                           {
                               c.Map(x => x.Text);
                               c.Map(x => x.AuthorEmail);
                               c.Map(x => x.CreationDate);
                           }).AsSet();
    }
}

O Rhino Mocks, framework de Mocks, também faz coisas parecidas. Você pode configurar uma expectativa em um objeto de Mock assim:

Expect.Call(repositorio.ObterPorId(id)).Return(cliente);

Fica simples de ler, certo?

E como você pode usar isso no seu código? Bom, eu peguei um exemplo bem legal do Jan Van Ryswyck, do Elegant Code, para mostrar. Não é a toa que o blog dele tem esse nome. Dêem uma olhada no que ele escreveu sobre interfaces fluentes nestes posts:

  1. Experimenting With Fluent Interfaces in the Domain
  2. Progressive Interface
  3. Be careful with the var keyword and expression builders

Peguei o primeiro post da lista e completei. A idéia é que uma categoria tem vários itens em um catálogo. Você pode adicionar itens à categoria. Um item tem a empresa que o fabricou (Manufacturer) e o produto (Product).

Modelo

O objetivo é adicionar items à categoria de maneirfa fluente.

Para entender o objetivo final, o resultado será esse:

            var category = new Category();
            category.Categorize(item =>item.Named("iPhone")
                .ManufacturedBy(manufacturer =>
                    manufacturer.Named("Apple"))
                    .ForProduct(product =>
                        product.Numbered("AA1687")));

Mais fluente impossível, não é?

Mas com interfaces fluentes nada é o que parece. Tudo é baseado em objetos construtores, os tais builders. Vou postar a solução aqui nos próximos posts, para ficar claro como isso está sendo feito. Eu já tinha visto isso várias vezes, achei legal dar uma olhada mais de perto e aprender a fazer. Você acaba praticamente construindo uma DSL para seu domínio. Fiquem ligados.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.