[Из песочницы] PHP и Temporal Coupling |
Здравствуйте, гость ( Вход | Регистрация )
[Из песочницы] PHP и Temporal Coupling |
11.4.2016, 13:09
Сообщение
#1
|
|
Администратор Группа: Главные администраторы Сообщений: 14349 Регистрация: 12.10.2007 Из: Twilight Zone Пользователь №: 1 |
Разработка*, Алгоритмы*, PHP* Про архитектуру приложений на PHP было написано не один десяток статей, но на данной проблеме больше акцентируют внимание разработчики Java и C#. Суть ее заключается в жесткой зависимости одного свойства на другом. Представим следующую ситуацию: Использование сеттера<?php class Page { /** * @var string */ private $content; /** * @param $content */ public function setContent($content) { $this->content = $content; } } class PageBuilder { /** * @var Page */ private $page; /** * @param $page */ public function setPage($page) { $this->page = $page; } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } } $pageBuilder = new PageBuilder(); $pageBuilder->setPage(new Page()); $pageBuilder->setContent('Test content'); $pageBuilder->build(); В данном примере видно, что $pageBuilder->build() является потенциально опасным и может привести к фатальной ошибке если $pageBuilder->setPage(new Page()) не был предварительно вызван. Другая часто встречающаяся ошибка — использование методов init() или initialization(): Использование инициализатораclass Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * Initialization */ public function init() { $this->page = new Page(); } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } } $pageBuilder = new PageBuilder(); $pageBuilder->init(); $pageBuilder->setContent('Test content'); $pageBuilder->build(); Если мы забудем вызвать метод init(), нас также ждут неприятности. Данный код является отличным примером плохой архитектуры приложения. Методы-инициализаторы пытаются вести себя как конструкторы, которыми не являются по определению. Для избежания Temporal Coupling нужно всегда пользоваться правилами:
Инъекция зависимости через конструктор Это решение является оптимальным и предпочтительным в большинстве случаев. Мы можем использовать механизмы Dependency Injection из Symfony, Laravel или других современных фреймворков. Инъекция через конструкторclass Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * PageBuilder constructor. * @param Page $page */ public function __construct(Page $page) { $this->page = $page; } // Методы-сеттеры } $pageBuilder = new PageBuilder(); $pageBuilder->setContent('Test content'); $pageBuilder->build(); Абстрактная фабрика Немного модифицируем наш код, добавив абстрактную фабрику: Абстрактная фабрика<?php class Page { // Class } class PageBuilder { /** * @var Page */ private $page; /** * PageBuilder constructor. * @param Page $page */ public function __construct(Page $page) { $this->page = $page; } /** * @param $content * @return $this */ public function setContent($content) { $this->page->setContent($content); return $this; } /** * @return Page */ public function build() { return $this->page; } } class PageBuilderFactory implements FactoryInterface { /** * @param Page|null $page * @return PageBuilder */ public function create(Page $page = null) { if (null === $page) { $page = new Page(); } return new PageBuilder($page); } } $pageBuilderFactory = new PageBuilderFactory(); $pageBuilder = $pageBuilderFactory->create(); $pageBuilder->setContent('Test content'); $pageBuilder->build(); Как видим, экземпляр класса Page создан без явного вызова и будет доступен нашему билдеру. Заключение Temporal Coupling нужно всегда избегать, вне зависимости от сложности приложения, влияния code-review или других факторов. Также помните что конструкторы должны выполнять только логику, связанную с инъекциями. Иначе вы рискуете получить ухудшение быстродействия на этапе создания экземпляров класса. Полезные ссылки Original source: habrahabr.ru (comments, light). Читать дальше -------------------- |
|
|
Текстовая версия | Сейчас: 29.1.2025, 23:40 | |