Code review в Java: что проверять и как давать обратную связь
Code review (ревью кода) — это не просто формальность, а один из самых эффективных способов улучшить качество кода и повысить профессиональный уровень команды. Для начинающих Java-разработчиков участие в ревью может казаться пугающим: «А вдруг я пропущу баг?», «Как сказать коллеге, что его код неидеален?». В этой статье мы разберем, на что обращать внимание при проверке Java-кода, и как давать обратную связь, чтобы она была полезной, а не обидной.
1. Что проверять в Java-коде: от синтаксиса до архитектуры
Code review не сводится к поиску опечаток. Хороший ревьюер смотрит на код системно. Вот основные категории проверки для Java-проектов:
1.1. Корректность и логика
Первый и главный вопрос: «Решает ли код поставленную задачу?». Проверьте:
- Крайние случаи (null, пустые коллекции, отрицательные значения).
- Логику условных операторов и циклов.
- Правильность работы с исключениями (не используйте
Exceptionкак универсальное решение).
Пример плохого кода:
public int divide(int a, int b) {
return a / b; // Потенциальное деление на ноль
}
Что предложить:
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Делитель не может быть нулем");
}
return a / b;
}
1.2. Читаемость и стиль
Java — язык с устоявшимися конвенциями (Java Code Conventions, Google Java Style). Обратите внимание на:
- Названия переменных, методов, классов (должны быть осмысленными).
- Форматирование (отступы, пробелы, длина строк).
- Наличие магических чисел (выносите их в константы).
Пример:
// Плохо
double x = 3.14159 * r * r;
// Хорошо
private static final double PI = 3.14159;
double area = PI * radius * radius;
1.3. Производительность и оптимизация
Для Java особенно важны:
- Избегайте ненужного создания объектов в циклах.
- Используйте
StringBuilderдля конкатенации строк в циклах. - Проверяйте сложность алгоритмов (O(n), O(n log n)).
Пример:
// Плохо (создается много объектов String)
String result = "";
for (int i = 0; i < 1000; i++) {
result += i;
}
// Хорошо
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
1.4. Тестируемость и тесты
Проверьте, покрыт ли новый код юнит-тестами. Обратите внимание на:
- Наличие тестов для граничных случаев.
- Отсутствие зависимостей от внешних систем (БД, API) в юнит-тестах.
- Читаемость самих тестов (метод
assertс понятными сообщениями).
2. Как давать обратную связь: конструктивно и без токсичности
Даже самый правильный код-ревью может провалиться, если обратная связь подана агрессивно или неконкретно. Вот несколько правил для начинающих:
2.1. Правило «Сэндвича»
Начните с позитива, затем укажите на недостатки, закончите ободрением. Например:
- Позитив: «Отличная идея вынести валидацию в отдельный метод!»
- Замечание: «Но здесь лучше использовать
Optionalвместо возврата null, чтобы избежатьNullPointerException». - Итог: «В остальном код чистый, спасибо за работу!»
2.2. Используйте «Я-сообщения» и вопросы
Вместо «Ты написал неправильно» скажите: «Мне кажется, здесь может возникнуть баг при пустом списке. Что думаешь?». Это снижает защитную реакцию и переводит диалог в конструктивное русло.
2.3. Комментируйте код, а не автора
Фокусируйтесь на конкретных строках кода, а не на личности разработчика. Сравните:
- Плохо: «Ты не знаешь, как работает equals()?»
- Хорошо: «В этой строке метод
equals()сравнивает ссылки, а не содержимое. Нужно переопределить его в классеUser».
2.4. Разделяйте «должно быть исправлено» и «можно улучшить»
Не все замечания обязательны к исполнению. Пометьте их:
- Blocker (блокирующее): баг, падение, нарушение безопасности. Исправить обязательно.
- Major (важное): нарушение конвенций, потенциальная проблема производительности.
- Minor (незначительное): стиль, нейминг, лишние пробелы.
3. Пример code review на Java (разбор реального кода)
Представьте, что коллега прислал следующий метод для проверки:
public List<String> getUsers() {
List<String> users = new ArrayList<>();
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "pass");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name FROM users");
while (rs.next()) {
users.add(rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }
}
}
return users;
}