[PHP, Проектирование и рефакторинг, Yii] SOLID на практике. Принцип открытости-закрытости и ActiveQuery Yii2
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Как-то в рабочей беседе один мой коллега-программист заметил, что всевозможные принципы и паттерны проектирования ПО хорошо применять, когда делаешь тестовые задания, однако в реальных, боевых проектах они как правило неприменимы. Почему так? Основных причин две:
- Реализация принципов и паттернов требует слишком много времени.
- Код становится тяжеловесным и сложным для понимания.
В серии статей «На практике» я попробую развеять эти предубеждения, продемонстрировав кейсы, реализующие принципы проектирования в практических задачах таким образом, чтобы этот код не был слишком сложным и на его написание уходило разумное количество времени. Вот первая статья из этой серии. Отправная точкаРаботаем над проектом на Yii2, в котором для доступа к данным используется ActiveRecord. Клиентский код загружает некий набор данных, используя метод ActiveRecord::find().
class ClientClass
{
// Много кода...
public function buildQuery(): ActiveQueryImplementation
{
$query = ActiveRecordModel::find(); // Получаем экземпляр ActiveQuery из модели
$query->active()->unfinished(); // Применяем условия, реализованные в конкретном классе ActiveQuery
return $query; // Далее результаты построения ActiveQuery используются для получения выборки из БД, например $query->all();
}
// Много кода...
}
Этот код применяет к экземпляру, реализовывающему ActiveQueryInterface, фиксированный набор условий и возвращает сконфигурированный таким образом экземпляр для дальнейшего использования. А если нужно добавить новые условия в запрос?Придерживаясь традиционного подхода, мы добавим вызовы методов с новыми условиями прямо в строку, применяющую эти условия к запросу.
$query->active()->unfinished()->newConditionA()->newConditionB();
Вуаля! Пять секунд работы, и мы получили изящный, легко читаемый код. Но что если эти условия нужны не во всех случаях, когда вызывается наш метод? Что если условия к запросу нужно применять динамически? Тут нас ждут определенные трудности. Очевидно, что при таком подходе весь клиентский код, использующий наш метод, будет получать запрос, к которому уже применены новые условия. Почему так получилось? Потому что мы... Нарушаем принцип открытости-закрытости Напомню, что принцип открытости-закрытости SOLID гласит:
Код должен быть открытым для дополнения и закрытым для изменения.
Мы изменили код нашего метода таким образом, что он начал выдавать другие результаты. А как сделать правильно? Чтобы соблюсти принцип открытости-закрытости, нам нужно было бы предусмотреть возможность в случае необходимости дополнять код таким образом, чтобы добавлять в него новые условия, не внося изменений в логику работы метода по умолчанию и не меняя его исходный код.Для этого изменим код нашего метода следующим образом.
class ClientClass
{
/**
* @var ActiveQueryFilter[]
*/
public $filters = []; // Добавляем возможность сконфигурировать экземпляр класса массивом фильтров
// Много кода...
public function buildQuery(): ActiveQueryImplementation
{
$query = ActiveRecordModel::find();
$query->active()->unfinished();
$this->applyFilters($query); // Применяем фильтры к запросу
return $query;
}
private function applyFilters(ActiveQueryImplementation &$query): void
{
foreach ($this->filters as $filter) {
$filter->applyTo($query);
}
}
// Много кода...
}
Определим интерфейс ActiveQueryFitler предполагает единственный метод applyTo(), применяющий дополнительные условия к запросу в качестве побочного эффекта.
interface ActiveQueryFilter
{
public function applyTo(ActiveQuery $query): void;
}
Теперь для добавления в запрос новых условий нам достаточно добавить соответствующую реализацию интерфейса ActiveQueryFilter.
class NewConditionsAAndBFilter implements ActiveQueryFilter
{
public function applyTo(ActiveQuery $query): void
{
$query->newCondtionA()->newConditionB();
}
}
Что мы имеем в итоге
- Мы решили стоящую перед нами задачу, дополнив первоначальный метод всего одним вызовом (минимальное вмешательство в первоначальный код).
- Поведение по умолчанию исходного метода не изменилось.
- Вызываемый из исходного метода новый метод applyFilters() не реализовывает собственной логики — вся логика делегируется классам фильтров. Таким образом, мы оставили неизменным и поведение всего исходного класса.
===========
Источник:
habr.com
===========
Похожие новости:
- [Анализ и проектирование систем, Проектирование и рефакторинг, Распределённые системы, Микросервисы] Макропроблема микросервисов (перевод)
- [Программирование, Проектирование и рефакторинг, Профессиональная литература] Как событийно-ориентированная архитектура решает проблемы современных веб-приложений (перевод)
- [PHP] Приглашаю все на вебинар по вопросам безопасности PHP
- [Программирование, Проектирование и рефакторинг] Рефакторинг без особой боли
- [Анализ и проектирование систем, SQL, Проектирование и рефакторинг] Опрос. Денормализация или нет?
- [Информационная безопасность, PHP] Почему я не люблю PHP
- [Разработка веб-сайтов, PHP, Программирование, Проектирование и рефакторинг] Сейчас я буду убеждать вас использовать статический анализ в PHP
- [PHP, Программирование] Состоялся релиз языка программирования PHP 8.0
- Релиз языка программирования PHP 8.0
- [Разработка веб-сайтов, PHP] Встречаем PHP 8 вместе: советы по обновлению, мнения за и против и интервью с одним из ключевых разработчиков
Теги для поиска: #_php, #_proektirovanie_i_refaktoring (Проектирование и рефакторинг), #_yii, #_solid, #_printsip_otkrytostizakrytosti (принцип открытости-закрытости), #_yii2, #_php, #_proektirovanie_i_refaktoring (
Проектирование и рефакторинг
), #_yii
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:11
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Как-то в рабочей беседе один мой коллега-программист заметил, что всевозможные принципы и паттерны проектирования ПО хорошо применять, когда делаешь тестовые задания, однако в реальных, боевых проектах они как правило неприменимы. Почему так? Основных причин две:
class ClientClass
{ // Много кода... public function buildQuery(): ActiveQueryImplementation { $query = ActiveRecordModel::find(); // Получаем экземпляр ActiveQuery из модели $query->active()->unfinished(); // Применяем условия, реализованные в конкретном классе ActiveQuery return $query; // Далее результаты построения ActiveQuery используются для получения выборки из БД, например $query->all(); } // Много кода... } $query->active()->unfinished()->newConditionA()->newConditionB();
Код должен быть открытым для дополнения и закрытым для изменения.
class ClientClass
{ /** * @var ActiveQueryFilter[] */ public $filters = []; // Добавляем возможность сконфигурировать экземпляр класса массивом фильтров // Много кода... public function buildQuery(): ActiveQueryImplementation { $query = ActiveRecordModel::find(); $query->active()->unfinished(); $this->applyFilters($query); // Применяем фильтры к запросу return $query; } private function applyFilters(ActiveQueryImplementation &$query): void { foreach ($this->filters as $filter) { $filter->applyTo($query); } } // Много кода... } interface ActiveQueryFilter
{ public function applyTo(ActiveQuery $query): void; } class NewConditionsAAndBFilter implements ActiveQueryFilter
{ public function applyTo(ActiveQuery $query): void { $query->newCondtionA()->newConditionB(); } }
=========== Источник: habr.com =========== Похожие новости:
Проектирование и рефакторинг ), #_yii |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:11
Часовой пояс: UTC + 5