сервис локатор паттерн php

А такой ли уж анти-паттерн этот Service Locator?

В индустрии сложилось устойчивое мнение, что Service Locator является анти-паттерном. Из wiki:

Стоит заметить, что в некотором случае локатор служб фактически является анти-шаблоном.

В этой публикации я рассматриваю тот случай, когда, на мой взгляд, Service Locator анти-шаблоном не является.

Вот что пишут в интернетах по поводу Локатора:

Некоторые считают Локатор Служб анти-паттерном. Он нарушает принцип инверсии зависимостей (Dependency Inversion principle) из набора принципов SOLID. Локатор Служб скрывает зависимости данного класса вместо их совместного использования, как в случае шаблона Внедрение Зависимости (Dependency Injection). В случае изменения данных зависимостей мы рискуем сломать функционал классов, которые их используют, вследствие чего затрудняется поддержка системы.

Service Locator идёт рука об руку с DI настолько близко, что некоторые авторы (Mark Seemann, Steven van Deursen) специально предупреждают:

Т.е., Локатор чертовски хорош и работает почти как надо, но есть один момент, который всё портит. Вот он:

The main problem with Service Locator’s the impact of reusability of the classes consuming it. This manifests itself in two ways:

* The class drags along the Service Locator as a redundant Dependency.

* The class makes it non-obvious what its Dependencies are.

Т.е., шаблон уменьшает возможности переиспользования кода некоторого класса по двум причинам: во-первых, из-за лишней зависимости класса от самого Локатора, во-вторых, становится неочевидным, какие зависимости используются классом.

Другими словами, вот так создавать объекты и внедрять в них зависимости благословляется:

При этом внедрение зависимостей через свойства (акцессоры) теми же авторами признаётся кошерным в некоторых случаях (например, когда внедряемые зависимости опциональны или задаются по умолчанию в конструкторе и могут быть переопределены впоследствии):

Property Injection should only be used when the class you’re developing has a good Local Default, and you still want to enable callers to provide different implementations of the class’s Dependency. It’s important to note that Property Injection is best used when the Dependency is optional. If the Dependency is required, Constructor Injection is always a better pick.

Если мы перепишем наш класс с Локатором в таком виде:

то, а) мы делаем его независимым от наличия Локатора (например, в тестовой среде), б) явным образом выделяем зависимости в setter’ах (также можно аннотировать, документировать, ставить префиксы и решать проблему «неочевидности» зависимостей любым другим доступным способом, вплоть до Ctrl+F по ключу «$locator->get» в коде).

Вот мы и подошли к тому моменту, когда, на мой взгляд, использование Локатора оправдано. В комментах к статье «Какое главное отличие Dependency Injection от Service Locator?» коллега @symbix резюмировал тему статьи так:

SL работает по принципу pull: конструктор «вытягивает» из контейнера свои зависимости.

DI работает по принципу push: контейнер передает в конструктор его зависимости.

Т.е., по сути дела, DI-контейнер объектов может использоваться и как Service Locator:

«Анти-паттерн» Service Locator же позволяет нам «вытягивать» из контейнера нужные нам зависимости по мере обращения к ним:

Итого, приведённый выше код:

может быть использован без контейнера в конструкторе за счёт возможности внедрения зависимости через setter (например, в тестах);

зависимости явно описываются через набор private-методов с префиксом init ;

иерархия зависимостей не тянется при создании экземпляра данного класса, а создаётся по мере использования.

Вот в таком варианте Service Locator становится очень даже «pattern» без всяких «anti».

Послесловие

Источник

Какое главное отличие Dependency Injection от Service Locator?

Ха, какая изящная маскировка Service Locator-а под DI. Даже может показаться, что это DI! 🙂

Это первый коммент к моей предыдущей публикации «Dependency Injection, JavaScript и ES6-модули». Спасибо коллеге symbix ‘у за этот коммент, т.к. именно он стало причиной погружения в тонкости отличия одного от другого. Под катом мой ответ на вопрос в заголовке.

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн php

(КДПВ особого смысла не имеет и предназначена в первую очередь для визуального опознания этой публикации в ряду других)

Для начала разберёмся с определениями (часть примеров кода я буду приводить на PHP, часть на JS, потому что эти два языка в настоящее время находятся в моём активном багаже, а часть на любом другом, потому что я спёр эти примеры из интернета).

Dependency Injection

DI же в двух словах — вместо require/import модуля вы инжектируете зависимость через параметр конструктора (или сеттер свойства). То есть за этим громким словом стоит простое «передавайте зависимости класса через параметры конструктора».

Этот коммент коллеги risedphantom ‘а довольно точно передает суть явления. Чтобы облегчить понимание кода разработчиком все зависимости описываются в явном виде — в виде параметров конструктора (обычно, но не всегда):

Всё. DI — он именно об этом. Нужные нам зависимости предоставляются кем-то там. А где этот «кто-то там» их берёт — DI это не волнует.

При анализе кода важно понимать, что именно «внутреннее» для него (и что мы можем смело менять), а что приходит/уходит за границу ответственности данного кода. Вот это волнует DI. Почему зависимости, в основном, передаются через конструктор, а не в setter’ах? Потому что разработчику так удобнее — он сразу видит все зависимости анализируемого кода в одном месте. Мы привыкли считать, что DI — это что-то на уровне классов, но параметры функции/метода — это ведь тоже DI:

Конструктор — это просто такой особый метод среди всех других.

Service Locator

Локатор служб — широко известный анти-шаблон. А чем он занимается? Предоставляет доступ одним объектам к другим объектам. Вот типичный интерфейс такого локатора:

Локатор представляет собой контейнер, в который можно положить готовые объекты (или задать правила их создания) и затем получить доступ к этим объектам. Локатору, по большому счёту, всё равно, каким образом в нём оказываются объекты — созданы они извне явным образом и помещены в контейнер или созданы самим контейнером согласно заданным правилам.

Локатор служб отвечает за хранение объектов и предоставление к ним доступа. Всё.

Dependency Injection Container

Что такое DI-контейнер? Согласно вольного пересказа содержимого «Dependency Injection Principles, Practices, and Patterns»: «a software library that that provides DI functionality and allows automating many of the tasks involved in Object Composition, Interception, and Lifetime Management. DI Containers are also known as Inversion of Control (IoC) Containers. (§3.2.2)»

Т.е., DI-контейнер в первую очередь отвечает за создание объектов, а лишь во вторую — за их хранение. В DI-контейнере может вообще не хранится ни одного созданного объекта, если само приложение не нуждается в объектах, общих для всего приложения (типа конфигурации или логгера).

Вот, например, интерфейс DI-контейнера Symfony:

Чем же плох Service Locator?

А ничем. Плох не сам шаблон, а то, каким образом он иногда используется. В частности, есть такое мнение, что «Service Locator нарушает инкапсуляцию в статически типизированных языках, потому что этот паттерн нечётко выражает предусловия«. И пример нарушения:

Типа, вот так плохо, а хорошо — вот так:

Composition Root

Говоря о Внедрении Зависимостей мы не можем не прийти к такому понятию, как Composition Root (далее я буду назвать это «Точка Сборки»). Это тот самый «кто-то«, кому делегированы обязанности по созданию зависимостей и их внедрению.

В Точке Сборки все зависимости явно определяются, соответствующие объекты создаются и внедряются туда, где их ждут. Здесь различия между Локатором Служб и DI-контейнером минимальны. И тот и другой позволяют создавать новые объекты, хранить созданные объекты, извлекать хранимые объекты. Я бы даже взялся утверждать, что в этом месте принципиальных различий между ними нет.

Главное отличие

А где же различия между DI-контейнером и контейнером Локатора Служб наиболее явные? В любом другом месте, а особенно при статическом доступе к контейнеру:

Вот оно. В таком виде в любом месте (если только это не Точка Сборки, но и там использование статического доступа весьма сомнительно) любой контейнер становится анти-паттерном с именем Service Locator.

Коллега VolCh кратко и ёмко ответил на мой вопрос:

А чем, по вашему, true DI отличается от Service Locator, замаскированного под DI?

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

Легальное применение Контейнера

Таким образом, является ли Контейнер DI-контейнером или контейнером Локатора Служб, очень сильно зависит от того, где и каким образом мы его используем. Как я уже сказал выше, в Точке Сборки разница между типами контейнеров исчезает. Но что мы передаём, если контейнер сам является зависимостью для какого-либо класса?

Опять-таки, все зависит от того, каким образом мы используем контейнер. Вот два примера, один из которых точно соответствует контейнеру Локатора Служб и является анти-паттерном, а другой имеет право на жизнь при определённых условиях.

Резюме

На самом деле всё несколько сложнее, DI-контейнер должен обладать более широким функционалом, чем Локатор Служб, но суть этой публикации в том, что даже самый навороченный DI-контейнер лекго и просто можно использовать, как Локатор Служб, а вот чтобы Локатор Служб использовать как DI-контейнер — нужно постараться.

Источник

Управление зависимостями — PHP: Полиморфизм

На протяжении всего курса, мы говорили про процесс инициализации, внутри которого создаются необходимые объекты. Затем эти объекты используются в прикладном коде. К таким объектам относятся: соединение с базой данных, логгер, кеш, шаблонизатор, интеграция с внешними сервисами и многое другое.

В простых ситуациях, там где объектов немного и мы сами управляем кодом (а не используем фреймворки, определяющие структуру), зависимости можно внедрять «руками»:

В коде, который активно использует инверсию зависимостей, инициализация кода выглядит как матрёшка из объектов. Объекты верхнего уровня принимают на вход объекты с нижних слоёв, шаг за шагом собирая готовое приложение.

С ростом числа объектов, процесс сборки усложняется и становится утомительным. Появляются ситуации, в которых объекты нужны в самой глубине кода, но прокинуть их можно только пройдя множество уровней. В популярных фреймворках инициализация может включать в себя создание и внедрение сотен объектов. Страшно даже представить, что придётся писать этот код вручную.

Для решения данной задачи, используется два подхода (шаблона проектирования). Ниже поговорим про каждый из них

Локатор (Service Locator)

Возьмём для примера микрофреймворк Slim. У него есть расширение PHP-View, которое добавляет шаблонизатор в фреймворк. Попробуем внедрить это расширение через Service Locator:

Вот такой нехитрый подход для внедрения зависимостей. По нему написаны сотни статей со всевозможными вариациями его создания и использования. В большинстве из них локатор рассматривается как антипаттерн. Так как прикладной код знает про его существование.

Контейнер (DI Container)

Вершиной эволюции инверсии зависимостей считается DI Container. Продвинутые контейнеры, это целые фреймворки, которые занимаются инициализацией приложения, собирают необходимые объекты и прокидывают их друг в друга. В некоторых экосистемах, контейнер – центральная часть всей системы, которая занимается её оркестрацией (управлением). В Java, например, это Spring Framework. Он с лёгкостью может собирать и веб-приложение и демонов.

Ключевое отличие контейнера от локатора в том, что зависимости из контейнера попадают внутрь приложения прозрачно. Прикладной код не догадывается о существовании контейнера, он лишь видит объекты которых ждёт. Для инъекции этих зависимостей используются стандартные подходы: либо через конструктор, либо через сеттеры и аргументы методов.

Снова посмотрим на Slim и интеграцию с PHP-View, но уже через встроенный контейнер:

Источник

Сервис локатор паттерн php

Цитатник веб-разработчиков В тексте курса вы встретите цитаты, высказанные в разное время разработчиками системы и разработчиками проектов на базе Bitrix Framework. Надеемся, что такие неформальные замечания внесут некоторое разнообразие в процесс изучения. Заодно опытные специалисты поделятся и своим опытом.

Чтобы научиться программировать в Bitrix Framework, нет необходимости изучать всю линейку курсов. Но есть моменты, которые необходимо знать разработчикам о системе, они раскрыты в начальных курсах:

Как построен курс

Общепринятая градация квалификации разработчиков в рамках курса обозначает что:

Начальные требования к подготовке

Для успешного изучения курса и овладения мастерством разработки сайтов на Bitrix Framework необходимо владеть (хотя бы на начальном уровне):

У нас часто спрашивают, сколько нужно заплатить

Но у нас есть Академия 1С-Битрикс, где можно обучиться на платной основе на курсах нашей компании либо наших партнёров.

Тесты

После изучения курса вам будет предложено пройти тесты на сертификацию. При успешной сдаче последовательности тестов на странице Моё обучение можно просмотреть результат обучения и загрузить сертификат в формате PDF.

Комментарии к статьям

Что дальше?

Одновременно с изучением курса Разработчик Bitrix Framework вам придётся обращаться к информации о других технологиях Bitrix Framework. Эта информация размещена в следующих курсах:

Для преподавания оффлайн

Если данный курс берётся в качестве основы для оффлайного преподавания, то рекомендуемая продолжительность: 5 дней (40 академических часов).

Если нет интернета

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн phpСкачать материалы курса в формате EPUB. Файлы формата EPUB Чем открыть файл на
Android:
EPUB Reader
CoolReader
FBReader
Moon+ Reader
eBoox

iPhone:
FBReader
CoolReader
iBook
Bookmate

Windows:
Calibre
FBReader
Icecream Ebook Reader
Плагины для браузеров:
EpuBReader – для Firefox
Readium – для Google Chrome

iOS
Marvin for iOS
ShortBook
обновляются периодически, поэтому возможно некоторое отставание их от онлайновой версии курса.

Источник

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн php

Продолжаю тему паттернов проектирования и в этом посте мы рассмотрим чем отличаются 2 озвученных в заголовке паттерна и для чего они нужны на примерах.

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн php

Верите или нет, но многие Android — разработчики, использовали DI с самого первого приложения, даже не зная о таких вещах как Dagger, Koin или другие фреймворки, облегчающие внедрение зависимостей. Как такое возможно? Давайте рассмотрим азы внедрения зависимости на примере.

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн php

А теперь взгляните на код класcа CarB

сервис локатор паттерн php. Смотреть фото сервис локатор паттерн php. Смотреть картинку сервис локатор паттерн php. Картинка про сервис локатор паттерн php. Фото сервис локатор паттерн php

В полном соответствии с принципом единственной обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму.

Следуя принципу DI, вы строите фундамент хорошей архитектуры вашего приложения. Используя DI вы автоматически получаете следующие преимущества:

Надеюсь, теперь стало понятно что такое DI и почему в каждой вакансии все требуют знание какого-либо DI-фреймворка. Давайте теперь рассмотрим какие есть способы внедрения зависимостей (DI) в Android:

А теперь расскажите что такое ServiceLocator

Альтернативой DI является паттерн, или как многие его называют антипаттерн ServiceLocator. Этот паттерн также как и DI уменьшает связанность кода. Однако, на мой взгляд имеет существенные недостатки. Суть паттерна в том, что вместо того, чтобы application или некий control flow передавал зависимости классу, сам класс вызывает некий метод для инициализации нужной ему зависимости. Это выглядит так:

То есть мы создали некую фабрику, которую класс Car использует для получения нужной ему зависимости.

Недостатки ServiceLocator

Существует две версии реализации паттерна ServiceLocator. Локатор сам по себе может быть синглтоном (в классическом виде, или в виде класса с набором статических методов), тогда доступ к нему может производиться из любой точки в коде (как в примере выше).

Или же ServiceLocator может передаваться требуемым классам через конструктор или свойство в виде объекта класса или интерфейса.

Оба эти подхода страдают от одних и тех же недостатков, но в первом случае все ниже перечисленные проблемы усиливаются, поскольку в этом случае совершенно любой класс приложения может быть завязан на любой «сервис».

Недостатками паттерна ServiceLocator являются:

Если класс принимает экземпляр сервис локатора, или, хуже того, использует глобальный локатор, то этот контракт, а точнее требования, которые нужно выполнить клиенту класса, становятся неясными. То есть если у вас миллион методов получения того или иного экземпляра, то какой именно экземпляр нужен вашему классу можно понять, лишь прочитав исходный код класса клиента (в данном примере нужно посмотреть исходный код класса Car )

И второй недостаток, это то, что когда наш класс использует сервис локатор, то стабильность класса становится неопределенной. Наш класс, теоретически, может использовать что угодно, поэтому изменение любого класса (или интерфейса) в нашем проекте может затронуть произвольное количество классов и модулей.

Ок. Ясно. Так что в итоге использовать?

Google рекомендует делать так, как в табличке ниже. Но, правда они не говорят, что есть еще Koin (кстати на AndroidSchool есть бесплатный туториал по работе c Koin), Toothpick, Kodein и другие инструменты для программной реализации DI.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *