2020-12-07 09:00:30
DI vs DI vs IoC
Знаете, почему сложно внедрять всякие принципы и лучшие практики? Они рождаются из конкретных ситуаций и решают конкретные проблемы. Чтобы передать эти ценнейшие знания, ситуацию приходится абстрагировать и в итоге получается набор терминов. Что с ними делать - непонятно, слишком абстрактно.
Сегодня разберём разницу между
Dependency injection, Dependency invertion и
Inversion of Control. Понимание пригодится на собеседованиях, при чтении статей по дизайну и архитектуре. Плюс поймёте, как хорошо вы программируете и какие проблемы решаете, даже не задумываясь.
Будем разбираться на простом примере.
Точка А: Сервис
Service записывает логи в файл с помощью класса
FileLogger:
class FileLogger {…}
class Service {
FileLogger logger=new FileLogger();
}
Сделаем код чуть лучше:
Dependency injection
это когда компоненты создаются не внутри класса, а передаются в конструкторах или сеттерах. Перенесём инициализацию логгера в конструктор:
class Service {
FileLogger logger;
Service (FileLogger logger) {
this.logger= logger;
}
}
Класс не занимается инициализацией логгера
Dependency invertion
Буква D в аббревиатуре SOLID, формулировка состоит из двух частей:
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции.
Суть: пусть сервис работает не с конкретным логгером, а с интерфейсом
interface Logger {…}
class FileLogger implements Logger {…}
class Service {
Logger logger=new FileLogger();
}
В интерфейсе доступно меньше методов, поэтому его проще использовать
Реализацию легко заменить
Оба класса проще тестировать
Почему используется слово "абстракция"? Группу методов можно выделить в интерфейс, в абстрактный класс и даже в обычный класс. Но интерфейс самый подходящий вариант.
IoC - Inversion of Control
В маленьких программах жизнь начинается в методе
main(). Программист создаёт объекты, вызывает методы, все шаги явно прописаны.
Inversion of Control - это когда ход выполнения программы задаёт фреймворк. Spring смотрит на классы и аннотации, а затем создаёт объекты, связывает их вместе и не даёт программе завершиться.
@Component class FileLogger {…}
@Component class Service {
@Autowired
FileLogger logger;
}
Меньше скучного кода
Низкая связность - код легко менять, тестировать и переиспользовать
Spring создаёт обёртки классов и работает через Dependency Injection. Можно и по-другому: через паттерн фабричный метод, стратегия или сервис локатор.
Историческая справка.
Сервис локатор иногда встречается в легаси проектах. Это когда компоненты создаются в классе
ServiceLocator, а другие классы получают к ним доступ через статические методы.
class ServiceLocator {
private static Logger logger=…
public static Logger getLogger() {
return logger;
}
}
public class Service {
private Logger logger = ServiceLocator.getLogger();
}
Резюме:
Dependency injection - класс не создаёт компоненты напрямую, они передаются через конструктор или сеттер
Dependency invertion - класс работает с другими компонентами через интерфейс
Inversion of Control - ход программы задаёт фреймворк. Соединять компоненты может Dependency injection, фабричный метод, стратегия или сервис локатор.
Ответ на вопрос перед постом:
Это словоблудие относится к Dependency injection
#теория
4.3K viewsedited 06:00