Clean Code на PHP: принципы и примеры на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему чистый код на PHP — это не роскошь, а необходимость

Каждый PHP-разработчик хотя бы раз сталкивался с ситуацией, когда простой баг в production-среде превращается в многочасовую охоту за «дьяволом в деталях». Чаще всего причина кроется не в сложности логики, а в грязном коде: бессмысленные имена переменных, функции длиной в 500 строк, отсутствие типов и комментарии-враньё. Clean Code (Чистый код) — это не просто эстетика. Это инструмент, который снижает стоимость поддержки проекта в 3–5 раз и позволяет новым членам команды вливаться в проект за часы, а не недели.

В этой статье мы разберём ключевые принципы Clean Code применительно к PHP, подкрепив их реальными примерами до и после рефакторинга. Вы узнаете, как применять стандарты PSR, принципы SOLID и простые правила нейминга, чтобы ваш код говорил сам за себя.

1. Именование переменных, функций и классов: говорите на языке бизнеса

Плохое имя — главный враг читаемости. Если переменная называется $a или $data, каждый раз, читая код, вы тратите ментальные ресурсы на расшифровку. Правило простое: имя должно отвечать на вопрос «Что это?» или «Что делает?»

Плохой пример

<?php
// Что такое $d? Почему $x = 2?
$d = new DateTime();
$x = 2;
$y = $d->modify('+' . $x . ' days');
echo $y->format('Y-m-d');
?>

Хороший пример (Clean Code)

<?php
$currentDate = new DateTime();
$daysToAdd = 2;
$futureDate = $currentDate->modify('+' . $daysToAdd . ' days');
echo $futureDate->format('Y-m-d');
?>

Дополнительные правила:

  • Классы и интерфейсы — существительные: UserRepository, PaymentGatewayInterface.
  • Методы — глаголы: getUserById(), sendEmailNotification().
  • Булевы переменные — префиксы is, has, can: $isActive, $hasPermission.
  • Избегайте сокращений: $cnt → $count, $usr → $user.

2. Функции и методы: принцип единой ответственности (SRP) в действии

Одна функция — одно действие. Если вы видите функцию длиннее 20–30 строк, скорее всего, её можно разбить. В PHP это особенно актуально, так как отсутствие строгой типизации (до PHP 7.4) провоцирует «свалки» кода.

Плохой пример: функция-швейцарский нож

<?php
function processOrder(array $orderData): array
{
    // Валидация
    if (empty($orderData['email'])) {
        throw new InvalidArgumentException('Email required');
    }
    // Сохранение в БД
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
    $stmt = $pdo->prepare('INSERT INTO orders (email, total) VALUES (?, ?)');
    $stmt->execute([$orderData['email'], $orderData['total']]);
    // Отправка email
    mail($orderData['email'], 'Order Confirmed', 'Thank you!');
    // Логирование
    file_put_contents('log.txt', 'Order processed: ' . $orderData['email'] . PHP_EOL, FILE_APPEND);
    return ['status' => 'success'];
}
?>

Хороший пример: разделение ответственности

<?php
class OrderProcessor
{
    private OrderValidator $validator;
    private OrderRepository $repository;
    private MailService $mailer;
    private Logger $logger;

    public function __construct(
        OrderValidator $validator,
        OrderRepository $repository,
        MailService $mailer,
        Logger $logger
    ) {
        $this->validator = $validator;
        $this->repository = $repository;
        $this->mailer = $mailer;
        $this->logger = $logger;
    }

    public function process(array $orderData): array
    {
        $this->validator->validate($orderData);
        $order = $this->repository->save($orderData);
        $this->mailer->sendConfirmation($order);
        $this->logger->log('Order processed: ' . $order['email']);
        return ['status' => 'success', 'order_id' => $order['id']];
    }
}
?>

Теперь каждый класс отвечает только за свою зону: валидация, работа с БД, отправка писем и логирование. Такой код легко тестировать и модифицировать.

3. Комментарии: когда они нужны, а когда — вредны

Роберт Мартин (автор книги «Clean Code») утверждает: «Хороший код не требует комментариев». Комментарий — это признак неудачной попытки объяснить, что делает код. Вместо того чтобы писать комментарий, улучшите сам код.

Плохой пример: комментарий-извинение

<?php
// Увеличиваем счетчик на 1, потому что так надо
$counter = $counter + 1;
// Проверяем, если пользователь админ
if ($user->role == 1) {
    // ... 
}
?>

Хороший пример: самодокументируемый код

<?php
$counter++;
if ($user->isAdmin()) {
    // ...
}
?>

Когда комментарии оправданы:

  • Пояснение бизнес-правил, которые невозможно выразить кодом (например, ссылка на закон или регламент).
  • Предупреждение о побочных эффектах (например, // Этот метод меняет глобальное состояние).
  • Todo-заметки для будущих доработок: // TODO: заменить на кэширование.

4. Стандарты PSR и форматирование: единый стиль для команды

PHP Framework Interop Group (PHP-FIG) разработала стандарты PSR,

Блоги

Рекомендаций по книгам