0: Депендеси инжекшн. На самом деле это уже 2 версия роликов. Прошлую версию я делал где-то осенью и мне кажется она получилась переусложнённой. Давайте попробуем все как-то разобрать попроще. Итак.
1: Де пенисии инжекшн.
2: Версия 2 0. Смотрите, сначала немножко я кода покажу так, на слайдах, потом посмотрим уже на живом коде, как это работает. Для чего это нужно. Давайте посмотрим, что такое прямые зависимости. Вот он.
3: У нас есть некий код, где у нас зависимости напрямую в этом коде используются, они там и где-то импортятся, и где-то истанцирует. Я в самом коде. Вот здесь мы создаём внутри user сервиса некий
4: Logger то, что называется политика высокого уровня, это user service ну, он у нас повыше уровнем стоит, а logger стоит пониже, а дальше мы создаём сам user service.
5: И что здесь говорит тот же самый дядя боб? Ну и остальные умные дяди о том, что зависимости должны быть развёрнуты, что у нас не должны идти зависимости такой цепочкой, что сначала политика на
6: Высшего уровня, и она зависит от политики низкого уровня. То есть ваша бизнес логика, она не должна зависеть от чего-то нижестоящего. Почему? Потому что ваша бизнес логика, она изменяется редко и по очень важным
7: Причинам, ну таким как изменение собственно бизнеса, потому что бизнес логика чаще всего отражает какие-то бизнес процессы, которые происходят с вашим приложением. И вот получается, что у вас, например, используется какой-то логгер, и вы его решили
8: Поменять и что происходит у вас в данный момент? Бизнес логика изменится от того, что у вас поменялся логгер. Это неправильно, и это потребует изменения и перетестирования самой важной, самой устойчивой части.
9: Вашего приложения бизнес логики, давайте проведём архитектурные границы, так называемые. Вот вот так мы отделили пользователя, здесь класс. User, он является политикой наивысшего уровня.
10: И он никаким образом не должен зависеть от логгера. Вот даже как-то вот так должна быть направлена эта стрелочка. То есть уже сам логгер должен зависеть от юзера. Как это сделать? Вот вспомним.
11: Такую буква d.
12: Может быть, кому-то приевшуюся аббревиатуру солит, что значит в ней?
13: Такую, может быть, кому-то приевшуюся аббревиатуру солит, что значит в ней буква d.
14: Буква d самая, может быть, главная, самая привычная нам буква, которую мы сейчас используем постоянно когда мы пишем на высоком, она означает депенденси, инжекшн нет, очень часто путают.
15: Уровне и не
16: Буква d самая, может быть, главная, самая привычная нам буква, которую мы сейчас используем постоянно, когда мы пишем на высоком уровне и она означает не депенденси, инжекшн нет, очень часто путают.
17: Как-то так получилось, потому что похоже да, депенденси инжекшн начинается с буквы, но на самом деле это депендеси inversion, то есть инверсия, которую вот как раз уже делают с помощью депендеси.
18: D зависимости.
19: Как-то так получилось, потому что похоже да, депенденси инжекшн начинается с буквы d, но на самом деле это депендеси inversion, то есть инверсия зависимости, которую вот как раз уже делают с помощью депендеси.
20: Это 1 из способов развернуть наши зависимости. Как нам можно их развернуть. Вот как-то так. То есть нам нужно добавить здесь interface interface. Нас изолирует интер.
21: Face находится в том же слое, что и наша бизнес логика, и теперь уже логгер реализует этот интерфейс, а внутри домен юзера он зависит уже от этого интерфейса, и наши стрелочки смотрите, они пересекают границы в нуж.
22: Сторону, то есть внутри, внутри вот этого слоя, стрелочки могут направлены быть в разные стороны, но границу они пересекают в правильную сторону. И как сделать такой простейший вариант? Диая, да, очень
23: Просто он делается с помощью конструктора, то мы объявляем конструктор, в котором пишем, что мы принимаем некий логгер, который должен реализовать интерфейс i. Логгер, дальше мы его создаём.
24: Есть.
25: Просто он делается с помощью конструктора, то есть мы объявляем конструктор, в котором пишем, что мы принимаем некий логгер, который должен реализовать интерфейс i логгер, дальше мы его создаём.
26: И инжектируем все, наш логгер, он приехал в наш user сервис. Таким образом, у нас получилась простейшая реализация, диая.
27: Итак, посмотрим это на каком-то коде другом.
28: Ну смотрите, вот у нас есть некий, скажем, класс dog, и у него есть метод барк, то есть мы говорим собаке лаять, собака может лаять в консоль сразу в этом.
29: Методе, но это не очень правильно, потому что собака здесь является высокоуровневой политикой, и она не должна знать о том, куда она будет лаять в консоль, а может быть в браузер. А может быть, в pdf, мы не знаем, поэтому мы здесь вот делаем некую
30: Методе, но это не очень правильно, потому что собака здесь является высокоуровневой политикой, и она не должна знать о том, куда она будет лаять в консоль, а может быть в браузер. А может быть, в pdf, мы не знаем, поэтому мы здесь вот делаем некую абстракцию.
31: Которая является cli аутпутом и через неё уже лайм в консоль. Ну немножечко завязались да, у нас уже сказано, что это cli, но она нас немножко немножко абстрагирует output он
32: И вот этот cli через принт.
33: Которая является cli аутпутом, и через неё уже лайм в консоль. Ну немножечко завязались. Да, у нас уже сказано, что это cli, но она нас немножко немножко абстрагирует. И вот этот cli output, он через принт
34: Message мы создаём собаку.
35: Пишет нам в консоль. И в итоге, когда она может лаять, да, ну, проверим. А, ну здесь у меня нету npm, поэтому просто нод и так.
36: Message пишет нам в консоль. И в итоге, когда мы создаём собаку, она может лаять, да, ну, проверим, а, ну здесь у меня нету npm, поэтому просто нод и так.
37: Этот файлик меня, да, но диай, вот собака. Попробуем сделать тоже самое с простейшим. Вот смотрите, мы объявили, что у нас на вход идёт некий
38: Лает диемм.
39: Этот файлик меня, да, но диай, вот собака лает. Попробуем сделать тоже самое с простейшим диемм. Вот смотрите, мы объявили, что у нас на вход идёт некий
40: И output аутпут будет у нас каким-то универсальным. Неважно. Смотрите, мы уже развязали эту зависимость, нам стало удобнее. Теперь мы некий универсальный аутпут, вызываем в нём метод print и печатаем сообщения.
41: Что?
42: И output аутпут будет у нас каким-то универсальным. Неважно. Смотрите, мы уже развязали эту зависимость. Нам стало удобнее, что теперь мы некий универсальный аутпут, вызываем в нём метод print и печатаем сообщения.
43: И наша собака тоже может лаять. Давайте попробуем версию.
44: Эту запустить.
45: И наша собака тоже может лаять. Давайте попробуем версию эту запустить.
46: Да, происходит то, что мы и хотели. Вот таким образом уже на чистом, на чистой ванили сделано то, что все работает как надо, но не так удобно. Вспомним о том, что по хорошему нам бы здесь нужны интерфейсы.
47: То есть, видите, мы можем собаке поддавать здесь аутпуты, но мы никаким гарантируем, что они реализуют этот интерфейс, что у них на входе будет метод print. Да, мы можем
48: Разные образом не здесь написать очень много.
49: То есть, видите, мы можем собаке поддавать здесь разные аутпуты, но мы никаким образом не гарантируем, что они реализуют этот интерфейс, что у них на входе будет метод print. Да, мы можем здесь написать очень много
50: Разного кода, чтобы это все было, чтобы стало красиво. Но это так неудобно. Конечно, мы в данном случае мы можем воспользоваться тайпскриптом. Давайте посмотрим, что мы можем сделать на тайпскрипте. Вот он
51: У нас есть, скажем, такой же уже поинтереснее, да, у нас появляется сервис.
52: Который создаёт собаку, передаёт ей аутпут и собака может лаять, как это выглядит, в общем то, абсолютно также. То есть здесь мы ещё не ввели никаких дополнительных
53: Интерфейсов, потому что смотрите, у нас здесь вот на вход подаётся именно конкретная реализация, которую мы вот отсюда импортим. Это, кстати, 1 из претензий к некоторым фреймворкам, которые очень любят делать вот такие
54: Прямые импорты и мы завязываемся на конкретную реализацию. Да, давайте проверим, конечно, что она работает и посмотрим дальше.
55: Посмотрим дальше, что мы с этим можем сделать.
56: Да у нас здесь все уже через type script собака может лаять все прекрасно но как-то не интересно что у нас вот есть такая прямая связь дальше мы можем воспользоваться уже
57: Интерфейсами. Давайте возьмём версию с инверсией. Да, вот она называется инверс. И здесь у нас что получается? Вот у нас есть, которая на вход уже принимает некий аут.
58: Собака.
59: Интерфейсами. Давайте возьмём версию с инверсией. Да, вот она называется инверс. И здесь у нас что получается? Вот у нас есть собака, которая на вход уже принимает некий аут.
60: Put, который соответствует интерфейсу. То есть у нас появляются интерфейсы. Вот у нас есть l output, он приходит на вход.
61: И таким образом мы можем здесь вот уже подменить. То есть здесь мы реализовали, да, вот у нас есть реализация, которая соответствует этому интерфейсу. Реализовали, мы засунули её в собаку.
62: Мы её.
63: И таким образом мы можем здесь вот уже подменить. То есть здесь мы реализовали, да, вот у нас есть реализация, которая соответствует этому интерфейсу, мы её реализовали, мы засунули её в собаку.
64: Собака может лаять тоже самое.
65: Да.
66: Собака может лаять, да, тоже самое.
67: Сделаем так, инверс.
68: Ну, просто вы чтоб видели, что все работает, да, вот оно хорошо. Давайте вернёмся. Смотрите, что у нас получается таким образом мы все время должны сами вручную.
69: Работает.
70: Ну, просто вы чтоб видели, что все работает, да, вот оно работает. Хорошо. Давайте вернёмся. Смотрите, что у нас получается таким образом, мы все время должны сами вручную.
71: Очень много создавать всего мы должны как-то по цепочке очень глубоко через конструкторы прокидывать наши зависимости. У нас диа есть, но не самый удобный в мире у нас получается очень много болерплейт. Итак,
72: Работать не всегда удобно. Да, конечно, если у вас не очень сложное приложение, этого достаточно, но чаще всего приложения становятся достаточно сложными.
73: И, конечно, мы можем наделать там всяких Хитрых фабрик для того, чтобы это все делалось само, но не переусложнил ли мы тогда все, и нам придётся писать очень много хитрого кода, который мы писать не хотим, потому что есть
74: Готовые решения, готовые решения для java script, они построены на декораторах чаще всего и это решение ну не только в java скрипте, оно называется контейнером и Okko, контейнером или Инвер.
75: В контрол контейнером. Что это значит? Вот у нас есть примерчик примерно все тоже самое, что у нас было, но появляется некий инжектил. И здесь самая магия, что здесь уже вручную
76: Ничего не что происходит. У нас есть некий аутентификейт сервис, который стучится в некий контейнер, задаёт ему тип, который в данном классом user.
77: Создаётся случае является
78: Ничего не создаётся. Что происходит? У нас есть некий аутентификейт, сервис, который стучится в некий контейнер, задаёт ему тип, который в данном случае является классом. User.
79: И?
80: Получает инстанс и уже с этим инстансом работает. Как мы можем все это сделать? Да, как это вообще выглядит?
81: И получает инстанс, и уже с этим инстансом работает. Как мы можем все это сделать? Да, как это вообще выглядит?
82: Ну, у нас в системе появляется вот некоторая такая вот, скажем, коробочка, которая может быть реализована по разному, этот контейнер, он есть с помощью, ну, его можно создать, точнее, с помощью разных реше.
83: Есть разные библиотеки, которые реализуют такую инверсию, это есть инверсии Фай. Такой контейнер есть в ангуляре, в несте, в общем, в любом современном фреймворке что-то такое будет, и мы можем ей пользоваться и на таком ви,
84: Верхнем верхнем уровне абстракции. Это выглядит как, что у нас есть контейнер, в который мы положить что-то созданные наши какие-то экземпляры классов, даже не экземпляры, а инструкции о том, как их создавать. А потом, когда мы
85: Можем.
86: Верхнем верхнем уровне абстракции. Это выглядит как, что у нас есть контейнер, в который мы можем положить что-то созданные наши какие-то экземпляры классов, даже не экземпляры, а инструкции о том, как их создавать. А потом, когда мы
87: Стучимся в контейнер, мы получим уже конкретный экземпляр. Более того, мы можем получить как тот же самый экземпляр, так и новый. Ну то есть мы можем написать инструкции о том, как это все создаётся. Фабрики
88: Уже будут лежать внутри. Опять же, давайте посмотрим, как это сделать с помощью инверсии Фая. Вот у нас есть все та же наша собачка, которая должна лаять, но код стал поинтереснее.
89: У нас вот корневой файл, и он очень сильно упростился. Здесь появился некий контейнер, из которого мы получаем экземпляр собаки, соответствующий
90: И вот это интересно, да, что это мы здесь передаём за типы. Давайте посмотрим, а это просто символ. То есть здесь мы стучимся в наш контейнер, стучимся в контейнер и говорим, отдай то, что у тебя
91: Лежит вот здесь по этому типу. А что там лежит? Давайте посмотрим. У нас есть некий конфигурационный файл для этого контейнера. Вот мы здесь создаём. Мы говорим, у нас есть некий ci.
92: Что?
93: Лежит вот здесь по этому типу. А что там лежит? Давайте посмотрим. У нас есть некий конфигурационный файл для этого контейнера. Вот мы здесь создаём, мы говорим, что у нас есть некий ci.
94: Который мы складываем под этой меткой. Дог, который мы складываем под этой меткой. Интересно, что там внутри все ещё проще. Мы заходим
95: Вот и ну.
96: Который мы складываем вот под этой меткой. И дог, который мы складываем под этой меткой. Интересно, что там внутри? Ну все ещё проще. Мы заходим
97: Внутрь собаки, что мы видим? Эта сущность является инжектируемой. То есть она умеет работать с контейнером. Дальше мы говорим
98: Видим.
99: Внутрь собаки, что мы видим? Эта сущность является инжектируемой. То есть она умеет работать с контейнером. Дальше мы говорим
100: Возьми из контейнера, инжектируй в нас то, что лежит вот по этой метке, по l output, вот по этому интерфейсу и соответствует этому интерфейсу, ну и положи это приватное.
101: Поле аутпут хорошо, а как выглядит наш села, да ещё проще мы просто говорим, что он инжектируемый и все. Ну а дальше мы вот собираем вот эти вот связки, то есть мы i.
102: Аутпут.
103: Поле аутпут хорошо, а как выглядит наш села аутпут, да ещё проще. Мы просто говорим, что он инжектируемый и все. Ну а дальше мы вот собираем вот эти вот связки, то есть мы i
104: Output, точнее пометки ай аутпут положили cli output, реализующий интерфейс i аутпут а пометки дог мы положили дог, который реализует.
105: Класс, док, ну здесь тоже можно сделать с интерфейсом, но кажется вот здесь как раз интерфейс не нужен, потому что это entity, она будет 1 в нашей системе разных способов вывода может быть много. Давайте.
106: Он а вот.
107: Класс, док, ну здесь тоже можно сделать с интерфейсом, но кажется вот здесь как раз интерфейс не нужен, потому что это entity он, она будет 1 в нашей системе, а вот разных способов вывода может быть много. Давайте.
108: Тоже проверим, что это все работает.
109: И, конечно же, весь этот код, он будет доступен на гитхабе. Ссылка под видео и можно посмотреть, как это все устроено. Вот смотрите, все работает, но
110: Насколько все стало проще, мы просто из контейнера получаем экземпляр нашего класса. Экземпляр нашего класса из контейнера получает себе средства для того,
111: Чтобы выводить себя и все, оно настраивается вот в этом месте, где мы складываем все эти связки. То есть здесь мы в наш контейнер загружаем инструкцию о том, как он должен действовать. А вот здесь у нас получается то
112: То, что называется, давайте у меня даже есть под это слайд специальный, то, что называется композишн рут. То есть корень нашей композиции, где мы все настраиваем. Вот дальше мы уже напрямую в контейнер лазить не должны. Смотрите, у нас
113: Здесь в единственном месте вызывается наш контейнер. В остальных файлах мы уже
114: Используем вот эти декораторы инжектил и инжект.
115: Если вы будете в разных местах лазить в контейнер, конечно это можно написали, что вы используете контейнер, постучались по метке и получили вот это уже будет паттерн service locator, который является не очень хорошим.
116: Потому что у вас по системе размазывается это знание, где, когда вы стучитесь в контейнер, а здесь у вас есть такое вот дерево. Конечно же, в контейнер можно положить все, что нужно, и переиспользовать, и константы, и не только
117: Классы и классы поменять по хитрому даже тесты можно писать вот на том, что у вас классы в контейнере подменяются. Вы берете вместо реализации, вы берете какой-то, кладёте в контейнер и используете вот
118: Мог.
119: Классы и классы поменять по хитрому даже тесты можно писать вот на том, что у вас классы в контейнере подменяются. Вы берете вместо реализации, вы берете какой-то мог, кладёте в контейнер и используете вот
120: Здесь я показал код на инверсии Фай, но если вы посмотрите в код на несте, вы увидите тоже самое, те же самые инжекта. И инжект, конечно, нест. Он немножко от вас скрывает, как у вас должно все быть сделано.
121: Правильно, потому что нас предполагает, что вы будете просто импортить сущности и завязываться на классы. А вот как вам предлагает инверсии Фай по умолчанию. Вот если мы ещё раз посмотрим, вы можете завяза.
122: На интерфейсы, и это будет намного чище, конечно, в несте можно писать также просто об этом в инструкции не сказано на 1 странице, а так было бы намного интереснее и, в общем то, больше.
123: Ничего сложного. Депенденси инжекшн нет, вы просто внедряете свои зависимости. Вы используете контейнер, куда вы их складываете, и достаёте из этого контейнера. Если вам все ещё непонятно, как работает ваш фреймворк, я вам
124: Предлагаю поставить инверсии ай и попробовать работать напрямую. Ну то есть у вас не будет уже фреймворка, у вас будет только иок контейнер, в который вы будете вручную складывать настроенные фабрики.
125: Для ваших сущностей и забирать их. Я надеюсь, что все у вас получится.
126: И?
127: Для ваших сущностей и забирать их. И я надеюсь, что все у вас получится.