Введение: почему code review — это не про «найти баги»
Code review (ревью кода) — один из самых эффективных инструментов для повышения качества программного продукта. В PHP-сообществе, где часто встречается наследие «спагетти-кода» и смесь procedural и OOP стилей, грамотное ревью становится особенно важным. Однако многие разработчики воспринимают его как «охоту на ошибки» или, что хуже, как способ самоутвердиться. На самом деле цель code review — передать знания, обеспечить единообразие кодовой базы и предотвратить потенциальные проблемы до того, как они попадут в продакшн.
В этой статье мы разберем, на что конкретно обращать внимание при ревью PHP-кода, и как давать обратную связь так, чтобы команда становилась сильнее, а не обижалась.
1. Что проверять в PHP-коде: чек-лист ревьювера
Чтобы ревью было системным, а не хаотичным, используйте следующий чек-лист. Он разделен на ключевые категории.
1.1. Безопасность (Security)
PHP — язык, где ошибки безопасности стоят дорого. Проверяйте:
- SQL-инъекции: используются ли подготовленные запросы (PDO или MySQLi)? Запрещена конкатенация строк в запросах.
- XSS (Cross-Site Scripting): весь пользовательский вывод экранируется через
htmlspecialchars()или шаблонизаторы (Twig, Blade). - CSRF-защита: есть ли токены в формах?
- Валидация на сервере: не полагайтесь только на клиентскую валидацию.
<?php
// ПЛОХО: SQL-инъекция
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
// ХОРОШО: PDO с prepared statement
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $_GET['id']]);
?>
1.2. Соответствие стандартам PSR
PHP-FIG (Framework Interop Group) разработала стандарты, которым следует большинство современных проектов. Проверяйте:
- PSR-12: отступы (4 пробела), фигурные скобки, нейминг (camelCase для методов, snake_case для переменных).
- PSR-4: автозагрузка классов и неймспейсы.
Используйте автоматические инструменты (PHP CodeSniffer, PHP-CS-Fixer), чтобы не тратить время на форматирование вручную.
1.3. Архитектура и SOLID
Даже в небольшом проекте принципы SOLID помогают избежать «большого комка грязи». Обращайте внимание на:
- Single Responsibility: один метод/класс — одна задача. Если метод делает 3 вещи — это повод для рефакторинга.
- Dependency Injection: не используйте
newвнутри классов, передавайте зависимости через конструктор. - Отсутствие «божественных объектов»: класс не должен знать всё о системе.
1.4. Производительность
Не оптимизируйте преждевременно, но явные антипаттерны стоит подсветить:
- Запросы в цикле (N+1 проблема).
- Использование
mysql_*функций (они удалены в PHP 7+). - Отсутствие индексов в БД для частых запросов.
2. Как давать обратную связь: искусство конструктивной критики
Даже самый правильный список замечаний не принесет пользы, если обратная связь звучит как «это ужасный код, перепиши». Вот несколько правил.
2.1. Правило «сэндвича»
Начинайте с позитива, затем замечание, затем поддержка.
- Позитив: «Отличное использование интерфейсов, код стал гибче».
- Замечание: «Но здесь есть потенциальная уязвимость XSS — давай экранируем вывод».
- Поддержка: «В остальном логика верная, после исправления можно мержить».
2.2. Вопросы вместо приказов
Вместо «Сделай по-другому» спросите: «А что если мы вынесем эту логику в отдельный сервис? Это упростит тестирование». Вопросы стимулируют мышление, а приказы — защиту.
2.3. Объясняйте «почему»
Просто написать «не используй global» — мало. Объясните: «Глобальные переменные создают скрытые зависимости, тестировать такой код сложно, а при изменении состояния в одном месте ломается всё». Так разработчик запомнит правило, а не просто исправит строку.
3. Типичные ошибки в PHP-коде, которые стоит подсвечивать
Даже опытные разработчики иногда допускают эти оплошности. Будьте внимательны.
3.1. Смешивание логики и представления
<?php
// ПЛОХО: HTML внутри PHP
echo "<h1>Привет, " . $user['name'] . "</h1>";
// ХОРОШО: Использование шаблонизатора или отделение логики
// В контроллере передаем данные, во вьюхе только вывод
?>
3.2. Игнорирование типов
PHP 7+ поддерживает строгую типизацию. Если в проекте включен declare(strict_types=1);, следите, чтобы типы аргументов и возврата были указаны.
<?php
declare(strict_types=1);
function calculateTotal(array $items, float $tax): float {
// ...
}
?>
3.3. «Магические числа» и строки
Числа и строки, смысл которых непонятен без контекста, должны быть константами или enum (PHP 8.1+).
<?php
// ПЛОХО
if ($status == 3) { ... }
// ХОРОШО
const STATUS_ACTIVE = 3;
if ($