Boilerplate é o código repetitivo que os desenvolvedores escrevem com mudanças mínimas em cada novo módulo ou projeto. Ele não contém lógica de negócios única, mas simplesmente prepara a infraestrutura: configuração, importação de bibliotecas, manipuladores padrão e classes DTO. De acordo com o CodeScene Engineering Productivity Report (2025), o boilerplate constitui de 20 a 40 por cento de todo o código em um aplicativo comercial típico. O principal problema desse código não é que ele se repete, mas que cada repetição é um ponto de falha: um erro em uma cópia não se sincroniza com as outras, e os bugs se multiplicam pelo projeto. Automatizar a geração de boilerplate através de geração de código, anotações e macros é uma das maneiras mais eficazes de acelerar o desenvolvimento sem perder qualidade.
Pontos principais
Código boilerplate são fragmentos de código fonte que se repetem em diferentes partes do projeto com variações mínimas. O termo vem da indústria gráfica, onde boilerplate se referia a blocos de texto pré-escritos para jornais que não precisavam ser reescritos. Em programação, é qualquer código que você é forçado a escrever repetidamente para atender aos requisitos do framework, linguagem ou arquitetura.
Boilerplate não é dívida técnica no sentido clássico — não contém bugs e não viola os princípios SOLID. No entanto, aumenta a quantidade de código que precisa ser mantida, testada e lida. Cada linha de boilerplate é um local potencial para um erro de digitação que o compilador nem sempre consegue detectar.
De acordo com o relatório JetBrains Developer Ecosystem (2025), 67 por cento dos desenvolvedores consideram o boilerplate a principal causa de redução de produtividade. No desenvolvimento móvel, esse número é maior: projetos Android em Java contêm uma quantidade significativa de código repetitivo para findViewById, Intents, adaptadores RecyclerView e ContentProviders. Kotlin e Swift resolveram parte desses problemas com meios sintáticos, mas o boilerplate não desapareceu completamente.
Ao projetar a arquitetura, tente escolher soluções que minimizem o código repetitivo. Por exemplo, em vez de escrever manualmente a implementação Parcelable, use @Parcelize em Kotlin. Em vez de fábricas para ViewModel — Hilt com @HiltViewModel. Cada otimização dessas economiza horas de desenvolvimento na escala do projeto.
O exemplo mais reconhecível de boilerplate no desenvolvimento Android é o RecyclerView.Adapter. Antes do Kotlin e ViewBinding, cada adaptador exigia cerca de 80–100 linhas de código repetitivo: onCreateViewHolder, onBindViewHolder, getItemCount, classe ViewHolder interna, construtor, vinculação de campos. Com ViewBinding o código reduziu, mas não desapareceu completamente.
class UserAdapter(
private val users: List<User>
) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_user, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
holder.bind(users[position])
}
override fun getItemCount(): Int = users.size
class ViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
Glide.with(itemView)
.load(user.avatarUrl)
.into(itemView.avatar)
}
}
}
Outro exemplo ilustrativo é o mapeamento JSON em Java sem bibliotecas. Analisar manualmente uma resposta de API requer escrever dezenas de métodos, cada um verificando a existência de uma chave, obtendo o valor e atribuindo a um campo. Com bibliotecas como Gson, Moshi ou Kotlin Serialization — é uma anotação @Serializable.
No desenvolvimento iOS, o boilerplate clássico é a implementação de CodingKey e Decodable para cada resposta de API, especialmente quando as chaves JSON diferem dos nomes de propriedades em camelCase. Apesar da geração automática de Codable, a enumeração manual de CodingKeys continua sendo uma fonte de código repetitivo.
Use geração de código para criar boilerplate em tempo de compilação. No Android — Annotation Processing (KSP) para Room, Dagger, Moshi. No iOS — Sourcery para Codable e AutoMockable. Para cada hora gasta na configuração da geração, você economiza dias de cópia manual.
Boilerplate prejudica o projeto de três maneiras: retarda a escrita de novas funcionalidades, complica a leitura do código existente e cria pontos de dessincronização durante as alterações.
A lentidão no desenvolvimento é óbvia: o desenvolvedor gasta tempo escrevendo código que não contém lógica de negócios. Em vez de implementar um novo recurso (por exemplo, adicionar um campo ao perfil do usuário), ele escreve uma migração de BD, classe DTO, mapper para entidade de domínio, tela com campo de entrada, validação e testes para cada camada. A maior parte desse trabalho é mecânica.
A dessincronização é um problema mais insidioso. Quando uma estrutura de dados muda em um lugar (por exemplo, um campo é adicionado a uma resposta de API), o desenvolvedor deve atualizar o DTO, mapper, modelo, tela e testes. Se um lugar for omitido, o aplicativo compila, mas falha em tempo de execução ou — pior — exibe dados incorretos sem erro. Quanto mais camadas de boilerplate, maior a probabilidade dessa dessincronização.
Analise o projeto em busca de padrões repetidos. Se você vir três classes idênticas com nomes diferentes — é candidato para geração. Introduza a geração de código como parte da solução arquitetural, não como uma otimização pontual. Ela se paga a cada novo módulo.
A geração de código é a maneira mais confiável de combater o boilerplate. Em vez de escrever código repetitivo manualmente, o desenvolvedor descreve metadados (anotações, esquemas, configurações), e o gerador cria o código pronto em tempo de compilação.
No ecossistema Android, a ferramenta padrão de geração de código é o KSP (Kotlin Symbol Processing). Ele substitui o obsoleto KAPT e funciona mais rápido devido ao acesso direto ao AST do Kotlin sem gerar stubs Java. KSP é usado por Room (geração de implementações DAO), Moshi (geração de JsonAdapter), Glide (geração de classes de carregamento alvo) e Dagger (geração do grafo DI).
@Entity(tableName = "users")
data class UserEntity(
@PrimaryKey val id: Long,
@ColumnInfo(name = "full_name") val name: String,
@ColumnInfo(name = "avatar_url") val avatarUrl: String
)
@Dao
interface UserDao {
@Query("SELECT * FROM users WHERE id = :id")
suspend fun getById(@Param("id") id: Long): UserEntity?
}
No desenvolvimento iOS, o papel da geração de código é desempenhado pelo Sourcery — uma ferramenta que processa templates Stencil e gera código Swift baseado em anotações em comentários. Cenários típicos: AutoMockable (geração de mocks para testes), AutoCodable (implementação Decodable sem CodingKeys), AutoEquatable e AutoLenses.
Para projetos Flutter, o boilerplate é reduzido por geradores através do build_runner: json_serializable para mapeamento JSON, freezed para modelos imutáveis com copyWith, retrofit_generator para clientes API e injectable_generator para DI. Cada um desses geradores transforma 10–20 linhas de anotações em centenas de linhas de código pronto.
Anotações e macros são uma forma declarativa de dizer ao compilador ou pré-processador qual código gerar. O desenvolvedor não escreve a implementação, apenas marca a intenção, e o gerador transforma a marcação em código pronto.
O exemplo mais marcante é o Lombok em Java (historicamente) e a data class do Kotlin. Data class em Kotlin gera automaticamente equals, hashCode, toString, componentN e copy — em Java isso exigiria cerca de 80 linhas de código escrito à mão ou usar Lombok com @Data. Kotlin resolveu o problema no nível da linguagem, tornando o boilerplate implícito.
Em Swift, um papel similar é desempenhado pelos macros (Swift Macros, introduzidos no Swift 5.9). Em vez de escrever manualmente a implementação Codable, o desenvolvedor marca a struct com @Codable — e o compilador gera o código necessário. Outros macros integrados: @Observable (estado observável), @ResultBuilder (construtores de resultado) e @MainActor (despacho para a thread principal).
@Codable
struct UserProfile {
let id: Int
let displayName: String
let avatarURL: URL
let bio: String?
}
// @Codable macro generates:
// extension UserProfile: Codable { }
// private enum CodingKeys: String, CodingKey {
// case id, displayName, avatarURL, bio
// }
Ao escolher entre geração de código e macros, prefira macros se a linguagem os suportar. Macros funcionam no nível do compilador, não requerem configuração de scripts de build, não retardam a compilação (ao contrário do Annotation Processing) e estão sempre sincronizados com o código fonte. Se macros não estiverem disponíveis — use geradores externos via KSP, Sourcery ou build_runner.
Cada linguagem e plataforma oferece suas próprias ferramentas para minimizar o boilerplate. Abaixo estão práticas específicas para as principais stacks de desenvolvimento móvel.
| Plataforma | Ferramenta / Técnica | O que substitui |
|---|---|---|
| Android / Kotlin | data class | equals, hashCode, toString, copy, componentN |
| Android / Kotlin | @Parcelize | Implementação Parcelable |
| Android / Kotlin | ViewBinding / DataBinding | findViewById, ButterKnife |
| iOS / Swift | Codable + macros | Parsing manual de JSON, CodingKeys |
| iOS / Swift | Sourcery | AutoMockable, AutoEquatable, AutoLenses |
| Flutter / Dart | freezed + json_serializable | copyWith, classes seladas, equals/hashCode, JSON |
| Flutter / Dart | retrofit_generator | Cliente API com requisições e respostas tipadas |
Para frontend web (React Native / TypeScript), a principal ferramenta é a geração de tipos a partir da especificação OpenAPI (openapi-typescript, swagger-codegen). Cada endpoint obtém automaticamente uma requisição e resposta tipadas — o desenvolvedor não precisa descrever manualmente interfaces para centenas de chamadas de API.
Introduza a geração de código nas fases iniciais do projeto. Migrar um projeto existente para geradores é mais difícil do que projetar com eles desde o início. Se o projeto já estiver escrito — comece pelo ponto mais doloroso: Java → Kotlin (data class), adaptadores manuais → ListAdapter com DiffUtil, mapeamento JSON manual → Moshi / Kotlin Serialization.
Perguntas frequentes
Boilerplate não é dívida, mas redundância: o código está correto, mas há excesso. Dívida técnica é uma decisão de compromisso consciente que terá que ser corrigida depois. Boilerplate não requer correção — requer automação.
Não, em projetos pequenos o boilerplate pode ser justificado pela simplicidade: é imediatamente visível e fácil de alterar. O problema surge em escala — quando há mais de dez módulos semelhantes, a cópia manual deixa de ser eficaz e é hora de introduzir geração.
Código que depende de serviços externos com lógica não padrão (SDKs personalizados, protocolos proprietários) é difícil de gerar. Nesses casos, o boilerplate é escrito manualmente, mas isolado em módulos separados para minimizar a dispersão no projeto.
Para novos projetos, é melhor migrar diretamente para Kotlin, onde data class resolve as mesmas tarefas no nível da linguagem. Se o projeto permanecer em Java — Lombok continua sendo o padrão de fato, mas lembre-se de que requer um plugin para IDE e pode conflitar com novas versões do Java.
Sim, a geração de código adiciona tempo à compilação. KSP funciona mais rápido que KAPT, mas ainda adiciona segundos ou minutos a uma compilação completa. Otimização: use compilações incrementais e cache dos resultados de geração entre compilações.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também