Code review в Kotlin: что проверять и как давать обратную связь новичкам

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

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

Начать курс

Code review в Kotlin: что проверять и как давать обратную связь

Code review (ревью кода) — это не просто формальность, а мощный инструмент для повышения качества проекта и роста команды. Для начинающих разработчиков на Kotlin процесс ревью часто вызывает страх: «А вдруг я пропущу баг?», «Как сказать коллеге, что его код плохой?». В этой статье мы разберём, на что обращать внимание при проверке Kotlin-кода и как формулировать замечания, чтобы они были полезными, а не обидными.

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

1. Null safety и работа с nullable типами

Kotlin гордится своей системой типов, которая устраняет большую часть NullPointerException на этапе компиляции. Однако новички часто злоупотребляют оператором !! (not-null assertion) или неправильно обрабатывают nullable-значения.

Что проверять:

  • Используется ли !! без веской причины? Если вы видите something!!, спросите автора: «Почему ты уверен, что здесь не будет null? Может, лучше использовать ?.let или ?:?».
  • Корректно ли обрабатываются цепочки вызовов через ?.? Например, user?.address?.city — безопасно, но если нужен city, лучше использовать ?: для значения по умолчанию.
  • Не забыт ли lateinit var инициализировать перед использованием? Проверьте, что все lateinit поля точно будут проинициализированы до первого чтения.
// Плохо
fun getUserCity(user: User?): String {
    return user!!.address!!.city // Риск NPE
}

// Хорошо
fun getUserCitySafe(user: User?): String {
    return user?.address?.city ?: "Unknown"
}

Как давать обратную связь: Вместо «Ты написал плохой код» скажите: «Здесь может быть null, давай заменим !! на безопасный вызов, чтобы избежать падения в рантайме». Предложите альтернативу — это учит, а не критикует.

2. Идиоматичность Kotlin: коллекции, scope-функции и sealed class

Kotlin — не просто «Java с другим синтаксисом». Многие новички пишут на Kotlin так, будто всё ещё работают в Java: используют циклы for вместо функций коллекций, забывают про apply, let, run и не применяют sealed class для представления состояний.

Что проверять:

  • Используются ли функции коллекций (map, filter, firstOrNull) вместо ручных циклов? Это делает код лаконичнее и читаемее.
  • Есть ли избыточные временные переменные? Например, val result = list.filter { ... }.map { ... } лучше, чем разбивать на три шага с мутабельными списками.
  • Используются ли sealed class для иерархий, где нужно обработать все варианты (например, Result, UiState)? Это обязательное требование в современных Kotlin-проектах.
// Плохо (Java-style)
fun getEvenSquares(list: List<Int>): List<Int> {
    val result = mutableListOf<Int>()
    for (i in list.indices) {
        if (list[i] % 2 == 0) {
            result.add(list[i] * list[i])
        }
    }
    return result
}

// Хорошо (Kotlin-idiomatic)
fun getEvenSquaresIdiomatic(list: List<Int>): List<Int> {
    return list.filter { it % 2 == 0 }.map { it * it }
}

Как давать обратную связь: Укажите на конкретную идиому: «Вместо цикла for можно использовать filter + map, это короче и понятнее. Хочешь, покажу пример?». Не навязывайте — предложите обсудить.

3. Архитектура и тестируемость

Даже если проект маленький, code review — отличный момент проверить, как код вписывается в общую архитектуру. Новички часто смешивают логику, нарушают Single Responsibility Principle или забывают про инъекцию зависимостей.

Что проверять:

  • Не содержит ли функция слишком много ответственности? Если метод делает и валидацию, и сохранение, и отправку уведомления — это повод разбить его.
  • Есть ли тесты? Проверьте, что для новой логики написаны unit-тесты. Если тестов нет, но код сложный — это красный флаг.
  • Используются ли зависимости правильно? Например, в Android-проектах проверьте, не создаётся ли Presenter/ViewModel внутри Activity — это усложняет тестирование.
// Плохо: смешиваем логику
class OrderProcessor {
    fun processOrder(order: Order) {
        if (order.total > 100) { // бизнес-логика
            // отправка email (инфраструктура)
            EmailSender.send(order.email, "Order confirmed")
        }
        // сохранение в БД (работа с данными)
        database.save(order)
    }
}

// Хорошо: разделяем на слои
class OrderProcessor(
    private val emailSender: EmailSender,
    private val orderRepository: OrderRepository
) {
    fun processOrder(order: Order) {
        if (order.total > 100) {
            emailSender.sendConfirmation(order)
        }
        orderRepository.save(order)
    }
}

Как давать обратную связь: Сфокусируйтесь на принципах, а не на личных предпочтениях. Например: «Эта функция делает три разных дела. Если мы вынесем отправку email в отдельный класс, её будет проще тестировать и переиспользовать». Спрашивайте мнение автора — возможно, у него есть веские причины.

4. Обратная связь: как не обидеть и научить

Теперь о самом сложном — о человеческом факторе. Даже идеальные замечания могут быть восприняты в штыки, если их неправильно подать. Вот несколько правил для начинающих ревьюеров:

  • Начинайте с позитива. Найдите в коде что-то хорошее: удачное название переменной,

Блоги

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