Código limpo em Kotlin: regras que economizarão seus nervos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que "código limpo" não é sobre estética



Quando você começa a escrever em Kotlin, parece que a própria linguagem já resolve metade dos problemas. Não há boilerplate como em Java. Existem `data class`, lambdas, corrotinas. Mas se você simplesmente jogar o código "de qualquer jeito", em um mês você mesmo não conseguirá entendê-lo. E se uma equipe trabalha no projeto — seus colegas vão odiá-lo (ou você os odiará).



Código limpo em Kotlin não é sobre tabs em vez de espaços. É sobre como reduzir a carga cognitiva, tornar a lógica transparente e evitar bugs que se escondem em construções "convenientes". Neste artigo, mostrarei técnicas específicas: desde trabalhar com nullable até usar scope functions e sealed classes. Sem enrolação, apenas prática.



1. Null Safety: como não proliferar "?" e "!!"



Kotlin se orgulha de seu sistema de tipos, mas muitos escrevem como se fosse Java com "açúcar sintático". O principal antipadrão são cadeias de `?.let` e `!!` em pânico.



Ruim (legibilidade sofre):

user?.address?.city?.let { city ->    println(city)} ?: run {    println("No city")


Bom (elegante e limpo):

val city = user?.address?.cityprintln(city ?: "No city")


Use `!!` apenas se você tiver 100% de certeza de que o valor não é null (por exemplo, em testes ou após uma verificação em `if`). Em produção, isso é uma granada. Se você precisa converter nullable para non-null e tratar ambos os casos — use when ou o operador elvis.



2. Scope Functions: `apply`, `run`, `with`, `let`, `also` — quando usar o quê?



Esta é uma ferramenta poderosa, mas muitas vezes é abusada. A regra de ouro: não aninhe scope functions umas dentro das outras. Se você tem `list.apply { ... }.let { ... }` — está escrevendo um macarrão.



Regras de escolha:

  • apply — para configuração de objeto (retorna o próprio objeto). Ideal para builders.
  • let — para executar uma ação com um valor non-null (frequentemente em par com `?.`).
  • run — quando você precisa calcular um valor e retornar o resultado.
  • with — para agrupar chamadas de um mesmo objeto sem retorno.
  • also — para efeitos colaterais (logging, validação).


Exemplo limpo:

data class User(var name: String, var age: Int)

fun createUser(): User = User("Unknown", 0).apply { name = "Alice" age = 30}


Não escreva user?.let { it.name } — é redundante. Apenas user?.name.



3. Extension Functions: não prolifere classes utilitárias



Em Java, você escreveria StringUtils.capitalize(str). Em Kotlin — str.capitalize(). Extension functions são uma forma de "complementar" uma classe alheia sem herdá-la.



Exemplo de extension útil:

fun String.isValidEmail(): Boolean {    return this.contains("@") && this.contains(".")}


Mas não exagere. Se uma extension function é usada em apenas um lugar — talvez ela deva ser privada. E não crie extension em `Any` — isso quebra o sistema de tipos.



4. Sealed Classes e When: sua principal ferramenta em vez de if-else



Quando você tem um conjunto finito de estados (por exemplo, o resultado de uma requisição de API), use sealed class. Isso garante que você tratou todas as variantes.



Abordagem correta:

sealed class NetworkResult<out T> {    data class Success<T>(val data: T) : NetworkResult<T>()    data class Error(val message: String, val code: Int) : NetworkResult<Nothing>()    object Loading : NetworkResult<Nothing>()}

fun handle(result: NetworkResult<String>) { when (result) { is NetworkResult.Success -> println("Data: ${result.data}") is NetworkResult.Error -> println("Error: ${resu

Blogs

Book Recommendations