Ревью кода на Kotlin: что бесит senior-разработчиков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как senior-ы видят ваш Kotlin-код: разбор на реальных примерах

Вы написали код, запушили его в репозиторий и с замиранием сердца ждёте аппрува. Но вместо зелёной галочки прилетает десяток комментариев от старшего разработчика. Знакомо? Если вы пишете на Kotlin, то наверняка сталкивались с ситуацией, когда ваш, казалось бы, идеальный код, после code review превращается в тыкву.

В этой статье мы разберём, какие типичные замечания senior-ов чаще всего встречаются при ревью кода на Kotlin. Мы не будем учить вас синтаксису — мы покажем, как писать так, чтобы ваш код проходил ревью с первого раза. Поехали!

1. Null Safety: «Почему ты не используешь элвис-оператор?»

Одна из главных фишек Kotlin — null safety. Но многие разработчики, особенно пришедшие из Java, продолжают писать код в стиле «проверь-на-null-и-выполни». Senior-ы это видят сразу.

Плохой пример (Java-стайл)

fun getUserName(user: User?): String {
    return if (user != null) {
        user.name
    } else {
        "Unknown"
    }
}

Хороший пример (Kotlin-стайл)

fun getUserName(user: User?): String {
    return user?.name ?: "Unknown"
}

Использование элвис-оператора (?:) и safe call (?.) делает код лаконичным и читаемым. Senior-ы обожают, когда вы экономите строки без потери ясности. Запомните: if (x != null) { ... } else { ... } — это моветон.

2. Extension Functions: «Где твои утилиты?»

Когда вы видите статический утилитный класс в духе StringUtils.capitalize(str), опытный разработчик на Kotlin поморщится. Extension functions — это то, что делает Kotlin таким элегантным.

Плохой пример

object StringUtils {
    fun capitalize(text: String): String {
        return text.replaceFirstChar { it.uppercase() }
    }
}

// Использование
val result = StringUtils.capitalize("hello")

Хороший пример

fun String.capitalizeFirst(): String {
    return this.replaceFirstChar { it.uppercase() }
}

// Использование
val result = "hello".capitalizeFirst()

Сеньоры скажут: «Зачем ты создаёшь объект-помойку? Просто расширь класс!» Используйте extension functions — это улучшает читаемость и следует принципу Kotlin best practices.

3. Sealed Classes вместо Enum: «Твой enum устарел»

Enum-ы в Kotlin — это хорошо, но sealed classes дают гораздо больше гибкости. Особенно когда нужно хранить разные типы данных в одной иерархии.

Плохой пример (enum)

enum class Result {
    SUCCESS,
    ERROR,
    LOADING
}

fun handleResult(result: Result) {
    when (result) {
        Result.SUCCESS -> // ...
        Result.ERROR -> // ...
        Result.LOADING -> // ...
    }
}

Хороший пример (sealed class)

sealed class Result {
    data class Success(val data: List<Item>) : Result()
    data class Error(val message: String, val code: Int) : Result()
    object Loading : Result()
}

fun handleResult(result: Result) {
    when (result) {
        is Result.Success -> println("Data: ${result.data}")
        is Result.Error -> println("Error: ${result.message}")
        Result.Loading -> println("Loading...")
    }
}

Senior-разработчики оценят, что вы используете sealed classes для представления состояний. Это один из главных советов senior kotlin — делайте иерархии типов явными.

4. Scope Functions: «Ты забыл про let, apply и run»

Scope functions (let, apply, run, with, also) — мощный инструмент, но новички часто либо не используют их вовсе, либо используют неправильно. Senior-ы на code review любят указывать на это.

Плохой пример (без scope functions)

val user = User()
user.name = "John"
user.age = 30
user.email = "john@example.com"
database.insert(user)

Хороший пример (с apply)

val user = User().apply {
    name = "John"
    age = 30
    email = "john@example.com"
}
database.insert(user)

Или используйте let для безопасной работы с nullable-объектами:

user?.let {
    println("User name: ${it.name}")
    updateUI(it)
}

Запоминайте: apply — для конфигурации объекта, let — для безопасного выполнения кода с non-null значением, run — для вычислений. Это чистый код Kotlin в действии.

5. Data Classes: «Пиши их правильно»

Казалось бы, что может быть проще data class? Но senior-ы находят ошибки и здесь. Главная проблема — использование изменяемых (mutable) полей.

Плохой пример

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

Хороший пример

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

Почему? Data class генерирует equals(), hashCode() и copy(). Если поля изменяемые, вы можете получить баги с коллекциями (например, HashSet). Senior-ы скажут: «Сделай поля val, а если нужно изменить — используй copy()».

val updatedUser = user.copy(age = 31)

Это один из ключевых Kotlin best practices, который спасёт вас от трудноуловимых ошибок.

6. Когда не нужен when: «Упрости логику»

Иногда разработчики пишут when там, где можно обойтись простым if или даже тернарным оператором. Senior-ы не любят излишнюю сложность.

Плохой пример

fun getStatusText(status: Boolean): String {
    return when (status) {
        true -> "Active"
        false -> "Inactive"
    }
}

Хороший пример

fun getStatusText(status: Boolean): String {
    return if (status) "Active" else "Inactive"
}

Или ещё лучше — используйте extension property:

val Boolean.statusText: String
    get() = if (this) "Active" else "Inactive"

Правило простое: if для двух вариантов, when для

Блоги

Рекомендаций по книгам