HTML Diff
1 added 1 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>На протяжении всего курса, мы говорили про процесс инициализации, внутри которого создаются необходимые объекты. Затем эти объекты используются в прикладном коде. К таким объектам относятся: соединение с базой данных, логгер, кеш, шаблонизатор, интеграция с внешними сервисами и многое другое.</p>
1 <p>На протяжении всего курса, мы говорили про процесс инициализации, внутри которого создаются необходимые объекты. Затем эти объекты используются в прикладном коде. К таким объектам относятся: соединение с базой данных, логгер, кеш, шаблонизатор, интеграция с внешними сервисами и многое другое.</p>
2 <p>В простых ситуациях, там где объектов немного и мы сами управляем кодом (а не используем фреймворки, определяющие структуру), зависимости можно внедрять "руками":</p>
2 <p>В простых ситуациях, там где объектов немного и мы сами управляем кодом (а не используем фреймворки, определяющие структуру), зависимости можно внедрять "руками":</p>
3 <p>В коде, который активно использует инверсию зависимостей, инициализация кода выглядит как матрёшка из объектов. Объекты верхнего уровня принимают на вход объекты с нижних слоёв, шаг за шагом собирая готовое приложение.</p>
3 <p>В коде, который активно использует инверсию зависимостей, инициализация кода выглядит как матрёшка из объектов. Объекты верхнего уровня принимают на вход объекты с нижних слоёв, шаг за шагом собирая готовое приложение.</p>
4 <p>С ростом числа объектов, процесс сборки усложняется и становится утомительным. Появляются ситуации, в которых объекты нужны в самой глубине кода, но прокинуть их можно только пройдя множество уровней. В популярных фреймворках инициализация может включать в себя создание и внедрение сотен объектов. Страшно даже представить, что придётся писать этот код вручную.</p>
4 <p>С ростом числа объектов, процесс сборки усложняется и становится утомительным. Появляются ситуации, в которых объекты нужны в самой глубине кода, но прокинуть их можно только пройдя множество уровней. В популярных фреймворках инициализация может включать в себя создание и внедрение сотен объектов. Страшно даже представить, что придётся писать этот код вручную.</p>
5 <p>Для решения данной задачи, используется два подхода (шаблона проектирования). Ниже поговорим про каждый из них</p>
5 <p>Для решения данной задачи, используется два подхода (шаблона проектирования). Ниже поговорим про каждый из них</p>
6 <h2>Локатор (Service Locator)</h2>
6 <h2>Локатор (Service Locator)</h2>
7 <p>Самый простой способ внедрять зависимости в таких системах - сервис локатор. Это объект, который содержит внутри себя все зависимости. Любой объект, которому нужен какой-либо сервис, обращается за ним к сервис локатору.</p>
7 <p>Самый простой способ внедрять зависимости в таких системах - сервис локатор. Это объект, который содержит внутри себя все зависимости. Любой объект, которому нужен какой-либо сервис, обращается за ним к сервис локатору.</p>
8 <p>Возьмём для примера микрофреймворк Slim. У него есть расширение PHP-View, которое добавляет шаблонизатор в фреймворк. Попробуем внедрить это расширение через Service Locator:</p>
8 <p>Возьмём для примера микрофреймворк Slim. У него есть расширение PHP-View, которое добавляет шаблонизатор в фреймворк. Попробуем внедрить это расширение через Service Locator:</p>
9 - <p>Вот такой нехитрый подход для внедрения зависимостей. По нему написаны сотни статей со всевозможными вариаиями его создания и использования. В большинстве из них локатор рассматривается как антипаттерн. Так как прикладной код знает про его существование.</p>
9 + <p>Вот такой нехитрый подход для внедрения зависимостей. По нему написаны сотни статей со всевозможными вариациями его создания и использования. В большинстве из них локатор рассматривается как антипаттерн. Так как прикладной код знает про его существование.</p>
10 <h2>Контейнер (DI Container)</h2>
10 <h2>Контейнер (DI Container)</h2>
11 <p>Вершиной эволюции инверсии зависимостей считается DI Container. Продвинутые контейнеры, это целые фреймворки, которые занимаются инициализацией приложения, собирают необходимые объекты и прокидывают их друг в друга. В некоторых экосистемах, контейнер - центральная часть всей системы, которая занимается её оркестрацией (управлением). В Java, например, это Spring Framework. Он с лёгкостью может собирать и веб-приложение и демонов.</p>
11 <p>Вершиной эволюции инверсии зависимостей считается DI Container. Продвинутые контейнеры, это целые фреймворки, которые занимаются инициализацией приложения, собирают необходимые объекты и прокидывают их друг в друга. В некоторых экосистемах, контейнер - центральная часть всей системы, которая занимается её оркестрацией (управлением). В Java, например, это Spring Framework. Он с лёгкостью может собирать и веб-приложение и демонов.</p>
12 <p>Ключевое отличие контейнера от локатора в том, что зависимости из контейнера попадают внутрь приложения прозрачно. Прикладной код не догадывается о существовании контейнера, он лишь видит объекты, которых ждёт. Для инъекции этих зависимостей используются стандартные подходы: либо через конструктор, либо через сеттеры и аргументы методов.</p>
12 <p>Ключевое отличие контейнера от локатора в том, что зависимости из контейнера попадают внутрь приложения прозрачно. Прикладной код не догадывается о существовании контейнера, он лишь видит объекты, которых ждёт. Для инъекции этих зависимостей используются стандартные подходы: либо через конструктор, либо через сеттеры и аргументы методов.</p>
13 <p>Снова посмотрим на Slim и интеграцию с PHP-View, но уже через встроенный контейнер. Обработчик запроса получает renderer через метод get(). Он не знает ничего про контейнер и про то, как зависимость попала внутрь $this.</p>
13 <p>Снова посмотрим на Slim и интеграцию с PHP-View, но уже через встроенный контейнер. Обработчик запроса получает renderer через метод get(). Он не знает ничего про контейнер и про то, как зависимость попала внутрь $this.</p>
14 <p>Помимо отсутствия глобального объекта в виде локатора, мы получаем еще ряд преимуществ, которые начинают играть роль с ростом приложения. Так как контейнер это объект, встроенный в процесс работы фреймворка, то он может связывать свою работу с его логикой:</p>
14 <p>Помимо отсутствия глобального объекта в виде локатора, мы получаем еще ряд преимуществ, которые начинают играть роль с ростом приложения. Так как контейнер это объект, встроенный в процесс работы фреймворка, то он может связывать свою работу с его логикой:</p>
15 <ul><li>Поддерживать работу с синглтонами и пулом объектов. Можно управлять состоянием объектов, создавая их один раз и переиспользуя в течение жизни приложения или отдельного запроса.</li>
15 <ul><li>Поддерживать работу с синглтонами и пулом объектов. Можно управлять состоянием объектов, создавая их один раз и переиспользуя в течение жизни приложения или отдельного запроса.</li>
16 <li>Интегрироваться с middleware и событиями. Во многих фреймворках контейнер связывается с системой middleware или событийной моделью, упрощая внедрение зависимостей в обработчики событий и промежуточные слои.</li>
16 <li>Интегрироваться с middleware и событиями. Во многих фреймворках контейнер связывается с системой middleware или событийной моделью, упрощая внедрение зависимостей в обработчики событий и промежуточные слои.</li>
17 <li>Обеспечивать автоматическую резолвинг-зависимостей. В продвинутых контейнерах можно регистрировать классы без явного указания всех зависимостей - контейнер сам анализирует конструкторы и подставляет нужные объекты.</li>
17 <li>Обеспечивать автоматическую резолвинг-зависимостей. В продвинутых контейнерах можно регистрировать классы без явного указания всех зависимостей - контейнер сам анализирует конструкторы и подставляет нужные объекты.</li>
18 </ul><p>В PHP контейнеры имеют настолько важную роль, что их интерфейс был унифицирован через<a>PSR-11</a>.</p>
18 </ul><p>В PHP контейнеры имеют настолько важную роль, что их интерфейс был унифицирован через<a>PSR-11</a>.</p>