Управление зависимостями в программном коде
TRANSCRIPT
![Page 1: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/1.jpg)
Управление зависимостямив программном коде
(dependency injection &
Inversion of Control includes)
![Page 2: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/2.jpg)
Agenda
• Качество архитектуры приложения• Что такое зависимый код?• Что такое инъекция зависимости?• Инверсия зависимости• IoC-контейнеры
![Page 3: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/3.jpg)
Это вам знакомо?
• Изменения в одном месте приводят к поломкам в другом
• Методы и классы сложно повторно использовать
• Изменения идут «со скрипом». Трудно что-либо добавить или изменить.
• «Без пол литра не разобраться» или «покажите мне умника, который так пишет?»
![Page 4: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/4.jpg)
Признаки плохой архитектуры
• Хрупкость (изменения ведут к поломкам)• Монолитность (сопротивление к
повторному использованию)• Жесткость (сопротивление к изменениям)• Чрезмерная сложность (ничего непонятно)• Вязкость («грязные» приемы работают
лучше: Copy-Paste, «Объект Бога», «Спагетти код» и т.д.)
![Page 5: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/5.jpg)
Одна из причинСильное связывание кода (Tight Coupling)
![Page 6: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/6.jpg)
Что такое зависимый код?
• public class User {
private MessageService transport = new SmtpMessageService();
public void sendMessage() {
transport.send();}
}
![Page 7: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/7.jpg)
Зависимость!
• public class User {
private MessageService transport = new SmtpMessageService();
public void sendMessage() {
transport.send();}
}
![Page 8: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/8.jpg)
Проблемы с классом User
• Мы не можем изменить реализацию MessageService
• Мы не можем протестировать класс User отдельно от класса SmtpMessageService
• Необходимо создавать новый класс или наследовать от класса User, чтобы добавить новую реализацию.
![Page 9: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/9.jpg)
Как избавиться от зависимости?
• Передать объект через set-метод:public void setMessageService(MessagService messageService) {
this.messageService = messageService;
}
• Передать объект через конструктор:public User(MessageService transport) {
this.transport = transport;
}
![Page 10: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/10.jpg)
Решение найденоИнъекция зависимости
![Page 11: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/11.jpg)
Инъекция!
• Передать объект через set-метод:public void setMessageService(MessagService transport) {
this.transport = transport;
}
• Передать объект через конструктор:public User(MessageService transport) {
this.transport = transport;
}
![Page 12: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/12.jpg)
Программирование основано на интерфейсах
• public interface MessageService {
public void send(String message);
}• public class SmtpMessageService implements MessageService {
public void send(String message) {
System.out.println(“Via smtp: ” + message);
}
}• public class JabberMessageService implements MessageService {
public void send(String message) {
System.out.println(“Via jabber: ” + message);
}
}
![Page 13: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/13.jpg)
Пример использования
• User userWithSmtp = new User();
userWithSmtp.setMessageService(new SmtpMessageService()) ;
userWithSmtp.send(“you can do it”); // print “Via smtp: you can do it”
• User userWithJabber= new User();
userWithJabber.setMessageService(new SmtpMessageService()) ;
userWithJabber.send(“ yes, you can”); // print “Via jabber: yes, you can”
![Page 14: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/14.jpg)
Что это нам дает?
• Менее связанный код (low coupling)• Небольшие, сильно зацепленные классы
(high cohesion)• Возможность повторного использования
(reuse)• Расширяемость
![Page 15: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/15.jpg)
Ответственность перешла другому классуИнверсия зависимости
![Page 16: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/16.jpg)
Кто-то должен это делать
• User userWithSmtp = new User();
userWithSmtp.setMessageService(new SmtpMessageService()) ;
userWithSmtp.send(“you can do it”); // print “Via smtp: you can do it”
• User userWithJabber= new User();
userWithJabber.setMessageService(new SmtpMessageService()) ;
userWithJabber.send(“ yes, you can”); // print “Via jabber: yes, you can”
Ответственность переходит классам верхнего уровня в соответствии принципом инверсии зависимости.
![Page 17: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/17.jpg)
Принцип инверсии
• Зависимости внутри системы стоятся на основе абстракций (интерфейсы или абстрактные классы).
• Модули верхнего уровня не зависят от модулей нижнего уровня.
• Абстракции не зависят от подробностей.
![Page 18: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/18.jpg)
IoC контейнеры
• IoC (Inversion of Control) контейнер – это специальный объект-сборщик, который на основании схемы зависимостей между классами и абстракциями может создать граф объектов. Любой IoC контейнер реализует принцип инверсии зависимостей
• IoC контейнеры появились в Java– Spring– Pico container
• IoC контейнеры используются на самых верхних уровнях приложений для инициализации объектов с учетом всех зависимостей
![Page 19: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/19.jpg)
Java: Spring Framework
• Позиционируется как complete dependency injection tool
• Позволяет описывать зависимости в коде или через XML-файл
![Page 20: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/20.jpg)
Пример для Spring Framework
• XML файл описания (dependency.xml)<beans> <bean id=“messageService" class="com.my_app.StmpMessageService"/> <bean id="client" class="com.my_app.User"> <property name=“transport"> <ref bean="messageService"/> </property> </bean></beans>
• Получение объектов с учетом зависимостейBeanFactory factory = new XmlBeanFactory(new
FileInputStream("dependency.xml"));User user= (User)factory.getBean(“user");user.send();
![Page 21: Управление зависимостями в программном коде](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5594cede1a28ab321d8b4625/html5/thumbnails/21.jpg)
Хорошая архитектура
• Простота – чем меньше архитектурных решений, тем проще
• Очевидность использования – минимум движений, чтобы получить результат
• Расширяемость – когда есть требования, система легко вбирает в себя функционал
• Устойчивость – разделение ролей позволяет быстро локализировать ошибки
• Повторное использование – низкая зависимость определяет возможности по использованию