Code review в Kotlin: что проверять и как давать обратную связь для начинающих
Code review (ревью кода) — это один из ключевых процессов в современной разработке. Для новичков на Kotlin он часто кажется пугающим: как найти ошибки? Что именно смотреть? Как не обидеть автора кода? В этой статье мы разберём, на что обращать внимание при code review проектов на Kotlin, и как давать обратную связь, чтобы она была полезной, а не обидной. Материал подойдёт как тем, кто только учится ревьюить, так и тем, кто хочет улучшить свои навыки.
Зачем нужен code review в Kotlin?
Kotlin — современный, лаконичный и безопасный язык, но он даёт разработчику много свободы. Без code review легко допустить ошибки, связанные с null-безопасностью, неправильным использованием корутин или излишней сложностью. Ревью помогает:
- Найти баги на ранних этапах.
- Улучшить читаемость и поддерживаемость кода.
- Распространить знания внутри команды.
- Соблюсти единый стиль кода.
Для начинающих это ещё и отличный способ учиться на чужих примерах. Давайте перейдём к конкретике.
Что проверять при code review кода на Kotlin
Вот чек-лист из ключевых пунктов, которые стоит проверять в каждом pull request. Разделим их на логические блоки.
1. Null-безопасность и типы
Kotlin гордится своей null-безопасностью, но её можно нарушить. Проверяйте:
- Используются ли nullable типы (например,
String?) только там, где это действительно нужно? - Нет ли ненужных
!!(non-null assertion)? В идеале их вообще не должно быть в production-коде. - Используются ли безопасные вызовы (
?.let { ... }) и элвис-оператор (?:) вместоif (x != null)?
Плохой пример:
val name: String? = getName()
val length = name!!.length // Опасно: вызовет NPE, если name == null
Хороший пример:
val name: String? = getName()
val length = name?.length ?: 0 // Безопасно: если null, то 0
2. Функции и их сигнатуры
Kotlin поддерживает именованные аргументы и значения по умолчанию. Проверьте:
- Является ли функция слишком длинной (больше 20–30 строк)? Возможно, её стоит разбить.
- Используются ли параметры по умолчанию для упрощения вызова?
- Нет ли функций с более чем 3–4 параметрами? Это усложняет чтение.
- Уместно ли использование extension-функций? Они не должны менять состояние объекта.
Пример:
// Вместо этого:
fun processUserData(name: String, age: Int, email: String, city: String, phone: String) { ... }
// Лучше так:
data class UserData(val name: String, val age: Int, val email: String, val city: String, val phone: String)
fun processUserData(user: UserData) { ... }
3. Работа с корутинами (Coroutines)
Корутины — мощный инструмент Kotlin, но их легко использовать неправильно. Обратите внимание:
- Не заблокирован ли поток внутри корутины (вызов
Thread.sleep()или блокирующий ввод-вывод)? - Используется ли правильный диспетчер (Dispatchers.IO для сетевых запросов, Dispatchers.Main для UI)?
- Нет ли утечек корутин (например, запущенных в Activity без отмены)?
- Используется ли
withContextдля смены диспетчера, а неlaunchвнутриlaunch?
Плохой пример:
fun fetchData() {
GlobalScope.launch { // Утечка: не отменяется при уничтожении компонента
Thread.sleep(1000) // Блокирует поток!
}
}
Хороший пример:
fun fetchData(scope: CoroutineScope) {
scope.launch {
withContext(Dispatchers.IO) {
// Сетевой запрос
}
}
}
4. Использование коллекций и функционального стиля
Kotlin поощряет функциональный подход с map, filter, fold и т.д. Проверьте:
- Не заменён ли простой цикл сложной цепочкой вызовов? Иногда
forчитается лучше. - Нет ли ненужных промежуточных коллекций (например,
.toList().filter { ... }.toList())? - Используются ли
sequenceдля ленивых вычислений, если коллекция большая?
Пример:
// Плохо: две промежуточные коллекции
val result = list.filter { it > 5 }.map { it * 2 }
// Хорошо: одна цепочка с sequence для больших списков
val result = list.asSequence().filter { it > 5 }.map { it * 2 }.toList()
Как давать обратную связь: советы для начинающих
Теперь, когда вы знаете, что проверять, важно правильно донести свои замечания. Вот несколько принципов.
1. Будьте конкретны и объясняйте "почему"
Вместо "это плохо" напишите "это может вызвать NullPointerException, потому что...". Приводите примеры кода. Например:
Плохой комментарий: "Тут всё неправильно."
Хороший комментарий: "Здесь используется !!, что опасно. Если user будет null, приложение упадёт. Предлагаю заменить на user?.let { ... } или ?:."
2. Начинайте с позитива
Найдите что-то хорошее в коде: "Отлично, что