Code review в C++: что проверять и как давать обратную связь
Code review — один из ключевых этапов разработки программного обеспечения. Особенно это важно для C++, где ошибки управления памятью или неверное использование стандартной библиотеки могут привести к серьезным проблемам. В этой статье мы разберем, на что обращать внимание при ревью кода на C++ и как давать обратную связь, чтобы она была полезной, а не обидной.
Почему code review важен для C++?
C++ — мощный, но сложный язык. Он предоставляет разработчику высокий уровень контроля, но при этом требует внимательности. Типичные проблемы: утечки памяти, неопределенное поведение, неэффективные алгоритмы. Хороший code review помогает выявить такие ошибки до того, как они попадут в продакшн.
Для начинающих разработчиков code review — это не только проверка, но и обучение. Получая обратную связь, вы учитесь писать более качественный код. Давая ревью — учитесь анализировать и аргументировать.
Что проверять в C++ коде: чек-лист
Чтобы ревью было системным, используйте следующий чек-лист.
1. Управление памятью и ресурсами
Это основа C++. Ошибки здесь — самые опасные.
- Используются ли умные указатели вместо сырых?
std::unique_ptrиstd::shared_ptrдолжны быть стандартом. Сырые указатели допустимы только для наблюдения (non-owning). - Есть ли утечки? Проверьте, что каждый
newимеет соответствующийdelete(если не используются умные указатели). - Правильно ли освобождаются ресурсы? Файлы, сокеты, мьютексы должны быть обернуты в RAII-классы.
// Плохо: сырой указатель и ручное управление
void process() {
int* data = new int[100];
// ... если здесь исключение, будет утечка
delete[] data;
}
// Хорошо: умный указатель
void process() {
auto data = std::make_unique<int[]>(100);
// память освободится автоматически
}
2. Безопасность типов и избегание неопределенного поведения
C++ полон неопределенного поведения (UB). Ревьювер должен быть начеку.
- Нет ли выхода за границы массива? Используйте
std::arrayилиstd::vectorс.at()вместо сырых массивов. - Правильно ли приведение типов? Избегайте C-style cast. Используйте
static_cast,dynamic_cast,const_castилиreinterpret_castосознанно. - Инициализированы ли все переменные? Неинициализированные переменные — частая причина UB.
- Нет ли переполнения знаковых целых? В C++ это UB.
// Плохо: C-style cast и неинициализированная переменная
int* p = (int*)malloc(sizeof(int));
int x; // не инициализировано
*p = x; // UB
// Хорошо: явное приведение и инициализация
int* p = static_cast<int*>(std::malloc(sizeof(int)));
int x = 0;
*p = x;
3. Производительность и эффективность
Не всегда нужно гнаться за скоростью, но очевидные узкие места стоит исправлять.
- Передаются ли объекты по значению без необходимости? Крупные объекты должны передаваться по константной ссылке (
const &). - Нет ли лишних копирований? Используйте move-семантику, где это уместно.
- Правильно ли выбран контейнер?
std::vectorдля быстрого доступа по индексу,std::listдля частых вставок в середину. - Не вызывается ли виртуальная функция в горячем цикле? Это может быть медленно.
// Медленно: копирование большого объекта
void process(std::string s) { /* ... */ }
// Быстро: передача по константной ссылке
void process(const std::string& s) { /* ... */ }
4. Читаемость и стиль кода
Код пишется один раз, а читается десятки раз.
- Понятны ли имена переменных и функций?
int a— плохо,int userCount— хорошо. - Соблюдается ли единый стиль? Отступы, скобки, нейминг (snake_case или camelCase).
- Нет ли магических чисел? Выносите константы в
constexprилиenum. - Не слишком ли длинная функция? Если функция делает больше одного дела — разбейте.
// Плохо: магические числа и непонятные имена
if (x > 3600) { /* ... */ }
// Хорошо: именованная константа
constexpr int SECONDS_IN_HOUR = 3600;
if (x > SECONDS_IN_HOUR) { /* ... */ }
Как давать обратную связь: советы для начинающих
Техническая часть — только половина дела. Вторая половина — умение общаться.
Будьте конкретны и аргументированы
Вместо «это плохой код» напишите: «Здесь возможна утечка памяти, так как new не соответствует delete. Рекомендую использовать std::unique_ptr».
Плохой комментарий: «Перепиши это». Хороший: «Функция слишком длинная (120 строк). Предлагаю разбить её на три: validateInput, processData и formatOutput».
Разделяйте критику кода и личности
Вы ревьюируете код, а не человека. Избегайте фраз вроде «ты написал ерунду». Говорите: «в этом участке кода есть потенциальная проблема».