Design de software

Escape do inferno de inicialização com 8 parâmetros usando o Builder Pattern do Swift

Ao criar um app com Swift, chega um momento em que o código de inicialização fica assim.

4 min de leitura
Imagem de capa de Escape do inferno de inicialização com 8 parâmetros usando o Builder Pattern do Swift

Ao criar um app com Swift, chega um momento em que o código de inicialização fica assim.

User(name:age:email:phone:address:isVerified:profileURL:createdAt:)

Oito parâmetros dentro dos parênteses.

Ao olhar o código de chamada, você acaba contando um por um para descobrir qual valor é email e qual é phone.

Essa situação é comum até em projetos pessoais, mas o Builder Pattern do Swift resolve tudo de forma organizada.

Em resumo, inicializações com muitos parâmetros ficam muito mais legíveis quando o Builder Pattern permite configurá-los “um por linha”. Você não precisa memorizar a ordem nem preencher à força com nil os valores que não usa.

Veja primeiro um resumo do que você vai aprender neste artigo.

  1. Por que um init com 8 parâmetros causa erros
  2. Como o Builder Pattern resolve isso
  3. Como fica o código usado na prática com Swift
  4. Quando usar este padrão e quando evitá-lo

Por que um init com 8 parâmetros é um inferno?

Com três ou quatro parâmetros, normalmente não há grandes problemas.

O problema começa quando a quantidade aumenta.

Primeiro, é fácil errar a ordem. Se você passar phone no lugar de email e ambos forem String, o compilador não vai detectar.

Segundo, o tratamento de valores opcionais fica confuso. Até os valores que você não usa agora precisam ser preenchidos com nil, nil, nil.

Terceiro, o código de chamada fica longo e já não dá para entender de imediato qual objeto está sendo criado.

Quanto mais parâmetros, mais o init parece uma prova cheia de lacunas para preencher; e quanto mais lacunas, mais erros aparecem.

Um bug causado por trocar phone e profileURL de lugar pode consumir mais de um dia. Quando os tipos são iguais, esses erros passam realmente despercebidos.


O que é o Builder Pattern?

O Builder Pattern cria um objeto complexo preenchendo os valores um por um e finalizando-o no fim, em vez de criar tudo de uma vez.

Em vez de passar todos os valores na inicialização, você escolhe e configura apenas os necessários e recebe o objeto final por meio de um método como build().

Pense em fazer um pedido em um restaurante. Em vez de gritar todos os ingredientes de uma vez, você diz: “Pão integral, queijo extra e sem molho”, item por item.

Se o método que configura um valor importante retornar a si próprio, você pode encadear as chamadas usando pontos. Este é o builder mais simples.

final class UserBuilder {
    private var name = ""
    private var email: String?
    // Configure um valor e selfretorne-o para permitir o encadeamento
    func setName(_ v: String) -> Self { name = v; return self }
    func setEmail(_ v: String) -> Self { email = v; return self }
    func build() -> User { User(name: name, email: email) }
}

Como o método de configuração retorna Self, você pode encadear chamadas como .setName(...).setEmail(...).

É assim que uma chamada encadeada realmente funciona
É assim que uma chamada encadeada realmente funciona
Coloquei um builder e organizei tudo tomando café; fiquei muito mais tranquilo
Coloquei um builder e organizei tudo tomando café; fiquei muito mais tranquilo

Como usar o Builder Pattern no Swift?

Você provavelmente está mais curioso para saber como o código de chamada muda na prática.

Usando o builder criado antes, o código de criação do objeto fica assim.

// Configure apenas os valores necessários, com rótulos e sem se preocupar com a ordem
let user = UserBuilder()
    .setName("Seokwoo Lee")
    .setEmail("[email protected]")
    .build()
// Não é preciso preencher valores não usados com nil

Como você pode ver, não há motivo para se preocupar com a ordem. O nome do método funciona como um rótulo e impede estruturalmente erros como passar phone no lugar de email.

Para valores que não são usados, basta não chamar o método.

No Swift, também é comum criar o builder com uma struct em vez de uma class, ou passar uma closure para configurar tudo dentro de um bloco. Escolha de acordo com o estilo do projeto.

Usar métodos com rótulos elimina a preocupação com a ordem
Usar métodos com rótulos elimina a preocupação com a ordem

Quando usar o Builder Pattern e quando evitá-lo

Adicionar o padrão em todos os lugares só porque ele parece útil apenas aumenta o código.

Organizei meus critérios em uma tabela (com base na minha experiência em projetos pessoais até 2026).

Situação Recomendação
5 ou mais parâmetros, muitos valores opcionais Builder Pattern
Vários parâmetros do mesmo tipo Builder Pattern
2 ou 3 parâmetros, todos obrigatórios init normal
Valores simples e fixos init normal

Em resumo, se há poucos parâmetros e todos são obrigatórios, não há motivo para criar um builder.

Por outro lado, para um objeto grande com valores opcionais misturados, um builder é muito mais conveniente.

P. Criar um builder não aumenta ainda mais o código?

É verdade. A própria classe builder aumenta o código. Mas, se esse objeto é criado em vários lugares, o ganho de deixar os códigos de chamada mais limpos é maior.

P. O Swift tem parâmetros padrão. Não posso usar isso?

Com três ou quatro parâmetros, apenas os parâmetros padrão já são suficientes. O Builder Pattern mostra seu valor quando há muitos parâmetros e combinações variadas.


Se você está sofrendo com um init de 8 parâmetros, experimente aplicar o Builder Pattern exatamente nesse ponto. Não é preciso refazer tudo; começar pelo objeto mais complexo reduz o esforço. Boa programação!

Leitura recomendada