Top erreurs des développeurs Kotlin débutants : comment les éviter et écrire du code propre
Kotlin est un langage moderne, concis et sûr qui a rapidement gagné en popularité dans le monde du développement Android et du backend. Cependant, sa flexibilité et son sucre syntaxique induisent souvent les débutants en erreur. Dans cet article, nous allons analyser 4 erreurs typiques que commettent les développeurs débutants en Kotlin, et montrer comment les corriger à l'aide d'exemples de code.
1. Ignorer la null safety et mauvaise utilisation de l'opérateur !!
L'un des principaux atouts de Kotlin est la null safety. Mais de nombreux débutants, habitués à Java, continuent d'utiliser !! (not-null assertion operator) sans réfléchir. C'est le chemin direct vers un NullPointerException.
Mauvais exemple :
fun getUserName(user: User?): String { return user!!.name // Si user == null, il y aura NPE}Bon exemple (travail sécurisé avec nullable) :
fun getUserNameSafe(user: User?): String { return user?.name ?: "Utilisateur inconnu"}Utilisez ?.let{}, ?: (opérateur Elvis) et ?.run{} pour un accès sécurisé. L'opérateur !! n'est justifié que dans de rares cas où vous êtes sûr à 100% que la valeur n'est pas null (par exemple, dans les tests).
2. Mauvaise utilisation des sealed classes et de when
Les sealed classes sont un outil puissant pour modéliser des hiérarchies limitées. Mais les débutants oublient souvent que when doit être exhaustif lorsqu'il travaille avec des sealed classes. Ou, à l'inverse, ils utilisent else là où il n'est pas nécessaire.
Mauvais exemple (branche manquante) :
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) // La branche pour Error est absente — il y aura un avertissement }}Bon exemple (when exhaustif) :
fun handleResultExhaustive(result: Result) { when (result) { is Result.Success -> println(result.data) is Result.Error -> println(result.message) } // Le compilateur n'exige pas else, car tous les cas sont couverts}Si vous ajoutez une nouvelle branche à une sealed class, le compilateur vous indiquera où mettre à jour le when. Cela protège le code des erreurs lors du refactoring.
3. Abus des coroutines : lancement sans contexte et ignorance de la structured concurrency
Les coroutines sont un excellent moyen de travailler avec l'asynchrone, mais les débutants les lancent souvent sans contexte approprié ou oublient la structured concurrency. Cela entraîne des fuites de mémoire et des tâches d'arrière-plan incontrôlées.
Mauvais exemple (scope global et perte de contexte) :
fun loadData() { GlobalScope.launch { // Mauvais ! Vit tant que l'application vit val data = fetchData() // Peut s'exécuter après la fermeture de l'Activity updateUI(data) // Erreur : l'UI est déjà détruite }}Bon exemple (structured concurrency avec viewModelScope) :
class MyViewModel : ViewModel() { fun loadData() { viewModelScope.launch { val data = fetchData() updateUI(data) // S'annule automatiquement lors du nettoyage du ViewModel } }}Utilisez toujours coroutineScope, viewModelScope ou votre propre CoroutineScope avec un cycle de vie clair. Évitez GlobalScope dans le code de production.
4. Surcharge des opérateurs sans comprendre la sémantique
Kotlin permet de surcharger les opérateurs (+, -, in