Principales errores de desarrolladores principiantes en Kotlin: cómo evitarlos y escribir código limpio
Kotlin es un lenguaje moderno, conciso y seguro que rápidamente ganó popularidad en el mundo del desarrollo Android y backend. Sin embargo, su flexibilidad y azúcar sintáctico a menudo confunden a los principiantes. En este artículo analizaremos 4 errores típicos que cometen los desarrolladores novatos en Kotlin y mostraremos cómo corregirlos con ejemplos de código.
1. Ignorar null safety y uso incorrecto del operador !!
Una de las principales características de Kotlin es null safety. Pero muchos principiantes, acostumbrados a Java, siguen usando !! (not-null assertion operator) sin pensar. Este es el camino directo a NullPointerException.
Ejemplo incorrecto:
fun getUserName(user: User?): String { return user!!.name // Si user == null, habrá NPE}Ejemplo correcto (trabajo seguro con nullable):
fun getUserNameSafe(user: User?): String { return user?.name ?: "Usuario desconocido"}Use ?.let{}, ?: (operador Elvis) y ?.run{} para acceso seguro. El operador !! solo se justifica en casos raros donde esté 100% seguro de que el valor no es null (por ejemplo, en tests).
2. Uso incorrecto de sealed classes y when
Las sealed classes son una herramienta poderosa para modelar jerarquías limitadas. Pero los principiantes a menudo olvidan que when debe ser exhaustivo al trabajar con sealed classes. O, por el contrario, usan else donde no es necesario.
Ejemplo incorrecto (rama omitida):
sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result()}
fun handleResult(result: Result) { when (result) { is Result.Success -> println(result.data) // Falta la rama para Error — habrá una advertencia }}Ejemplo correcto (when exhaustivo):
fun handleResultExhaustive(result: Result) { when (result) { is Result.Success -> println(result.data) is Result.Error -> println(result.message) } // El compilador no requiere else, ya que todas las variantes están cubiertas}Si agrega una nueva rama a una sealed class, el compilador le indicará dónde debe actualizar el when. Esto protege el código de errores durante la refactorización.
3. Abuso de corrutinas: lanzamiento sin contexto e ignorando structured concurrency
Las corrutinas son una excelente forma de trabajar con asincronía, pero los principiantes a menudo las lanzan sin el contexto adecuado u olvidan structured concurrency. Esto provoca fugas de memoria y tareas en segundo plano incontroladas.
Ejemplo incorrecto (ámbito global y pérdida de contexto):
fun loadData() { GlobalScope.launch { // ¡Mal! Vive mientras vive la aplicación val data = fetchData() // Puede ejecutarse después de cerrar la Activity updateUI(data) // Error: la UI ya fue destruida }}Ejemplo correcto (structured concurrency con viewModelScope):
class MyViewModel : ViewModel() { fun loadData() { viewModelScope.launch { val data = fetchData() updateUI(data) // Se cancelará automáticamente al limpiar el ViewModel } }}Use siempre coroutineScope, viewModelScope o su propio CoroutineScope con un ciclo de vida claro. Evite GlobalScope en código de producción.
4. Sobrecarga de operadores sin comprender la semántica
Kotlin permite sobrecargar operadores (+, -, in