Основы инверсии управления
Поймите, зачем и когда инвертировать зависимости
«Основы инверсии управления» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Жёстко заданные зависимости
Когда класс создаёт собственные зависимости с помощью new, он оказывается тесно связан с конкретными типами. Такой класс трудно перенастроить и тестировать.
Пример с тесной связанностью
В этом примере сервис создаёт собственного logger. Невозможно подставить другой logger, не изменив класс.
class ConsoleLogger { log(m: string) { console.log(m); } }
class OrderService {
private logger = new ConsoleLogger(); // hard-coded
place() { this.logger.log("order placed"); }
}
new OrderService().place();Что такое инверсия управления?
Инверсия управления (IoC) переносит ответственность за выбор зависимостей. Вместо того чтобы класс создавал их сам, их предоставляет внешний компонент. Класс объявляет, что ему нужно, и получает это.
Внедрение зависимостей
Внедрение зависимостей (DI) — распространённый способ реализовать IoC: зависимости передаются извне, а не создаются внутри. Вызывающая сторона управляет выбором реализации.
Версия с внедрением
Теперь logger передаётся извне. Сервис больше не знает и не интересуется, какой конкретно logger он получил.
class OrderService {
constructor(private logger: { log(m: string): void }) {}
place() { this.logger.log("order placed"); }
}
new OrderService(new ConsoleLogger()).place();Почему IoC повышает тестируемость
Поскольку зависимости поступают извне, в тесты можно передавать подставные реализации или шпионов. Вы можете проверять поведение без реального ввода-вывода, баз данных или сетевых calls.
const calls: string[] = [];
const fakeLogger = { log: (m: string) => calls.push(m) };
new OrderService(fakeLogger).place();
console.log(calls); // ["order placed"]Зависите от абстракций
IoC работает лучше всего, когда классы зависят от интерфейса, а не от конкретного класса. Можно внедрить любую реализацию, соответствующую интерфейсу.
interface Logger { log(m: string): void; }
class OrderService {
constructor(private logger: Logger) {}
}Внедрение через конструктор
Внедрение через конструктор передаёт зависимости в качестве параметров конструктора. Они доступны сразу и могут быть объявлены как readonly, что делает их явными и обязательными.
class OrderService {
constructor(private readonly logger: Logger) {}
}Внедрение через свойство
Внедрение через свойство задаёт зависимость в открытом свойстве или свойстве с возможностью присваивания после создания объекта. Это гибче, но позволяет объекту временно существовать без зависимости.
class OrderService {
logger!: Logger; // set after construction
place() { this.logger.log("placed"); }
}
const s = new OrderService();
s.logger = new ConsoleLogger();Выбор стиля
Предпочитайте внедрение через конструктор для обязательных зависимостей, поскольку объект никогда не находится в наполовину созданном состоянии. Используйте внедрение через свойство для необязательных зависимостей или разрыва циклов создания.
Предварительный обзор IoC container
В больших приложениях ручное связывание зависимостей становится утомительным. IoC container автоматизирует создание и передачу зависимостей; в следующих уроках это будет рассмотрено на примере InversifyJS.
Краткая проверка
Краткая проверка по этому уроку.
Итоги
Инверсия управления переносит создание зависимостей за пределы класса, а внедрение зависимостей передаёт их внутрь. Зависите от интерфейсов, предпочитайте внедрение через конструктор для обязательных зависимостей и упрощайте тестирование с помощью подставных реализаций.
Часто задаваемые вопросы
Урок «Основы инверсии управления» бесплатный?
Да — полный текст урока «Основы инверсии управления» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Основы инверсии управления»?
Поймите, зачем и когда инвертировать зависимости Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Основы инверсии управления»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы инверсии управления
- Внедрение через конструктор
- DI-контейнеры с InversifyJS
- Типобезопасные токены служб