Dependency injection на примере unity и n inject
Upcoming SlideShare
Loading in...5
×
 

Dependency injection на примере unity и n inject

on

  • 3,198 views

 

Statistics

Views

Total Views
3,198
Views on SlideShare
3,117
Embed Views
81

Actions

Likes
1
Downloads
35
Comments
0

4 Embeds 81

http://project2502.wordpress.com 66
http://www.slideshare.net 10
http://www.linkedin.com 4
https://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • В процессе разработки и проектирования приложения мы стремимся чтобы код и само приложение в целом соответствовали определенному набору критериев, которые в нашем понимании являются критериями качественного кода, критериями хорошо спроектированой системы. Эти критерии известны и сформировались с опытом. Это расширяемость, сопровождаемость, простота, читабельность и тестируемость.В процессе проектирования/перепроектирования/рефакторинга мы сталкиваемся с проблемами которые …
  • В процессе разработки код программы постоянно меняется. Вот некоторые проблемы с которыми сталкиваются разработчики при изменении/перепроектировании систем.При создании объекта явно указывается класс. Задание имени класса при создании объекта привязывает к конкретной реализации, что усложняет изменение объекта в будущем. Т.е. поддерживать такой объект будет намного сложнее, а связанность объектов повышается.При сильной связанности внутри программы код становится более хрупким. Внесение изменений затруднено, так как изменения приходится вносить в Внесение изменений в одном месте кода ведет к изменениям в другом, в следствии чего число багов увеличивается
  • This is another option for an Overview slides using transitions.
  • В процессе разработки код программы постоянно меняется. Вот некоторые проблемы с которыми сталкиваются разработчики при изменении/перепроектировании систем.При создании объекта явно указывается класс. Задание имени класса при создании объекта привязывает к конкретной реализации, что усложняет изменение объекта в будущем. Т.е. поддерживать такой объект будет намного сложнее, а связанность объектов повышается.При сильной связанности внутри программы код становится более хрупким. Внесение изменений затруднено, так как изменения приходится вносить в Внесение изменений в одном месте кода ведет к изменениям в другом, в следствии чего число багов увеличивается
  • В процессе разработки код программы постоянно меняется. Вот некоторые проблемы с которыми сталкиваются разработчики при изменении/перепроектировании систем.При создании объекта явно указывается класс. Задание имени класса при создании объекта привязывает к конкретной реализации, что усложняет изменение объекта в будущем. Т.е. поддерживать такой объект будет намного сложнее, а связанность объектов повышается.При сильной связанности внутри программы код становится более хрупким. Внесение изменений затруднено, так как изменения приходится вносить в Внесение изменений в одном месте кода ведет к изменениям в другом, в следствии чего число багов увеличивается

Dependency injection на примере unity и n inject Dependency injection на примере unity и n inject Presentation Transcript

  • Dependency Injection на примере Unity и nInject
    Калита Роман
    TaskManagementSoft
  • План
    Что такое Dependency Injection?
    Как проблемы решает и какие преимущества дает при проектировании
    Какие есть формы DI
    DI контейнеры в .NET
  • Качественный код/система
    Код
    View slide
  • Некоторые проблемы при проектировании приложений
    По версии GoF
    View slide
  • Сильносвязанные системы
  • Сильносвязанные системы
    сложно
    О каких качествах кода может идти речь?
  • Уменьшаем связанность
  • Фабрика, Локатор, Метод
    Запрашивает IMyInterface
    Клиент
    Фабрика, Локатор, Метод
    Создает MyClass
    MyClass
    IMyInterface
    Реализует IMyInterface
  • Dependency Injection
    Обявляет зависимости
    запрашивает
    Клиент
    DI контейнер
    внедряет
    создает/возвращает
    читает
    MyClass : IMyInterface
    MyClass : IMyInterface
    Конфигурация
  • Что такое Dependency Injection?
    Инверсия зависимостей == Обращение контроля == Внедрение зависимостей == Dependency injection
    Это принцип в объектно ориентированом программировании, который означает:
    • Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции.
    • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
    Цель:
    • Уменьшить связность
  • Пример связанного приложения
    publicclassProgram
    {
    publicstaticvoid Main(string[] args)
    {
    varorderManager = newOrderManager();
    orderManager.ProcessOrders();
    }
    }
    OrderManager
    OrdersQueue
    OrdersProcessor
  • Пример связанного приложения
    publicclassOrderManager
    {
    publicvoid ProcessOrders()
    {
    var ordersQueue = newOrdersQueue();
    IList<Order> orders = ordersQueue.GetPendingOrders();
     
    if (orders.Count == 0)
    thrownewEmptyOrdersQueueException();
     
    var ordersProcessor = newManualOrdersProcessor();
    foreach (Order order in orders)
    {
    ordersProcessor.ProcessOrder(order);
    }
    }
    }
  • Пример связанного приложения
    publicclassOrderManager
    {
    publicvoid ProcessOrders()
    {
    var ordersQueue = newOrdersQueue();
    IList<Order> orders = ordersQueue.GetPendingOrders();
     
    if (orders.Count == 0)
    thrownewNoOrdersException();
     
    var ordersProcessor = newManualOrdersProcessor();
    foreach (Order order in orders)
    {
    ordersProcessor.ProcessOrder(order);
    }
    }
    }
  • Проблемы в примере
    • Тестируемость
    [TestClass]
    publicclassOrderManagerTests
    {
    [TestMethod]
    publicvoidshould_process_orders()
    {
    varorderManager = newOrderManager();
    orderManager.ProcessOrders();
    }
    }
    • Привязан к конкрентым сущностям, знает о них и создает их
  • Применяем принципвручную
    • Будем привязыватся к интерфейсам
    publicinterfaceOrdersProcessor
    {
    void Process(Order order);
    }
    publicinterfaceIOrdersQueue
    {
    List<Order> GetPendingOrders();
    }
    • Вынесемзависимости в readonlyполя класса, которые будут заполнятся из вне при инстанциировании объекта
  • Применяем принципвручную
    publicclassOrderManager{
    privatereadonlyIOrdersQueueordersQueue;
    privatereadonlyIOrdersProcessorordersProcessor;
    publicOrderManager(IOrdersQueueordersQueue,
    IOrdersProcessorordersProcessor)
    {
    this.ordersProcessor = ordersProcessor;
    this.ordersQueue = ordersQueue;
    }
    publicvoidProcessOrders()
    {
    IList<Order> orders = ordersQueue.GetPendingOrders();
    if (orders.Count == 0)
    thrownewNoOrdersException();
    foreach (Orderorderin orders)
    {
    ordersProcessor.Process(order);
    }
    }
    }
  • Применяем используя контейнер
    publicclassOrderManager
    {
    [Inject]
    publicIOrdersQueueordersQueue { get; set; }
    [Inject]
    publicIOrdersProcessorordersProcessor { get; set; }
    publicvoidProcessOrders()
    {
    IList<Order> orders = ordersQueue.GetPendingOrders();
    if (orders.Count == 0)
    thrownewNoOrdersException();
    foreach (Orderorderin orders)
    {
    ordersProcessor.Process(order);
    }
    }
    }
  • Ручное DI vsКонтейнер
    • Оба варианта решают проблему класса с высокой связанностью
    • Если вручную, выполнение лишней работы по созданию и наполнению зависимостями
    • Если используюя контейнер досутпны возможности по «автоматическому» или «условному» наполнению зависимостями, не требующие никаких усилий
    • Время жизни объектов также должно гибко контролироватся, вручную – «лишняя работа»
  • Формы Dependecy Injection
    • Constructor Injection
    [Inject]
    publicOrderManager(IOrdersQueueordersQueue, IOrdersProcessorordersProcessor)
    {
    this.ordersProcessor= ordersProcessor;
    this.ordersQueue= ordersQueue;
    }
    • Property(Setter) Injection
    [Inject]
    publicIOrdersProcessorordersProcessor { get; }
    • Method Injection
    [Inject]
    voidDoSomeTask(IOrdersQueueorederQueue)
    {
    // ...
    }
  • Dependecy Injectionконтейнеры
    • StructureMap (AltDotNet)
    http://structuremap.sourceforge.net/Default.htm
    • Castle Windsor (AltDotNet)
    http://www.castleproject.org/container/index.html
    • Unity (Microsoft P&P)
    http://www.codeplex.com/unity
    • Ninject (open source)
    http://ninject.org
    • Много других (LinFu, например)
  • Dependecy Injection используя nInject
    • Необходимо определить конфигурацию
    publicclassOrdersModule : NinjectModule
    {
    publicoverridevoid Load()
    {
    Bind<IOrdersQueue>().To<OrdersQueue>();
    Bind<IOrdersQueue>().To<OrdersQueue>();
    Bind<IOrdersProcessor>().To<ManualOrdersProcessor>();
    Bind<OrderManager>().ToSelf();
    }
    }
    • Теперь можно использовать, например property injection
    [Inject]
    publicIOrdersQueueordersQueue { get; set; }
  • Dependecy Injection используя Unity
    • Необходимо определить конфигурацию
    varunityContainer = newUnityContainer()
    .RegisterType<IOrdersProcessor, ManualOrdersProcessor>()
    .RegisterType<IOrdersQueue, OrdersQueue>();
    OrdersManager manager = unityContainer.Resolve<OrdersManager>();
    manager.ProcessOrders();
    • Теперь можно использовать, например property injection
    [Dependency]
    publicIOrdersQueueordersQueue { get; set; }
  • “Продвинутая” конфигурация
    • Условный биндинг
    Bind<IOrdersProcessor>().To<ManualOrdersProcessor>().WhenTargetHas<MyAttribute>();
    Bind<IOrdersProcessor>().To<ManualOrdersProcessor>()
    .Only(When.Context.Target.Name.BeginsWith("Manual"));
    var container = newUnityContainer()
    .RegisterType<IOrdersQueue, OrdersQueue>()
    .RegisterType<IOrdersProcessor, ManualOrdersProcessor>(newInjectionConstructor(10));
    • Время жизни
    Bind<IOrdersProcessor>().To<ManualOrdersProcessor>().InSingletonScope();
    Bind<IOrdersProcessor>().To<ManualOrdersProcessor>().InThreadScope();
    var container = newUnityContainer()
    .RegisterType<IOrdersProcessor, ManualOrdersProcessor>(newContainerControlledLifetimeManager())
  • Преимущества от использования Dependecy Injection
    • Разделение конфигурирования связей и использования объектов
    • Уменьшается связывание
    Абстрактные интерфейсы не меняются
    Конкретные объекты реализуют эти интерфейсы
    Конкретные объекты проще заменить
    • Увеличение мобильности модулей
    • Улучшение изоляции объектов
    Уменьшается связность
    Увеличивается тестируемость
    Увеличивается удобство в поддержке
  • Ссылки
    • http://martinfowler.com/articles/injection.html
    • http://www.objectmentor.com/resources/articles/dip.pdf
    • http://msdn.microsoft.com/en-us/library/aa973811.aspx
    • http://ninject.org/
    • http://unity.codeplex.com
  • Спасибо за внимание:)