Clean Code em Kotlin: princípios e exemplos na prática
Código limpo (Clean Code) não é apenas um termo da moda, mas uma habilidade fundamental para o desenvolvedor profissional. No contexto do Kotlin, uma linguagem moderna e concisa, os princípios do código limpo ganham especial importância. Kotlin permite escrever código expressivo, mas sem disciplina é fácil criar uma arquitetura confusa. Neste artigo, analisaremos os principais princípios do Clean Code com exemplos em Kotlin que ajudarão você a escrever código compreensível para colegas e para você mesmo daqui a seis meses.
1. Nomes significativos: a chave para a legibilidade do código
A nomeação correta é o primeiro passo para um código limpo. Os nomes de variáveis, funções e classes devem responder às perguntas "por quê?", "o quê?" e "como?". Kotlin oferece ferramentas poderosas para isso.
Exemplo ruim:
fun calc(a: Int, b: Int): Int { val c = a + b * 2 return c}Exemplo bom (Clean Code):
fun calculateDiscountedPrice(basePrice: Int, discountPercent: Int): Int { val discountAmount = basePrice * discountPercent / 100 return basePrice - discountAmount}No bom exemplo, cada nome fala por si. calculateDiscountedPrice é um verbo que descreve a ação. basePrice e discountPercent são substantivos que transmitem com precisão a essência dos dados. Kotlin suporta argumentos nomeados, o que torna a chamada de funções ainda mais transparente:
val finalPrice = calculateDiscountedPrice(basePrice = 1000, discountPercent = 20)Regras importantes:
- Evite nomes de uma letra (exceto para índices de loops).
- Use
camelCasepara variáveis e funções. - Para valores booleanos, use os prefixos
is,has,can(por exemplo,isActive,hasPermission).
2. Funções: uma função — uma tarefa
O princípio da responsabilidade única (Single Responsibility Principle) se aplica não apenas a classes, mas também a funções. Uma função deve fazer apenas uma ação e fazê-la bem. Kotlin, com seus recursos funcionais, simplifica essa prática.
Exemplo ruim (função faz demais):
fun processUser(userId: String) { val user = database.findUser(userId) if (user != null) { user.name = user.name.uppercase() database.updateUser(user) sendEmail(user.email, "Welcome!") }}Exemplo bom (divisão em funções pequenas):
fun processUser(userId: String) { val user = findUserOrThrow(userId) val updatedUser = user.apply { name = name.uppercase() } updateUserInDatabase(updatedUser) sendWelcomeEmail(updatedUser.email)}
private fun findUserOrThrow(userId: String): User { return database.findUser(userId) ?: throw IllegalArgumentException("User not found")}
private fun updateUserInDatabase(user: User) { database.updateUser(user)}
private fun sendWelcomeEmail(email: String) { sendEmail(email, "Welcome!")}Agora cada função é responsável por uma etapa lógica. Isso facilita os testes, a depuração e a reutilização do código. As funções Kotlin podem ser locais (aninhadas), permitindo encapsular a lógica sem criar classes desnecessárias.
3. Trabalhando com tipos anuláveis e tratamento elegante de erros
Clean Code implica gerenciamento explícito de incertezas. Kotlin introduz tipos anuláveis (?) e operadores poderosos para trabalhar com eles com segurança. O uso de !! (non-null assertion) é um sinal de código ruim. Em vez disso, use chamadas seguras e o operador elvis.
Exemplo ruim (risco de NPE):
fun getCity