Вы находитесь на странице: 1из 47

Архитектура, алгоритмы и паттерны на PHP

Урок 3.
Ошибки при
проектировании.
Антипаттерны
План занятия

● Как применять шаблоны, чтобы не сделать хуже.


● Разбираем «популярные» антипаттерны.
Всегда ли шаблоны — это
безусловно хорошо?
Когда это плохо

● Насильственная адаптация кода к шаблону.


● Применение ради применения.
Вывод

Использовать шаблоны нужно, только


если потенциальный выигрыш от их
применения больше стоимости
трудозатрат на это.
Антипаттерны — паттерны
наоборот, «вредные советы».
Антипаттерны — распространённый
подход к решению часто
встречающихся проблем, при этом
неэффективный, рискованный или
непродуктивный.
Антипаттерны условно делят на:
● антипаттерны разработки
(development antipatterns);
● архитектурные антипаттерны
(architectural antipatterns);
● организационные антипаттерны
(managerial antipatterns).
Антипаттерны условно делят на:
● антипаттерны разработки
(development antipatterns);
● архитектурные антипаттерны
(architectural antipatterns);
● организационные антипаттерны
(managerial antipatterns).
Дополнительно разделим
Антипаттерны в коде
Спагетти-код (Spaghetti Code)

Код с чрезмерно запутанным порядком


выполнения.

Что делать: структурировать,


распределить функциональность по
компонентам.
Сигналами спагетти-кода могут стать:
● Чрезмерное использование глобальных переменных. Не стоит ими
злоупотреблять.

● Пересечение библиотек (одна частично содержит другую), перекрёстные


вызовы. Стоит заранее изучить внедряемый код и не допускать повторений.

● «Бесполезные» действия. Тот случай, когда в рамках одного кода встречаются


функции с противоположным действием, сводящие общий эффект к нулю.

● Однотипные или неговорящие названия. Если в коде встречаются smth1.php,


smth2.php, smth3.php, то необходимо срочно заняться переименованием. Это
касается и переменных.
Сигналами спагетти-кода могут стать:

● Повисший и неиспользуемый код. Такие «артефакты» могут не только затруднить


понимание, но и запутать разработчика.

● Чрезмерное использование циклов. Если закончились буквы для индексов или


количество вложенных циклов уже трудно подсчитать, то пора бить тревогу.

● Условия в if, требующие долгой прокрутки вправо. Стоит задуматься либо о


разделении, либо об упрощении кода.
Лазанья-код (Lasagna Code)

Использование неоправданно большого


количества уровней абстракции.

Что делать: рефакторинг,


направленный на упрощение,
избавление от лишних уровней
абстракции.
Слепая вера (Blind Faith)

Недостаточная проверка корректности


исправления ошибки или результата
работы подпрограммы.

Что делать: всегда проверять


возвращаемые извне результаты на
ошибки.
Кодирование исключениями
(Code by Exception)
Добавление нового исключения «на
каждый чих».

Что делать: вводить новые типы


исключений только для группы ошибок,
объединённых по какому-либо
признаку.
Шифрованный код
(Cryptic code)
Использование аббревиатур в качестве
имён.

Что делать: заменить аббревиатуры в


именах сущностей на мнемонические
имена.
Шифрованный код
(Cryptic code)

Class UFG { Class Order {


private $fdgdfg; private $data;

function doUD() {} function updateData() {}


} }

$u1_0 = 'Иванов Иван'; $userName = 'Иванов Иван';


$u1_1 = 'ivan@ivn.ru'; $userEmail = 'ivan@ivn.ru';
$u1_2 = 'Случайный $userComment = 'Случайный
комментарий'; комментарий';

const S1 = 1; const STATUS_ERROR = 1;


const S2 = 2; const STATUS_PAGE_NOT_FOUND =
2;
Магические числа
(Magic numbers)
Использование числовых констант без
объяснения их смысла.

Что делать: объявить число в виде


именованной константы, при
необходимости сопроводить
комментарием.
Магические числа
(Magic numbers)

$a = 100; const MIN_LIMIT = 100;


$i = 100; const MAX_LIMIT = 1000;
while ($i <= 1000) { const DIVIDER = 7**2;
if ($i != 0 && $i % 7*7 == 0) {
return $i; $i = MIN_LIMIT;
}
$i++; while ($i <= MAX_LIMIT) {
} if ($i != 0 && $a % DIVIDER == 0) {
return $i;
}
$i++;
}
Жёсткое кодирование
(Hard code)
Внедрение предположений об окружении
системы в слишком большом количестве
точек её реализации.

Что делать: вынести сведения об


окружении системы в
конфигурационные файлы и
использовать их только оттуда.
Мягкое кодирование
(Soft code)
Патологическая боязнь жёсткого
кодирования, приводящая к тому, что
настраивается всё что угодно.

Что делать: конфигурировать лишь те


параметры, которые потенциально
часто могут изменяться.
Антипаттерны в ООП
Божественный объект
(God Object)
Концентрация слишком большого
количества функций в одном классе.

Что делать: разделить


функциональность такого объекта и
делегировать её разным классам.
<?php

Божественный объект class GodObject {


protected $order;

(God Object) protected $delivery;


protected $promo;

public function calculateSale($promo) {...}

public function confirmDelivery($delivery) {...}

public function makeOrder() {...}

public function getOrder() {...}

public function setOrder($order) {...}

public function getDelivery() {...}

public function getPromo(){...}

}
Полтергейст
(Poltergeist)
Объекты, чьё единственное
предназначение — передавать
информацию другим объектам.

Что делать: избавиться от объекта-


полтергейста либо добавить ему
дополнительную полезную
функциональность.
Полтергейст
(Poltergeist)
<?php

class CarMore {
private Car $car;

public function __construct()


{
$this->car = new Car();
}

function drive() {
$car->drive();
}

function makeLoudSound() {
$car -> beep();
}
}
Сплошное одиночество
(Singletonitis)
Неуместное использование паттерна
«Одиночка».

Что делать: свести к крайне


необходимому минимуму
использование классов-одиночек.
Приватизация (Privatization)
Сокрытие функциональности в
приватной секции (private), что
затрудняет его расширение в классах-
потомках.

Что делать: функционально важные


методы в классе объявить как
защищённые (protected).
Интерфейсная солянка
(Interface Soup)
Объединение нескольких интерфейсов,
раздёленных согласно принципу изоляции
интерфейсов (Interface segregation), в
один.

Что делать: разделить контракт


интерфейса на несколько более
мелких контрактов.
Интерфейсная солянка
(Interface Soup)

<?php
interface animal {
protected function run();
protected function swim();
protected function fly();
protected function eatMeat();
}
Заглушка (Stub)

Попытка «натянуть» на объект уже


имеющийся малоподходящий по смыслу
интерфейс.

Что делать: создать новый интерфейс.


Методологические антипаттерны
Программирование методом
копирования и вставки
(Copy-Paste programming)
Копирование (и лёгкая модификация)
существующего кода вместо создания
общих решений.

Что делать: не допускать копирования


чужого кода. Создавайте общие
решения.
Золотой молоток
(Golden Hammer)

Уверенность в том, что найденное


решение универсально.

Что делать: для каждой конкретной


задачи необходимо искать наиболее
эффективное решение.
Фактор невероятности
(Improbability factor)

Предположение, что известная ошибка


наверняка не сработает

Что делать: не полагаться на догадки.


Код должен быть всегда хорошо
написан, вне зависимости от текущих
условий.
Преждевременная оптимизация
(Premature optimization)
Оптимизация ускоряет работу
программы по времени или памяти, но
делает код менее понятным.
Что делать: процесс оптимизации
должен происходить поэтапно и только
на основе анализа уже написанного и
работающего кода.
Изобретение колеса
(Reinventing the wheel)

Создание решения с нуля, а не


использование готового.

Что делать: когда встречается


распространённая задача, стоит
поискать готовые и проверенные
решения, прежде чем изобретать
собственные.
Изобретение квадратного колеса
(Reinventing the square wheel)

Создание плохого решения, когда


существует хорошее известное
решение.
Что делать: использовать готовое
решение, которое лучше.
Архитектурные антипаттерны
Инверсия абстракции
(Abstract Inversion)
Сокрытие части функциональности в
надежде, что никто не будет его
использовать.

Что делать: проанализировать


требования к классу и варианты его
использования.
Большой комок грязи
(Big ball of mud)
Система с нераспознаваемой
структурой.
Что делать: структурировать код,
разделить его на слои и абстракции.
Затычка на ввод (Input kludge)

Забывчивость в спецификации и
поддержке потенциально неверного
ввода.

Что делать: всегда составлять строгую


спецификацию на ввод данных извне,
валидировать и обезвреживать
введённые данные.
Волшебная кнопка
(Magic pushbutton)
Выполнение результатов действий
пользователя в виде неподходящего
(недостаточно абстрактного)
интерфейса.

Что делать: бизнес-логику размещать


только в определённом
спецификацией разделе.
Членовредительство (Mutilation)
Излишнее затачивание объекта под узкую задачу
таким образом, что он не способен будет
работать ни с какими иными задачами, пусть и
очень схожими.

Что делать: увеличить абстракцию


кода без привязки к конкретной
реализации.
Задание
Цель — научиться критически подходить к принятию
решений и постараться понять, какие реализации
считаются хорошими, а какие следует переписать.

1. Провести code review ваших прошлых проектов,


чтобы найти использование антипаттернов.
Укажите классы и строки, в которых они
проявляются. Или найти места, где антипаттерны
могли бы появиться, но код написан верно.

2. Распределить обнаруженные антипаттерны по


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

Вам также может понравиться