Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

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

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

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

const geolocationService = new GoogleMaps();
const storeService = new StoreService(geolocationService);
const app = new App({ storeService });
app.run();

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

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

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

Локатор (Service Locator)

Самый простой способ внедрять зависимости в таких системах - сервис локатор. Это объект, который содержит внутри себя все зависимости. Любой объект, которому нужен какой-либо сервис, обращается за ним к сервис локатору.

Возьмем для примера микрофреймворк Fastify из JS. У него есть расширение, которое добавляет шаблонизатор в фреймворк. Попробуем внедрить шаблонизатор Pug через Service Locator:

import fastify from 'fastify';
import pug from 'pug';

const app = fastify();

const locators = {
  renderer: (templatePath) => pug.renderFile(templatePath),
};

app.get('/hello', (req, res) => res.send(locators.renderer('index.pug')));

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

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

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

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

Снова посмотрим на Fastify и интеграцию с Pug, но уже через встроенный контейнер. Для внедрения зависимости фреймворк имеет метод register():

import fastify from 'fastify';
import view from '@fastify/view';
import pug from 'pug';

const app = fastify();

await app.register(view, { engine: { pug } });

app.get('/hello', (req, res) => res.view('index'));

Обработчик запроса получает метод отрисовки через метод view(). Обработчик не знает ничего про контейнер и про то, как зависимость попала внутрь приложения.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 7 ноября
профессия
от 39 525 ₸ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 7 ноября
профессия
от 25 000 ₸ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 7 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу