Download - Основы Di контейнеров
![Page 1: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/1.jpg)
Предпосылки появления DI-контейнеров
Уральская группа пользователей .NET, март 2010
Павел Егоров, СКБ Контур [email protected]
http://xoposhiy.livejournal.com
![Page 2: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/2.jpg)
S
O
L
I
D
RP — Single Responsibility Principle
CP — Open Closed Principle
SP — Liskov Substitution Principle
SP — Interface Segregation Principle
IP — Dependency Inversion Principle
![Page 3: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/3.jpg)
— Хотим спроектировать хорошо!
— Быть готовым к грядущим изменениям!
![Page 4: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/4.jpg)
SOLID
RP — Single Responsibility Principle
Модуль =
= одна обязанность =
= одна причина изменения
пихать все в один класс — НЕТ! :-\
плодить много мелких классов — ДА :-)
![Page 5: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/5.jpg)
Iso8859Decoder
InvoiceConverter
Utf8Decoder
SRP всех вылечит! :-)
![Page 6: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/6.jpg)
Iso8859Decoder
Invoice
Converter
Utf8Decoder
void Convert(){ var decoder = new Iso8859Decoder(); … decoder.Decode(…); …}
![Page 7: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/7.jpg)
SOLIDIP — Dependency Inversion Principle
Классы должны зависеть от интерфейсов, а не от других классов.
InvoiceConverte
r
IDecoder
Iso8859Decoder Utf8Decoder…
![Page 8: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/8.jpg)
public InvoiceConverter(IDecoder decoder)
{ this.decoder = decoder;}
…
public void Convert(){ … decoder.Decode(…); …}
SRP + DIP всех вылечат! :-)
new InvoiceConverter(new Iso8859Decoder());
или
new InvoiceConverter(new Utf8Decoder());
InvoiceConverte
r
IDecoder
Iso8859Decoder Utf8Decoder
![Page 9: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/9.jpg)
реализация интерфейса использование
SRP
DIP
![Page 10: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/10.jpg)
Miško Heverymisko.hevery.com
— Давайте жестко разделять:
код, содержащий логику программы
код, вызывающий конструкторы
new A(new B(…), new C(…))…new SmtpClient(smtpUrl);…new ConsoleLogger()…
![Page 11: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/11.jpg)
IService
Locator
![Page 12: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/12.jpg)
ServiceLocator
![Page 13: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/13.jpg)
зависимости стали неявными…
хрупкость!
ServiceLocator
![Page 14: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/14.jpg)
ServiceLocator
![Page 15: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/15.jpg)
ServiceLocator
все зависят от ServiceLocator’а
жесткость!
![Page 16: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/16.jpg)
Miško Heverymisko.hevery.com
![Page 17: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/17.jpg)
Электронный бухгалтер
более 100 сервисов Rule of thumb:1 сервис на каждые 5-7 килобайт кодаДействительно МНОГО
серого тупого рутинного кода
![Page 18: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/18.jpg)
время жизни
Автоматический поиск всех типов
с каждой новой «фичей» будет все хуже…Ленивая инициализация, коллекции, один объект на несколько интерфейсов, xml-конфигурирование, IDisposable, дочерние контейнеры, …
![Page 19: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/19.jpg)
← ServiceLocator
![Page 20: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/20.jpg)
ServiceLocator
![Page 21: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/21.jpg)
Conventions over configuration(via RoboContainer)
Электронный бухгалтер
<castle> <components> <component id="JsonSerializer" service="SKBKontur.IB.Serialization.IDataSerializer, IB.Serialization" type="SKBKontur.IB.Serialization.JsonSerializer, IB.Serialization"> </component> <component id="BankReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.DataContracts.BankInfo, IB.DataContracts]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Bank.BankReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="BankReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.DataContracts.BankInfo, IB.DataContracts], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Bank.BankReferenceImplementation, IB.ReferenceService" > </component> <component id="BankReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.DataContracts.BankInfo, IB.DataContracts], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.DataContracts.BankInfo, IB.DataContracts], [System.String]], IB.ReferenceService" > </component> <component id="BankReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Bank.BankReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component>
<component id="LocationReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.DataContracts.Address.LocationInfo, IB.DataContracts]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Location.LocationReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="LocationReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.DataContracts.Address.LocationInfo, IB.DataContracts], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Location.LocationReferenceImplementation, IB.ReferenceService" > </component> <component id="LocationReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.DataContracts.Address.LocationInfo, IB.DataContracts], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.DataContracts.Address.LocationInfo, IB.DataContracts, Version=1.0.0.0, Culture=neutral], [System.String]], IB.ReferenceService" > </component> <component id="LocationReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Location.LocationReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component>
<component id="StreetReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.ReferenceService.KLADR.Street.StreetInfo, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="StreetReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.ReferenceService.KLADR.Street.StreetInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceImplementation, IB.ReferenceService" > </component> <component id="StreetReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.ReferenceService.KLADR.Street.StreetInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.ReferenceService.KLADR.Street.StreetInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceSearchParams, IB.ReferenceService, Version=1.0.0.0, Culture=neutral]], IB.ReferenceService" > </component> <component id="StreetReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.Street.StreetReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component>
<component id="HouseReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.ReferenceService.KLADR.House.HouseInfo, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="HouseReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.ReferenceService.KLADR.House.HouseInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceImplementation, IB.ReferenceService" > </component> <component id="HouseReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.ReferenceService.KLADR.House.HouseInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.ReferenceService.KLADR.House.HouseInfo, IB.ReferenceService], [SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceSearchParams, IB.ReferenceService, Version=1.0.0.0, Culture=neutral]], IB.ReferenceService" > </component> <component id="HouseReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.KLADR.House.HouseReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component>
<component id="IFNSReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.DataContracts.IFNSInfo, IB.DataContracts]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="IFNSReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.DataContracts.IFNSInfo, IB.DataContracts], [SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceImplementation, IB.ReferenceService" > </component> <component id="IFNSReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.DataContracts.IFNSInfo, IB.DataContracts], [SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.DataContracts.IFNSInfo, IB.DataContracts], [SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceSearchParams, IB.ReferenceService]], IB.ReferenceService" > </component> <component id="IFNSReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.IFNS.IFNSReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component>
<component id="RegionReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.ReferenceService.Region.RegionInfo, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Region.RegionReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral" > </component> <component id="RegionReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.ReferenceService.Region.RegionInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Region.RegionReferenceImplementation, IB.ReferenceService" > </component> <component id="RegionReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.ReferenceService.Region.RegionInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.ReferenceService.Region.RegionInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" > </component>
<component id="VKTMOReferenceSource" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceSource`1[[SKBKontur.IB.ReferenceService.VKTMO.VKTMOInfo, IB.ReferenceService]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.VKTMO.VKTMOReferenceSource, IB.ReferenceService, Version=1.0.0.0, Culture=neutral"> </component> <component id="VKTMOReferenceImplementation" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceImplementation`2[[SKBKontur.IB.ReferenceService.VKTMO.VKTMOInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.VKTMO.VKTMOReferenceImplementation, IB.ReferenceService" > </component> <component id="VKTMOReference" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReference`2[[SKBKontur.IB.ReferenceService.VKTMO.VKTMOInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" type="SKBKontur.IB.ReferenceService.Reference`2[[SKBKontur.IB.ReferenceService.VKTMO.VKTMOInfo, IB.ReferenceService], [System.String]], IB.ReferenceService" > </component> <component id="VKTMOReferenceWriter" lifestyle="singleton" service="SKBKontur.IB.ReferenceService.IReferenceServiceWriter, IB.ReferenceService" type="SKBKontur.IB.ReferenceService.VKTMO.VKTMOReferenceServiceWriter, IB.ReferenceService" > <parameters> <dataSerializer>${JsonSerializer}</dataSerializer> </parameters> </component> </components> </castle>
Windsor containerxml-конфигурирование
модуль AJAX подсказок
160 строк,11 Кб
3 строки конфигурирования2 из которых «не по делу» и сигнализируют о «мертвом», неиспользуемом коде.
DisclaimerИспользуя Windsor containerтоже можно практиковать подходConvention over Configuration! Наверное…
![Page 22: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/22.jpg)
Подытожим• Наш проект ждут изменения.• SRP+DIP дают нам защиту от изменений, но…• …принуждают к тому, чтобы писать много мелких
классов.• Из мелких классов где-то нужно собирать граф
объектов.• Контейнеры всего лишь упрощают эту сборку.• А с convention over configuration упрощают
радикально!
Вопросы
![Page 23: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/23.jpg)
Но будет много противных аргументов конструктора!
обычно бывает так:
а вовсе не так:
секретный слайд
— Аргументов будет мало,это я вам гарантирую! ;-)
![Page 24: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/24.jpg)
Может быть конфигурировать в конструкторе?
секретный слайд
задавать через GUI
не загружать дважды
![Page 25: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/25.jpg)
Conventions — это путь к хрупкости
Conventions Configuration
Неявность :-( :-)
Рутина :-))) :-(((
Ошибки
секретный слайд
![Page 26: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/26.jpg)
Robert C. Martinobjectmentor.com
http://objectmentor.com/resources/articles/Principles_and_Patterns.pdfDesign Principles and Design Patterns
![Page 27: Основы Di контейнеров](https://reader034.vdocuments.pub/reader034/viewer/2022051400/554f47eab4c905b9508b466c/html5/thumbnails/27.jpg)
Дизайн плох, если…
…надо много переделывать
…трогать код опасно!
…проще сделать «в обход»
…использовать готовое решение не получается
жесткость
хрупкость
нетехнологичность
немобильность
[когда приходит новая задача]
rigidity viscosity
fragility immobility