SlideShare a Scribd company logo
1 of 38
Андрей Кулешов
Деловые решения
Про что мы говорим?
 В первую очередь – про подход к взаимодействую
  между классами и объектами в мире объектно-
  ориентированного программирования
 Во вторую очередь – про существующие шаблоны
  реализации этого подхода
 И только в третью очередь – про сторонние
  компоненты - IoC-контейнеры
Спагетти-код и лазанья-код
 Спагетти-код – это код, представляющий собой одну
  большую хаотичную мешанину классов, отвечающих за
  все функции вашего приложения
 Лазанья-код - это код, представляющий собой
  несколько отдельных маленьких хаотичных мешанин
  классов – слоёв, взаимодействующих друг с другом по
  строго определенным контрактом, не зависящим от
  реализации.
 Классическая модель – всем известная уровень
  данных, уровень бизнес-логики, уровень
  пользовательского интерфейса. Но их может быть
  больше.
Формирование слоёв
 Слой – группа классов, имеющих схожее
  назначение
 Взаимодействие между слоями идёт через «швы»
 Взаимодействие через швы должны идти только
  через контракты (интерфейсы или абстрактные
  классы), а не конкретные реализации
 И этим вы сможете добиться, что маленький
  локальный хаос внутри конкретного слоя
  останется таковым, а не разрастется на всё
  приложение
Что такое «зависимость» («dependency»)

 Что-то сильно внешнее по отношению к нашему классу,
 медленное, тяжелое в настройке, а также просто ещё не
 готовое.. В первую очередь это:
 - файловая система;
 - база данных
 - сеть;
 - сервис, который коллега послезавтра обязательно
 допишет;
 - система старта ракетных двигателей.

 Ваш класс должен зависеть от абстракций, а не от
 конкретных реализаций
Классическая работа с
зависимостями:
 Когда вы напрямую создаёте экземпляр объекта в
 вашем классе - вы контролируете его
 IDbConnection connection =
     new SqlServerConnection(“source=localhost”);
 Контролируете, когда он создается, какие параметры
  принимает, когда он больше не нужен и его надо
  удалять
 Контролируете, что создается именно этот тип объекта,
  а не схожий по функиональности
 То есть всерьез декларируете, что класс, который
  считает сумму заказов в вашей корзине покупок,
  должен знать о балансированной ферме Sql Server, и
  том, какой таймаут допустим при работе с ней
Демо
Классический контроль
Inversion of Control
Инвертированный контроль:
 При использование IoC – ваш класс больше не
 имеет контроля над зависимостями
 public class Basket{
     public Basket(IDbConnection connection){
           //save connection...
     }
 }
 Об этом заботится кто-то снаружи этого класса
 Кто-то, кто знает больше и лучше. Кто на этом
  специализируется
 А ваш класс перестаёт зависеть от конкретной
  реализации
Что злобные враги
рассказывают вам об DI
 DI – это «локатор сервисов»
  нагло врут
 DI нужен только для тестирования
  нагло врут
 DI нужен только для позднего связывания
  нагло врут
 Для архитектуры в стиле DI нужен IoC контейнер
  нагло врут
Как всё начиналось
 Одним из первых паттернов, способствующих
  уменьшению связности между классами, был
  локатор сервисом (Service Locator)
  До сих пор он у многих ассоциируется с понятием
  Dependency Injection
 Однако сейчас он считается скорее анти-
  паттерном, не рекомендуемым к применению
 Основная проблема – неявные требования при
  работе с классами, использующими локаторы
  сервисов
Демо
Локатор сервисов
Как внедрять зависимости?
Основное требование – объект всегда должен быть в рабочем
состоянии.
Если зависимость неявная – значит, она должна быть
необязательной.
Ни при каких обстоятельствах не должен происходить
NullReferenceException
Четыре стандартных подхода:
 Вставка через конструктор (constructor injection)
 Вставка через свойства (property injection)
 Вставка через параметры методов (methods injection)
 Использование общедоступного внешнего контекста
  (ambient context)
Constructor Injection
 Используется для всех зависимостей, без которых
    классу не обойтись
public class GreetingsManager
{
    private readonly IWriter _writer;

     public GreetingsManager(IWriter writer)
     {
         if(writer == null)
             throw new ArgumentNullException("writer",
                       "Writer was not provided");
         _writer = writer;
     }
        ...
        ...
}
Демо
Constructor Injection
Property Injection
 Используется для всех              public class GreetingsManager
  опциональных                       {
  зависимостей                           private IWriter _writer = null;
 Или для зависимостей, у                public IWriter Writer
  которых есть локальная                 {
  реализация по умолчанию                    get
                                             {
 То есть когда в 90% случаев                    if(_writer == null)
  подойдет стандартная, но                       {
  иногда нужно иметь                                 _writer = new ConsoleWriter();
  возможность заменить…                          }
 Возможно, иногда также                         return _writer;
  подойдет NullObject –                      }
  паттерн, то есть объект-                   set
   заглушка, не выполняющая                  {
   действий                                      if(_writer != null)
                                                     throw new
(пример не совсем чистый – в                            InvalidOperationException(
примерах кода GreetingsManager и                        "You can't change writer
ConsoleWriter находятся в разных                        implementation after usage");
сборках. Локальная реализация
должна принадлежать той же сборке)               _writer = value;
                                             }
                                         }
Демо
Property Injection
Method Injection
 Имеет смысл использовать, если зависимость меняется от
  метода к методу
 Также удобно использовать при написании собственного
  фреймворка, когда мы хотим передать получателю
  (например, стороннему плагину) некий контекст, хранящий
  информацию о вызывающей стороне
 public string RunPlugin(SomeValue value, ISomeContext context)
 {
     if (context == null)
     {
         throw new ArgumentNullException("context");
     }
     return context.Name;
 }
Демо
Method Injection
Ambient Context
 Некий контекст, который с большей долей
  вероятности может понадобиться (а может и не
  понадобится) в большинстве разрабатываемых
  классов
 Чтобы не передавать зависимость в каждый из
  разрабатываемых классов – применяем
  общедоступный Ambient Context
 Пример использования – текущее время (но с
  возможностью подмены значения)
Демо
Ambient Context
Абстрактные фабрики
 Удобно использовать для инстанциирования
  короткоживущих объектов
 Удобно использовать для инстанциирования
  объектов, когда тип создаваемых объектов зависит
  от параметров, известных только во время
  выполнения
 Удобно использовать, когда создание зависимости
  стоит дорого, а нужно не при каждом
  использовании класса
Декораторы
 Цепочка из декоратор позволяет нам в полной мере
  реализовать Open/Closed принцип – создавать
  классы, закрытые для модификаций, но доступные
  для расширения
 Только для расширения мы будем применять не
  наследование от этого же класса, а наследование от
  абстракции
 По сути, декоратор – это умный прокси.
Так кто же создает всю
иерархию?
 В идеале – одно место в приложении, где
  формируется весь граф зависимостей (паттерн
  Composition Root)
 В идеале – одно на всё приложение место, где мы
  запрашиваем объект – вершину пирамиды
  зависимостей
 Современные фреймворки создаются с учетом
  этого требования
  Так, в жизненном цикле запроса к ASP.NET MVC
  таким местом является ControllerFactory
Демо
Composition Root своими руками
Управление временем жизни
Lifestyle       Описание
Singletone      Единственный экземпляр, предоставляемый всем
                потребителям
Transient       Новый экземпляр каждому потребителю
PerThread       Один экземпляр внутри потока
Pooled          Определенное количество экземпляров, предоставляемое
                по мере освобождения
PerWebRequest   Один экземпляр, предоставляемый всем потребителям в
                пределах одного запроса к Web-серверу
PerGraph        Один экземпляр на граф объектов
Scoped          Один экземпляр внутри явно выделенного участка кода
Lazy            Transient, но инициализируемый не при разрешении
                зависимости, а при первом использовании
IoC – контейнеры
 Делают всё то же самое, что мы делаем руками
 Но большая часть их багов была уже поймана
  другими людьми
 Одно из главных требований к IoC контейнеру –
  99% вашего кода не должно подозревать, что вы его
  используете
 Мне неизвестные причины, которые
  аргументировали бы НЕ использовать IoC
  контейнер
IoC-контейнеры – из чего выбрать?
Ну, например…
 AutoFac
 Castle Windsor
 Dynamo.Ioc
 Funq
 Hiro
 LightCore
 LightInject
 LinFu
 Munq
 Ninject
 Petite
 Simple Injector
 Spring.NET
 StructureMap
 TinyIoc
 Unity
Castle Windsor
 Один из старейших IoC-контейнеров для .NET
 Текущая версия – 3.0.4001
 Поддерживает конфигурирование из кода (FluentAPI),
    конфигурирование из XML и конфигурирование согласно
    конвенциям
   Отличные возможности для отладки – полная
    диагностическая информация о зарегистрированных
    классах и интерфейсах
   Концепция установщиков (Installer), позволяющая
    разносить регистрационный код для компонентов
   Поддержка абстракций логирования
   Поддержка Interception
   Поддержка авто-реализации фабрик
Демо
Регистрация и разрешение
зависимостей
Перехват (Interception) вызовов
 Один из подходов к реализации cross-cutting
  concerns (вещей, которые используются во всех
  слоях вашего приложения – таких как логирование,
  проверка безопасности, кэширование и т.п.)
  Разновидность аспектного программирования
 Позволяет выполнять действия до или после
  вызовов методов у зависимостей, а также
  обрабатывать результат выполнения
 Сходен с Декоратором, но отсутствует
  необходимость дублировать код для каждого
  интерфейса и метода в интерфейсе
Демо
Interception в Castle Windsor
Фабрики в Castle Windsor
 Interface-based Factories – на основе интерфейса
  Castle Windsor сам генерирует фабрику
 Delegate-based Factories – можно зарегистрировать
  делегат типа Func<TResult>, который будет играть
  роль фабричного метода
Демо
Фабрики в Castle Windsor
Отдельные темы для обсуждения
 Constructor Over-Injection
 public HomeController(IBookRepository rep,
      ICurrentUser user,
      ICurrencyFormatter formatter,
      IDateTimeProvider dateTimeProvider,
      IBookReturnmentPolicy policy,
      IBookOrderService         bookOrderService,
      IBookSearchService bookSearchService,
      IScheduler scheduler,
      IEmailService emailService,
      ISmsSender smsSender){
      …
 }

 Работа с IDisposable-зависимостями
 Круговая зависимость
Реальная жизнь
 На примере сайт GetDev.NET
  ASP.NET MVC 3
  Castle Windsor
 Так и не удалось добиться единого Composition Root –
  CustomRoleProvider создается средой исполнения и не
  имеет возможности вставки зависимостей
  Используем Service Locator ;)
 Для доступа к данным – абстракция над Linq to Sql
 interface IUnitOfWork : IDisposable{
        ITable<User> Users{ get; set; }
        …
 }
  Создаётся абстрактной фабрикой
 Декоратор вокруг IAccountService – кэширование ролей
  пользователя
Вопросы?
          Внимательно слушаю! 
                  Андрей Кулешов
                  «Деловые решения»
                  Директор
akuleshov@solforbiz.com            akuleshov.tula
http://www.solforbiz.com


Специально для http://GetDev.NET
Интересное чтение
 Dependency Injection in .NET by Mark Seemann
    http://manning.com/seemann/
   Castle Windsor homepage
    http://stw.castleproject.org/Windsor.MainPage.ashx
   Krzysztof Koźmic's blog
    http://kozmic.pl/
   Сравнение производительности IoC-контейнеров
    http://www.palmmedia.de/Blog/2011/8/30/ioc-container-
    benchmark-performance-comparison
   Сравнение функциональности некоторых IoC-контейнеров
    http://code.google.com/p/net-ioc-frameworks/
Интересное видео
 IoC Container usage: Patterns and anti-pattern (Krzysztof
  Koźmic)
  http://kozmic.pl/presentations/
 Inversion of Control/Dependency Injection Pattern
  (Hammet Verissimo & Michael Puleio)
  http://channel9.msdn.com/posts/PP-Symposium-2010-
  Inversion-of-ControlDependency-Injection-Pattern-
  Hammet-Verissimo--Michael-Puleio
 Channel 9
  http://channel9.msdn.com/
  Текстовое поле “Search” –> “Dependency Injection” ||
  “Inversion of Control” -> Enter

More Related Content

What's hot

C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.Igor Shkulipa
 
введение в Javascript
введение в Javascriptвведение в Javascript
введение в Javascriptinqubick
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.Igor Shkulipa
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0akrakovetsky
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.Igor Shkulipa
 
Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Dima Dzuba
 
Объектно-ориентированное программирование. Лекции 15 и 16
Объектно-ориентированное программирование. Лекции 15 и 16Объектно-ориентированное программирование. Лекции 15 и 16
Объектно-ориентированное программирование. Лекции 15 и 16Dima Dzuba
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.Igor Shkulipa
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.Igor Shkulipa
 
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoFШаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoFSergey Nemchinsky
 
Java. Многопоточность.
Java. Многопоточность.Java. Многопоточность.
Java. Многопоточность.Unguryan Vitaliy
 
МАИ, Сети ЭВМ, Лекция №4
МАИ, Сети ЭВМ, Лекция №4МАИ, Сети ЭВМ, Лекция №4
МАИ, Сети ЭВМ, Лекция №4Dima Dzuba
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 

What's hot (20)

C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.C++ STL & Qt. Занятие 03.
C++ STL & Qt. Занятие 03.
 
введение в Javascript
введение в Javascriptвведение в Javascript
введение в Javascript
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
 
лекция 5
лекция 5лекция 5
лекция 5
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Working with .NET Threads
Working with .NET ThreadsWorking with .NET Threads
Working with .NET Threads
 
Обзор SObjectizer 5.5
Обзор SObjectizer 5.5Обзор SObjectizer 5.5
Обзор SObjectizer 5.5
 
Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.
 
Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.Архитектура. Доступноять программных систем.
Архитектура. Доступноять программных систем.
 
Объектно-ориентированное программирование. Лекции 15 и 16
Объектно-ориентированное программирование. Лекции 15 и 16Объектно-ориентированное программирование. Лекции 15 и 16
Объектно-ориентированное программирование. Лекции 15 и 16
 
Bytecode
BytecodeBytecode
Bytecode
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.
 
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoFШаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
 
Java. Многопоточность.
Java. Многопоточность.Java. Многопоточность.
Java. Многопоточность.
 
Сервлеты
СервлетыСервлеты
Сервлеты
 
МАИ, Сети ЭВМ, Лекция №4
МАИ, Сети ЭВМ, Лекция №4МАИ, Сети ЭВМ, Лекция №4
МАИ, Сети ЭВМ, Лекция №4
 
C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 

Similar to Dependency injection

Шаблоны проектирования в Magento
Шаблоны проектирования в MagentoШаблоны проектирования в Magento
Шаблоны проектирования в MagentoPavel Usachev
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011etyumentcev
 
Как пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftКак пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftAnton Loginov
 
C# Desktop. Занятие 15.
C# Desktop. Занятие 15.C# Desktop. Занятие 15.
C# Desktop. Занятие 15.Igor Shkulipa
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьAndrey Bibichev
 
Codeception + Docker + Robo и что из этого вышло
Codeception + Docker + Robo и что из этого вышлоCodeception + Docker + Robo и что из этого вышло
Codeception + Docker + Robo и что из этого вышлоCOMAQA.BY
 
Pavel Rumantsev - Java Script
Pavel Rumantsev - Java ScriptPavel Rumantsev - Java Script
Pavel Rumantsev - Java Scriptbeloslab
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.Igor Shkulipa
 
JavaScript design patterns overview
JavaScript design patterns overview JavaScript design patterns overview
JavaScript design patterns overview Kseniya Redunova
 
Платформа для автоматического тестирования Erlang проектов на примере UserGat...
Платформа для автоматического тестирования Erlang проектов на примере UserGat...Платформа для автоматического тестирования Erlang проектов на примере UserGat...
Платформа для автоматического тестирования Erlang проектов на примере UserGat...DevDay
 
Java осень 2012 лекция 9
Java осень 2012 лекция 9Java осень 2012 лекция 9
Java осень 2012 лекция 9Technopark
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5Technopark
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - MultithreadingNoveo
 
разработка бизнес приложений (7)
разработка бизнес приложений (7)разработка бизнес приложений (7)
разработка бизнес приложений (7)Alexander Gornik
 

Similar to Dependency injection (20)

DESIGN PATTERNS? EASY!
DESIGN PATTERNS? EASY!DESIGN PATTERNS? EASY!
DESIGN PATTERNS? EASY!
 
Шаблоны проектирования в Magento
Шаблоны проектирования в MagentoШаблоны проектирования в Magento
Шаблоны проектирования в Magento
 
Step 1
Step 1Step 1
Step 1
 
Deep Dive in Magento DI
Deep Dive in Magento DIDeep Dive in Magento DI
Deep Dive in Magento DI
 
ук 03.003.01 2011
ук 03.003.01 2011ук 03.003.01 2011
ук 03.003.01 2011
 
Как пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftКак пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на Swift
 
Software Design Patterns
Software Design PatternsSoftware Design Patterns
Software Design Patterns
 
C# Desktop. Занятие 15.
C# Desktop. Занятие 15.C# Desktop. Занятие 15.
C# Desktop. Занятие 15.
 
Refactoring
RefactoringRefactoring
Refactoring
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связность
 
Codeception + Docker + Robo и что из этого вышло
Codeception + Docker + Robo и что из этого вышлоCodeception + Docker + Robo и что из этого вышло
Codeception + Docker + Robo и что из этого вышло
 
Pavel Rumantsev - Java Script
Pavel Rumantsev - Java ScriptPavel Rumantsev - Java Script
Pavel Rumantsev - Java Script
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 
JavaScript design patterns overview
JavaScript design patterns overview JavaScript design patterns overview
JavaScript design patterns overview
 
Платформа для автоматического тестирования Erlang проектов на примере UserGat...
Платформа для автоматического тестирования Erlang проектов на примере UserGat...Платформа для автоматического тестирования Erlang проектов на примере UserGat...
Платформа для автоматического тестирования Erlang проектов на примере UserGat...
 
Java осень 2012 лекция 9
Java осень 2012 лекция 9Java осень 2012 лекция 9
Java осень 2012 лекция 9
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - Multithreading
 
Genome
GenomeGenome
Genome
 
разработка бизнес приложений (7)
разработка бизнес приложений (7)разработка бизнес приложений (7)
разработка бизнес приложений (7)
 

More from GetDev.NET

Leap Motion - игрушка с заделом на будущее
Leap Motion - игрушка с заделом на будущееLeap Motion - игрушка с заделом на будущее
Leap Motion - игрушка с заделом на будущееGetDev.NET
 
Гирлянда для программистов
Гирлянда для программистовГирлянда для программистов
Гирлянда для программистовGetDev.NET
 
Mind Mapping, или как заставить свой мозг работать лучше
Mind Mapping, или как заставить свой мозг работать лучшеMind Mapping, или как заставить свой мозг работать лучше
Mind Mapping, или как заставить свой мозг работать лучшеGetDev.NET
 
Что нового в Visual Studio 2015
Что нового в Visual Studio 2015Что нового в Visual Studio 2015
Что нового в Visual Studio 2015GetDev.NET
 
Docker контейнерная революция
Docker контейнерная революцияDocker контейнерная революция
Docker контейнерная революцияGetDev.NET
 
Windows 10 для пользователей и разработчиков
Windows 10 для пользователей и разработчиковWindows 10 для пользователей и разработчиков
Windows 10 для пользователей и разработчиковGetDev.NET
 
PhoneGap для мобильного разработчика - глубокое погружение без ОЗК
PhoneGap для мобильного разработчика - глубокое погружение без ОЗКPhoneGap для мобильного разработчика - глубокое погружение без ОЗК
PhoneGap для мобильного разработчика - глубокое погружение без ОЗКGetDev.NET
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web APIGetDev.NET
 
Что нового в Visual Studio 2013
Что нового в Visual Studio 2013Что нового в Visual Studio 2013
Что нового в Visual Studio 2013GetDev.NET
 
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...GetDev.NET
 
Lego Mindstorms
Lego MindstormsLego Mindstorms
Lego MindstormsGetDev.NET
 
Особенности мобильной платформы Windows Phone 8
Особенности мобильной платформы Windows Phone 8Особенности мобильной платформы Windows Phone 8
Особенности мобильной платформы Windows Phone 8GetDev.NET
 
Async Javascript
Async JavascriptAsync Javascript
Async JavascriptGetDev.NET
 
XAML - язык разметки приложений
XAML - язык разметки приложенийXAML - язык разметки приложений
XAML - язык разметки приложенийGetDev.NET
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language RuntimeGetDev.NET
 
JavaScript: хороший тон клиентской разработки
JavaScript: хороший тон клиентской разработкиJavaScript: хороший тон клиентской разработки
JavaScript: хороший тон клиентской разработкиGetDev.NET
 
Roslyn - компилятор как сервис
Roslyn - компилятор как сервисRoslyn - компилятор как сервис
Roslyn - компилятор как сервисGetDev.NET
 

More from GetDev.NET (20)

Go
GoGo
Go
 
Leap Motion - игрушка с заделом на будущее
Leap Motion - игрушка с заделом на будущееLeap Motion - игрушка с заделом на будущее
Leap Motion - игрушка с заделом на будущее
 
Гирлянда для программистов
Гирлянда для программистовГирлянда для программистов
Гирлянда для программистов
 
Mind Mapping, или как заставить свой мозг работать лучше
Mind Mapping, или как заставить свой мозг работать лучшеMind Mapping, или как заставить свой мозг работать лучше
Mind Mapping, или как заставить свой мозг работать лучше
 
Что нового в Visual Studio 2015
Что нового в Visual Studio 2015Что нового в Visual Studio 2015
Что нового в Visual Studio 2015
 
Docker контейнерная революция
Docker контейнерная революцияDocker контейнерная революция
Docker контейнерная революция
 
Windows 10 для пользователей и разработчиков
Windows 10 для пользователей и разработчиковWindows 10 для пользователей и разработчиков
Windows 10 для пользователей и разработчиков
 
PhoneGap для мобильного разработчика - глубокое погружение без ОЗК
PhoneGap для мобильного разработчика - глубокое погружение без ОЗКPhoneGap для мобильного разработчика - глубокое погружение без ОЗК
PhoneGap для мобильного разработчика - глубокое погружение без ОЗК
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
 
Что нового в Visual Studio 2013
Что нового в Visual Studio 2013Что нового в Visual Studio 2013
Что нового в Visual Studio 2013
 
AngularJS
AngularJSAngularJS
AngularJS
 
TypeScript
TypeScriptTypeScript
TypeScript
 
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
Создание повторно используемых бизнес моделей с помощью технологии Domain Com...
 
Lego Mindstorms
Lego MindstormsLego Mindstorms
Lego Mindstorms
 
Особенности мобильной платформы Windows Phone 8
Особенности мобильной платформы Windows Phone 8Особенности мобильной платформы Windows Phone 8
Особенности мобильной платформы Windows Phone 8
 
Async Javascript
Async JavascriptAsync Javascript
Async Javascript
 
XAML - язык разметки приложений
XAML - язык разметки приложенийXAML - язык разметки приложений
XAML - язык разметки приложений
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language Runtime
 
JavaScript: хороший тон клиентской разработки
JavaScript: хороший тон клиентской разработкиJavaScript: хороший тон клиентской разработки
JavaScript: хороший тон клиентской разработки
 
Roslyn - компилятор как сервис
Roslyn - компилятор как сервисRoslyn - компилятор как сервис
Roslyn - компилятор как сервис
 

Dependency injection

  • 2. Про что мы говорим?  В первую очередь – про подход к взаимодействую между классами и объектами в мире объектно- ориентированного программирования  Во вторую очередь – про существующие шаблоны реализации этого подхода  И только в третью очередь – про сторонние компоненты - IoC-контейнеры
  • 3. Спагетти-код и лазанья-код  Спагетти-код – это код, представляющий собой одну большую хаотичную мешанину классов, отвечающих за все функции вашего приложения  Лазанья-код - это код, представляющий собой несколько отдельных маленьких хаотичных мешанин классов – слоёв, взаимодействующих друг с другом по строго определенным контрактом, не зависящим от реализации.  Классическая модель – всем известная уровень данных, уровень бизнес-логики, уровень пользовательского интерфейса. Но их может быть больше.
  • 4. Формирование слоёв  Слой – группа классов, имеющих схожее назначение  Взаимодействие между слоями идёт через «швы»  Взаимодействие через швы должны идти только через контракты (интерфейсы или абстрактные классы), а не конкретные реализации  И этим вы сможете добиться, что маленький локальный хаос внутри конкретного слоя останется таковым, а не разрастется на всё приложение
  • 5. Что такое «зависимость» («dependency»)  Что-то сильно внешнее по отношению к нашему классу, медленное, тяжелое в настройке, а также просто ещё не готовое.. В первую очередь это: - файловая система; - база данных - сеть; - сервис, который коллега послезавтра обязательно допишет; - система старта ракетных двигателей.  Ваш класс должен зависеть от абстракций, а не от конкретных реализаций
  • 6. Классическая работа с зависимостями:  Когда вы напрямую создаёте экземпляр объекта в вашем классе - вы контролируете его IDbConnection connection = new SqlServerConnection(“source=localhost”);  Контролируете, когда он создается, какие параметры принимает, когда он больше не нужен и его надо удалять  Контролируете, что создается именно этот тип объекта, а не схожий по функиональности  То есть всерьез декларируете, что класс, который считает сумму заказов в вашей корзине покупок, должен знать о балансированной ферме Sql Server, и том, какой таймаут допустим при работе с ней
  • 8. Inversion of Control Инвертированный контроль:  При использование IoC – ваш класс больше не имеет контроля над зависимостями public class Basket{ public Basket(IDbConnection connection){ //save connection... } }  Об этом заботится кто-то снаружи этого класса  Кто-то, кто знает больше и лучше. Кто на этом специализируется  А ваш класс перестаёт зависеть от конкретной реализации
  • 9. Что злобные враги рассказывают вам об DI  DI – это «локатор сервисов» нагло врут  DI нужен только для тестирования нагло врут  DI нужен только для позднего связывания нагло врут  Для архитектуры в стиле DI нужен IoC контейнер нагло врут
  • 10. Как всё начиналось  Одним из первых паттернов, способствующих уменьшению связности между классами, был локатор сервисом (Service Locator) До сих пор он у многих ассоциируется с понятием Dependency Injection  Однако сейчас он считается скорее анти- паттерном, не рекомендуемым к применению  Основная проблема – неявные требования при работе с классами, использующими локаторы сервисов
  • 12. Как внедрять зависимости? Основное требование – объект всегда должен быть в рабочем состоянии. Если зависимость неявная – значит, она должна быть необязательной. Ни при каких обстоятельствах не должен происходить NullReferenceException Четыре стандартных подхода:  Вставка через конструктор (constructor injection)  Вставка через свойства (property injection)  Вставка через параметры методов (methods injection)  Использование общедоступного внешнего контекста (ambient context)
  • 13. Constructor Injection  Используется для всех зависимостей, без которых классу не обойтись public class GreetingsManager { private readonly IWriter _writer; public GreetingsManager(IWriter writer) { if(writer == null) throw new ArgumentNullException("writer", "Writer was not provided"); _writer = writer; } ... ... }
  • 15. Property Injection  Используется для всех public class GreetingsManager опциональных { зависимостей private IWriter _writer = null;  Или для зависимостей, у public IWriter Writer которых есть локальная { реализация по умолчанию get {  То есть когда в 90% случаев if(_writer == null) подойдет стандартная, но { иногда нужно иметь _writer = new ConsoleWriter(); возможность заменить… }  Возможно, иногда также return _writer; подойдет NullObject – } паттерн, то есть объект- set заглушка, не выполняющая { действий if(_writer != null) throw new (пример не совсем чистый – в InvalidOperationException( примерах кода GreetingsManager и "You can't change writer ConsoleWriter находятся в разных implementation after usage"); сборках. Локальная реализация должна принадлежать той же сборке) _writer = value; } }
  • 17. Method Injection  Имеет смысл использовать, если зависимость меняется от метода к методу  Также удобно использовать при написании собственного фреймворка, когда мы хотим передать получателю (например, стороннему плагину) некий контекст, хранящий информацию о вызывающей стороне public string RunPlugin(SomeValue value, ISomeContext context) { if (context == null) { throw new ArgumentNullException("context"); } return context.Name; }
  • 19. Ambient Context  Некий контекст, который с большей долей вероятности может понадобиться (а может и не понадобится) в большинстве разрабатываемых классов  Чтобы не передавать зависимость в каждый из разрабатываемых классов – применяем общедоступный Ambient Context  Пример использования – текущее время (но с возможностью подмены значения)
  • 21. Абстрактные фабрики  Удобно использовать для инстанциирования короткоживущих объектов  Удобно использовать для инстанциирования объектов, когда тип создаваемых объектов зависит от параметров, известных только во время выполнения  Удобно использовать, когда создание зависимости стоит дорого, а нужно не при каждом использовании класса
  • 22. Декораторы  Цепочка из декоратор позволяет нам в полной мере реализовать Open/Closed принцип – создавать классы, закрытые для модификаций, но доступные для расширения  Только для расширения мы будем применять не наследование от этого же класса, а наследование от абстракции  По сути, декоратор – это умный прокси.
  • 23. Так кто же создает всю иерархию?  В идеале – одно место в приложении, где формируется весь граф зависимостей (паттерн Composition Root)  В идеале – одно на всё приложение место, где мы запрашиваем объект – вершину пирамиды зависимостей  Современные фреймворки создаются с учетом этого требования Так, в жизненном цикле запроса к ASP.NET MVC таким местом является ControllerFactory
  • 25. Управление временем жизни Lifestyle Описание Singletone Единственный экземпляр, предоставляемый всем потребителям Transient Новый экземпляр каждому потребителю PerThread Один экземпляр внутри потока Pooled Определенное количество экземпляров, предоставляемое по мере освобождения PerWebRequest Один экземпляр, предоставляемый всем потребителям в пределах одного запроса к Web-серверу PerGraph Один экземпляр на граф объектов Scoped Один экземпляр внутри явно выделенного участка кода Lazy Transient, но инициализируемый не при разрешении зависимости, а при первом использовании
  • 26. IoC – контейнеры  Делают всё то же самое, что мы делаем руками  Но большая часть их багов была уже поймана другими людьми  Одно из главных требований к IoC контейнеру – 99% вашего кода не должно подозревать, что вы его используете  Мне неизвестные причины, которые аргументировали бы НЕ использовать IoC контейнер
  • 27. IoC-контейнеры – из чего выбрать? Ну, например…  AutoFac  Castle Windsor  Dynamo.Ioc  Funq  Hiro  LightCore  LightInject  LinFu  Munq  Ninject  Petite  Simple Injector  Spring.NET  StructureMap  TinyIoc  Unity
  • 28. Castle Windsor  Один из старейших IoC-контейнеров для .NET  Текущая версия – 3.0.4001  Поддерживает конфигурирование из кода (FluentAPI), конфигурирование из XML и конфигурирование согласно конвенциям  Отличные возможности для отладки – полная диагностическая информация о зарегистрированных классах и интерфейсах  Концепция установщиков (Installer), позволяющая разносить регистрационный код для компонентов  Поддержка абстракций логирования  Поддержка Interception  Поддержка авто-реализации фабрик
  • 30. Перехват (Interception) вызовов  Один из подходов к реализации cross-cutting concerns (вещей, которые используются во всех слоях вашего приложения – таких как логирование, проверка безопасности, кэширование и т.п.) Разновидность аспектного программирования  Позволяет выполнять действия до или после вызовов методов у зависимостей, а также обрабатывать результат выполнения  Сходен с Декоратором, но отсутствует необходимость дублировать код для каждого интерфейса и метода в интерфейсе
  • 32. Фабрики в Castle Windsor  Interface-based Factories – на основе интерфейса Castle Windsor сам генерирует фабрику  Delegate-based Factories – можно зарегистрировать делегат типа Func<TResult>, который будет играть роль фабричного метода
  • 34. Отдельные темы для обсуждения  Constructor Over-Injection public HomeController(IBookRepository rep, ICurrentUser user, ICurrencyFormatter formatter, IDateTimeProvider dateTimeProvider, IBookReturnmentPolicy policy, IBookOrderService bookOrderService, IBookSearchService bookSearchService, IScheduler scheduler, IEmailService emailService, ISmsSender smsSender){ … }  Работа с IDisposable-зависимостями  Круговая зависимость
  • 35. Реальная жизнь  На примере сайт GetDev.NET ASP.NET MVC 3 Castle Windsor  Так и не удалось добиться единого Composition Root – CustomRoleProvider создается средой исполнения и не имеет возможности вставки зависимостей Используем Service Locator ;)  Для доступа к данным – абстракция над Linq to Sql interface IUnitOfWork : IDisposable{ ITable<User> Users{ get; set; } … } Создаётся абстрактной фабрикой  Декоратор вокруг IAccountService – кэширование ролей пользователя
  • 36. Вопросы? Внимательно слушаю!  Андрей Кулешов «Деловые решения» Директор akuleshov@solforbiz.com akuleshov.tula http://www.solforbiz.com Специально для http://GetDev.NET
  • 37. Интересное чтение  Dependency Injection in .NET by Mark Seemann http://manning.com/seemann/  Castle Windsor homepage http://stw.castleproject.org/Windsor.MainPage.ashx  Krzysztof Koźmic's blog http://kozmic.pl/  Сравнение производительности IoC-контейнеров http://www.palmmedia.de/Blog/2011/8/30/ioc-container- benchmark-performance-comparison  Сравнение функциональности некоторых IoC-контейнеров http://code.google.com/p/net-ioc-frameworks/
  • 38. Интересное видео  IoC Container usage: Patterns and anti-pattern (Krzysztof Koźmic) http://kozmic.pl/presentations/  Inversion of Control/Dependency Injection Pattern (Hammet Verissimo & Michael Puleio) http://channel9.msdn.com/posts/PP-Symposium-2010- Inversion-of-ControlDependency-Injection-Pattern- Hammet-Verissimo--Michael-Puleio  Channel 9 http://channel9.msdn.com/ Текстовое поле “Search” –> “Dependency Injection” || “Inversion of Control” -> Enter