Builder seguro e elegante
Tags: designpatterns, java, builder, fluentapi
Published: 2020-07-24 20:59:58

[Builder][0] é um dos padrões de projeto da classe dos criacionais da [bíblia da Gangue dos Quadro][1]. Esse padrão permite construir objetos complexos passo a passo e um efeito colateral disso é uma construção fluente para os objetos. 

```java
var pessoa = Pessoa.builder().nome("João").sobrenome("das Couve").idade(36).build();
```

Dessa forma, o que observamos do uso de builder e sua popularização está muito mais ligado à substituição de um construtor com muitos parâmetros por um design mais fluente do que propriamente o a intenção da [GoF][1]:

>"...separação da construção de um objeto complexo da sua representação, de forma que o mesmo processo de construção possa criar diferentes representações."

Para diferenciar essa inteção do builder padrão, é comum chama-lo de *Fluent Interface Builder*.

O pattern está disponível nas IDEs para ser auto criado e ficou ainda mais conhecido no mundo Java através do [Projeto Lombok][2] que tirou um grande boilerplate e transformou em uma simples anotação.

Esse builder costuma ter o seguinte padrão:

```java
package builder;

public class Pessoa {
    private final String nome;
    private final String sobrenome;
    private final int idade;

    public Pessoa(String nome, String sobrenome, int idade) {
        this.nome = nome;
        this.sobrenome = sobrenome;
        this.idade = idade;
    }

    public static PessoaBuilder builder() { return new PessoaBuilder(); }

    // Getters and setters

    public static class PessoaBuilder {
        private String nome;
        private String sobrenome;
        private int idade;

        public PessoaBuilder nome(String nome) {
            this.nome = nome;
            return this;
        }

        public PessoaBuilder sobrenome(String sobrenome) {
            this.sobrenome = sobrenome;
            return this;
        }

        public PessoaBuilder idade(int idade) {
            this.idade = idade;
            return this;
        }

        public Pessoa build() { return new Pessoa(nome, sobrenome, idade); }
    }
}

```
Mas sempre me incomodou que o builder, possuindo muitos passos, poderia contribuir para que o desenvolvedor desatento chame o *build()* prematuramente, isto é, com o objeto ainda incompleto. Isso só seria percebido em tempo de execução com uma exceção, ou pior, com a tentativa frustrada de acesso àquela propriedade esquecida. 

Quando temos um construtor podemos impor que certos campos sejam *final* e isso obriga o desenvolvedor a preencher aqueles parâmetros, mas com o builder padrão, isso não é possível.

Esse incômodo, felizmente, acabou quando achei o artigo brilhante [Simple Implementation of Fluent Builder - Safe Alternative To Traditional Builder][3] do [Sergiy Yevtushenko][4].

Esse gênio resolveu o problema e ainda de uma forma extremamente elegante! 

```java
package builder;

public class Pessoa {
    private final String nome;
    private final String sobrenome;
    private final int idade;

    public Pessoa(String nome, String sobrenome, int idade) {
        this.nome = nome;
        this.sobrenome = sobrenome;
        this.idade = idade;
    }

    public static PessoaBuilder.Stage0 builder() {
        return nome -> sobrenome -> idade -> () -> new Pessoa(nome, sobrenome, idade);
    }

    private interface PessoaBuilder {
        interface Stage0 { Stage1 nome(String nome); }
        interface Stage1 { Stage2 sobrenome(String sobrenome); }
        interface Stage2 { Stage3 idade(int idade); }
        interface Stage3 { Pessoa build(); }
    }
}
```

Aqui, definimos, de forma obrigatória, os parâmetros e a ordem em que eles devem ser preenchidos. Nosso builder é construído com passos representados por interfaces funcionais. Por conveniência, inseri esses passos dentro de uma interface que se comporta aqui como um *namespace*.

1. O método builder retorna o primeiro estágio, uma classe que tem apena o método nome;
1. Este retorna uma classe que tem também um único método que, sobrenome;
1. Sobrenome retorna a Stage3 com o método build(),
1. O build cria um objeto Pessoa.

## Conclusão
O builder padrão é excelente quando se deseja dar ao desenvolvedor a flexibilidade de preencher os parâmetros que achar necessário, mantendo valores padrões para aqueles que não preencher. Para uma situação em que certos parâmetros não são opcionais, a solução apresentada é uma alternativa bastante enxuta e elegante.

## Referências
- [Builder][0]
- [Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos][1]
- [Lombok - Builder][2]
- [Simple Implementation of Fluent Builder safe alternative to traditional builder][3]
- [Sergiy Yevtushenko][4]

[0]: https://pt.wikipedia.org/wiki/Builder
[1]: https://www.amazon.com.br/Padr%C3%B5es-Projetos-Solu%C3%A7%C3%B5es-Reutiliz%C3%A1veis-Orientados/dp/8573076100/ref=asc_df_8573076100/?tag=googleshopp00-20&linkCode=df0&hvadid=379748659420&hvpos=&hvnetw=g&hvrand=16168119258048787299&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1001566&hvtargid=pla-812887614857&psc=1
[2]: https://projectlombok.org/features/Builder
[3]: https://dev.to/siy/simple-implementation-of-fluent-builder-safe-alternative-to-traditional-builder-3m1d
[4]: https://dev.to/siy