Clean Code на PHP: принципы и примеры
Каждый PHP-разработчик сталкивался с ситуацией, когда собственный код через пару месяцев становится непонятным. А что уж говорить о чужом коде, унаследованном от предыдущей команды. Это приводит к багам, долгому онбордингу новичков и нежеланию вносить изменения. Решение этой проблемы — принципы Clean Code (чистого кода), популяризированные Робертом Мартином (дядей Бобом). В этой статье мы разберем ключевые принципы Clean Code применительно к PHP и рассмотрим конкретные примеры.
1. Именование переменных, функций и классов
Правильное именование — основа читаемого кода. Имя должно отвечать на вопросы: "Что это?" и "Зачем это?". Не экономьте буквы в угоду краткости.
Плохой пример (плохой код)
<?php
function getData($d, $u) {
$r = [];
foreach ($d as $i) {
if ($i['status'] === 'active' && $i['user_id'] === $u) {
$r[] = $i;
}
}
return $r;
}
?>
Хороший пример (чистый код)
<?php
function getActiveOrdersByUser(array $orders, int $userId): array
{
$activeOrders = [];
foreach ($orders as $order) {
if ($order['status'] === 'active' && $order['user_id'] === $userId) {
$activeOrders[] = $order;
}
}
return $activeOrders;
}
?>
Правила именования:
- Переменные — существительные:
$userName,$orderTotal. - Функции — глаголы:
calculateTotal(),sendEmail(). - Классы — существительные в единственном числе:
UserRepository,OrderProcessor. - Булевы переменные — начинайте с
is,has,can:$isActive,$hasPermission. - Избегайте сокращений (
$usr), транслита ($sozdanieZakaza) и однобуквенных переменных (кроме счетчиков циклов$i).
2. Функции: маленькие и с одной ответственностью
Функция должна делать только одно действие и делать его хорошо. Если функция выполняет несколько задач — её нужно разбить. Идеальный размер функции — 10–20 строк.
Плохой пример (функция делает всё)
<?php
function processOrder(array $orderData): bool
{
// Валидация
if (empty($orderData['items'])) {
return false;
}
// Расчет стоимости
$total = 0;
foreach ($orderData['items'] as $item) {
$total += $item['price'] * $item['quantity'];
}
// Сохранение в БД
$sql = "INSERT INTO orders (user_id, total, status) VALUES (?, ?, 'new')";
$stmt = $this->db->prepare($sql);
$stmt->execute([$orderData['user_id'], $total]);
// Отправка email
mail($orderData['email'], 'Order Confirmation', 'Your order is placed');
return true;
}
?>
Хороший пример (разделение на маленькие функции)
<?php
class OrderService
{
public function processOrder(array $orderData): bool
{
if (!$this->validateOrder($orderData)) {
return false;
}
$total = $this->calculateTotal($orderData['items']);
$orderId = $this->saveOrder($orderData['user_id'], $total);
$this->sendConfirmationEmail($orderData['email']);
return true;
}
private function validateOrder(array $orderData): bool
{
return !empty($orderData['items']);
}
private function calculateTotal(array $items): float
{
$total = 0;
foreach ($items as $item) {
$total += $item['price'] * $item['quantity'];
}
return $total;
}
private function saveOrder(int $userId, float $total): int
{
// Логика сохранения в БД
return 123; // ID заказа
}
private function sendConfirmationEmail(string $email): void
{
// Логика отправки email
}
}
?>
3. Комментарии: когда они нужны, а когда — нет
Чистый код самодокументируем. Комментарии не должны объяснять что делает код (это должна показывать структура и имена), а почему он делает это именно так. Избегайте закомментированного кода — используйте систему контроля версий.
Плохой пример (бесполезный комментарий)
<?php
// Увеличиваем счетчик на 1
$counter = $counter + 1;
?>
Хороший пример (объяснение бизнес-логики)
<?php
// Скидка 10% применяется только для новых клиентов (статус 'new')
// в первые 30 дней после регистрации
if ($user->getStatus() === 'new' && $user->getDaysSinceRegistration() < 30) {
$total *= 0.9;
}
?>
Когда комментарии оправданы:
- Сложные бизнес-правила.
- Предупреждения о побочных эффектах.
- Ссылки на внешние источники (баг-трекеры, документацию).
- TODO и FIXME с указанием причины.
4. Форматирование и PSR-стандарты
PHP-FIG (PHP Framework Interop Group) разработала стандарты PSR, которые помогают писать единообразный код. Для Clean Code особенно важны PSR-1 (базовые правила) и PSR-12 (стиль кода).
Основные правила PSR-12:
- Отступы — 4 пробела (не табуляция).
- Открывающая фигурная скобка класса — на новой строке.
- Открывающая фигурная скобка метода — на новой строке.
- Открывающая фигурная скобка управляющих конструкций (if, foreach) — на той же строке.