Является ли интерфейс единственным способом абстракции в паттерне инверсии зависимости?
Что проверяют
Отличаете ли вы принцип от механизма. За вопросом стоит проверка: понимаете ли вы, что инверсия зависимостей говорит про направление связей, а интерфейс это лишь один из способов задать абстракцию, причём во фронтенде далеко не главный.
Как отвечать
Нет, не единственный. Принцип инверсии зависимостей из SOLID требует, чтобы модуль с бизнес-логикой не зависел от конкретной реализации, а и он, и реализация зависели от абстракции. Форма абстракции не оговорена.
Во фронтенде доступны как минимум:
- функция параметром: компонент принимает
onSaveпропсом и ничего не знает про транспорт; - структурная типизация TypeScript: подойдёт любой объект нужной формы,
interfaceиtypeтут равноправны; - абстрактный класс с шаблонным методом;
- модуль-адаптер за фасадом, когда подменить нужно не класс, а весь слой доступа к данным;
- контекст или контейнер, отдающий реализацию по токену.
Важнее формы другое: абстракция принадлежит высокоуровневому модулю. Контракт описывает потребность бизнес-логики, а не возможности готовой библиотеки. Если интерфейс списан с методов конкретного HTTP-клиента, зависимость никуда не делась, её просто переименовали.
И про термины: инверсия зависимостей это принцип, внедрение зависимостей это техника, IoC-контейнер это инструмент. Их постоянно называют одним словом.
Где спотыкаются
Называют принцип паттерном и путают с внедрением зависимостей. Передать зависимость в конструктор можно и напрямую конкретным классом, инверсии от этого не появится.
Помнят, что в TypeScript интерфейсы стираются при компиляции, и делают вывод, что в браузере абстракция не работает. Она работает на этапе типизации и в структуре кода, а в рантайме её роль выполняет обычный контракт объекта или функции.
Заводят интерфейс на каждый класс из принципа. Абстракция оправдана там, где реализаций больше одной или где нужна подмена в тестах, в остальных случаях это лишний файл и ложное ощущение гибкости.