Ответ
«Запахи кода» — это поверхностные индикаторы потенциально более глубоких проблем в дизайне или архитектуре программы. Они не являются багами сами по себе, но сигнализируют о нарушениях принципов чистого кода (SOLID, DRY), что затрудняет чтение, тестирование и поддержку.
Распространённые запахи кода и примеры на PHP:
-
Дублирование кода (Violation of DRY): Одна и та же логика в нескольких местах.
// Запах function calculateCartTotal($items) { $total = 0; foreach ($items as $item) { $total += $item['price'] * $item['quantity']; // Логика расчёта стоимости дублируется } return $total; } function generateInvoiceLine($item) { return $item['price'] * $item['quantity']; // То же самое здесь } -
Длинный метод: Метод, который делает слишком много и его сложно понять.
-
Большой класс (Божественный объект): Класс, который знает и делает слишком много, нарушая принцип единственной ответственности (SRP).
-
Цепочка вызовов (Feature Envy): Чрезмерное обращение к внутренним данным другого объекта.
// Запах: класс Customer слишком много знает о внутреннем устройстве Order $discount = $customer->getOrder()->getItems()->getLast()->getPromo()->getValue(); -
Использование "магических" чисел или строк: Непонятные значения прямо в коде.
// Запах if ($user->age > 18) { // Что такое 18? // ... } // Рефакторинг const LEGAL_AGE = 18; if ($user->age > LEGAL_AGE) { // ... }
Рефакторинг примера с дублированием:
// Выносим общую логику в отдельный метод/функцию
function calculateItemTotal(float $price, int $quantity): float {
return $price * $quantity;
}
function calculateCartTotal(array $items): float {
$total = 0.0;
foreach ($items as $item) {
$total += calculateItemTotal($item['price'], $item['quantity']);
}
return $total;
}
function generateInvoiceLine(array $item): string {
$lineTotal = calculateItemTotal($item['price'], $item['quantity']);
return "{$item['name']}: {$lineTotal} USD";
} Ответ 18+ 🔞
А, ну это же классика, ёпта! Сидишь такой, читаешь чужой код, а от него прямо волнение ебать — пахнет, как будто в программировании только вчера открыли, что функции бывают. Эти «запахи кода» — они как сигнал: «Чувак, тут пиздец, но пока не критичный». Сам по себе код может работать, но читать его — терпения ноль ебать, а через полгода и поддерживать будет охренеть как сложно.
Вот смотри, основные «ароматы», от которых глаза слезятся.
1. Дублирование кода (Нарушение DRY — Don't Repeat Yourself). Это когда одно и то же говно написано в пяти разных местах. Представь, у тебя формула расчёта суммы в корзине и в строке счёта. И ты её тупо копипастишь.
// Запах — чувствуешь, да? Одна и та же хуйня в двух местах.
function calculateCartTotal($items) {
$total = 0;
foreach ($items as $item) {
$total += $item['price'] * $item['quantity']; // Вот эта строчка...
}
return $total;
}
function generateInvoiceLine($item) {
return $item['price'] * $item['quantity']; // ...она же тут, блядь! Дубликат!
}
2. Длинный метод. Открываешь функцию, а там овердохуища строк. Она и печеньки печёт, и на сервер грузит, и письма отправляет. Разобраться, что она делает — задача для экстрасенса. Через месяц сам от себя охуеешь, пытаясь вспомнить логику.
3. Большой класс (он же «Божественный объект»). Этот класс знает всё: он и пользователя авторизует, и заказы обрабатывает, и отчёты в PDF генерит, и, кажется, уже кофе заваривать начинает. Нарушает первый же принцип SOLID — единственная ответственность. Такой класс — это пизда рулю, чистой воды.
4. Цепочка вызовов (Feature Envy). Когда один объект лезет в сраку другому, вытаскивая данные через длиннющую цепочку методов. Смотри, какой пиздец:
// Класс Customer вдруг решил, что ему жизненно важно знать про последнюю промо-акцию последнего товара в заказе.
// Да ты кто такой, сука? Прекрати!
$discount = $customer->getOrder()->getItems()->getLast()->getPromo()->getValue();
Малейшее изменение в классе Order — и всё, приехали, всё посыпется. Доверия к такому коду — ебать ноль.
5. «Магические» числа и строки. Просто цифры или тексты, вставленные в код без пояснений. Смотришь и думаешь: «А это нахуя 18?».
// Запах — что за хуй с горы?
if ($user->age > 18) { // 18? Это возраст совершеннолетия, что ли? А если юрисдикция поменяется?
// ...
}
// Рефакторинг — делаем понятную константу, ядрёна вошь!
const LEGAL_AGE = 18;
if ($user->age > LEGAL_AGE) { // А, всё, теперь ясно.
// ...
}
Как это починить? Рефакторим пример с дублированием:
Всё просто, ебушки-воробушки. Выносим общую логику в отдельную сущность, чтобы не повторяться.
// Делаем одну маленькую, но гордую функцию для одной конкретной операции.
function calculateItemTotal(float $price, int $quantity): float {
return $price * $quantity; // И больше эта формула нигде не дублируется!
}
function calculateCartTotal(array $items): float {
$total = 0.0;
foreach ($items as $item) {
// Используем нашу новую функцию. DRY, детка!
$total += calculateItemTotal($item['price'], $item['quantity']);
}
return $total;
}
function generateInvoiceLine(array $item): string {
// И тут тоже её используем. Красота!
$lineTotal = calculateItemTotal($item['price'], $item['quantity']);
return "{$item['name']}: {$lineTotal} USD";
}
Вот и всё. Чувствуешь, как запах выветрился? Код стал чище, логичнее, и когда надо будет поменять формулу расчёта (например, добавить налог), ты поправишь её в ОДНОМ месте, а не бегать по всему проекту, как угорелый.