Введение: почему «чистый код» — это не про педантичность, а про деньги и нервы
Представьте, что вы заходите в старый проект на PHP, написанный год назад. Вы открываете файл index.php, а там — мешанина из HTML, SQL-запросов, echo и функций с именами типа f1(). Знакомо? Если да, то вы либо новичок, который только начинает свой путь, либо опытный разработчик, которому достался «легаси» проект.
Чистый код на PHP — это не дань моде и не прихоть тимлида. Это инструмент, который экономит часы, нервы и деньги. В этой статье мы разберем, как превратить ваш PHP-код из «грязного черновика» в «чистовик», который будет радовать вас и ваших коллег. Мы поговорим о стандартах PSR, принципах SOLID, правильном нейминге и дадим реальные примеры. Поехали!
1. Философия чистого кода: главные принципы
Прежде чем нырять в синтаксис, давайте договоримся о правилах игры. Чистый код — это код, который:
- Понятен без комментариев (хотя комментарии иногда нужны).
- Легко тестируется.
- Не боится рефакторинга.
- Соблюдает единый стиль во всем проекте.
Роберт Мартин (Дядюшка Боб) в своей книге «Чистый код» сказал: «Единственный способ быстро писать — это писать хорошо». Если вы пишете быстро и грязно, то через месяц вы будете тратить в 10 раз больше времени на отладку. Давайте учиться на чужих ошибках, а не на своих.
2. Стандарты PSR: ваш первый шаг к порядку
В мире PHP есть PSR (PHP Standards Recommendations) — это рекомендации, которые приняло сообщество. Если вы не используете их, вы как минимум усложняете жизнь себе и коллегам, которые будут читать ваш код.
2.1 PSR-1 и PSR-12: Базовый стиль кодирования
PSR-1 задает общие правила, а PSR-12 — расширенный стиль. Вот несколько ключевых моментов:
- Файлы должны использовать только
<?phpили<?=. - Кодировка файлов — UTF-8 без BOM.
- Имена классов должны быть в
StudlyCaps(например,UserController). - Имена методов и свойств — в
camelCase(например,getUserName()). - Отступы — 4 пробела (не табуляция!).
Пример плохого кода:
<?
class user_controller {
function Get_User_Name($id) {
$name = Db::query("SELECT name FROM users WHERE id=$id");
return $name;
}
}
Пример хорошего кода (PSR-12):
<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Models\User;
class UserController
{
public function getUserName(int $id): ?string
{
$user = User::find($id);
return $user ? $user->getName() : null;
}
}
Видите разницу? Второй вариант читается как книга: сразу понятно, что делает метод, какие типы данных он принимает и возвращает.
2.2 PSR-4: Автозагрузка классов
Забудьте про require_once в каждом файле. Используйте Composer и PSR-4. Это позволяет подключать классы автоматически по пространству имен. Структура папок должна соответствовать неймспейсам:
src/
App/
Controllers/
UserController.php
Models/
User.php
Services/
PaymentService.php
В composer.json это настраивается одной строкой:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
3. Правильный нейминг: как не назвать переменную $a
Нейминг — это 50% успеха. Плохое имя переменной может запутать даже гения. Давайте разберем частые ошибки.
3.1 Избегайте сокращений (кроме очевидных)
Плохо: $usr_nm, $cnt, $d.
Хорошо: $userName, $counter, $date.
3.2 Булевы переменные должны звучать как вопрос
Плохо: $flag, $status.
Хорошо: $isActive, $hasAccess, $canEdit.
3.3 Имена функций должны быть глаголами
Плохо: userData() — непонятно, что делает.
Хорошо: getUserData(), saveUser(), validateEmail().
3.4 Пример рефакторинга нейминга
Было (ужас):
function gud($uid) {
$q = "SELECT * FROM users WHERE id=" . $uid;
$r = mysqli_query($conn, $q);
$d = mysqli_fetch_assoc($r);
return $d['name'];
}
Стало (красота):
public function getUserNameById(int $userId): string
{
$user = $this->userRepository->find($userId);
if (!$user) {
throw new UserNotFoundException("User with ID $userId not found");
}
return $user->getName();
}
Теперь даже джуниор поймет, что делает этот код, не заглядывая в документацию.
4. Магия SOLID: 5 принципов, которые спасут ваш проект
SOLID — это не абстрактная теория, а практические правила для объектно-ориентированного программирования. Давайте разберем их на примерах PHP.
4.1 S — Single Responsibility (Принцип единственной ответственности)
Класс должен иметь только одну причину для изменения. Если ваш класс Order умеет и сохранять заказ, и отправлять email, и генерировать PDF-счет — это нарушение SRP.
Плохо:
class Order {
public function save() { /* ... */ }
public function sendEmail() { /* ... */ }
public function generatePdf() { /* ... */ }
}
Хорошо (разделяем ответственность):
class OrderRepository {
public function save(Order $order) { /* ...