Dependency Injection. Неявное управление зависимостями

Содержание

Слайд 2

public class Chessboard
{
public Chessboard()
{
this.cells = LoadBoard(
new StreamReader("input.txt"),
new

public class Chessboard { public Chessboard() { this.cells = LoadBoard( new StreamReader("input.txt"),
BoardParser());
}
}

НЕЯВНОЕ УПРАВЛЕНИЕ ЗАВИСИМОСТЯМИ

Неявные связи

Слайд 3

реализация интерфейса

использование

SRP

DIP

реализация интерфейса использование SRP DIP

Слайд 4

public class Chessboard
{
public Chessboard(
StreamReader input,
IBoardParser boardParser)
{
this.cells = LoadBoard(input,

public class Chessboard { public Chessboard( StreamReader input, IBoardParser boardParser) { this.cells
boardParser);
}
}

ЯВНОЕ (ИНЪЕКЦИЯ ЗАВИСИМОСТЕЙ)

Нужные значения передадут извне

Слайд 5

Не вызывать статические методы
Не вызывать конструкторы
Ссылки на объекты передавать в конструктор
- Кто

Не вызывать статические методы Не вызывать конструкторы Ссылки на объекты передавать в
их передает в конструктор?
- Кто-то «свыше»!
- А ему?
- Тоже кто-то «свыше»!
- А ему?

ЯВНОЕ УПРАВЛЕНИЕ ЗАВИСИМОСТЯМИ

Слайд 6

Composition Root
место, где модули соединяются вместе
загончик для операторов new
Чем ближе к точке

Composition Root место, где модули соединяются вместе загончик для операторов new Чем
входа – тем лучше
void Main() для консольного приложения
HttpHandler для веб-сервиса
В библиотеках
либо не собирать – пусть собирает использующий
либо в классе-фасаде библиотеки

ТОЧКА ВХОДА - МЕСТО СБОРА ЗАВИСИМОСТЕЙ

Слайд 7

Имена файлов, пути, порты, ...
Неудобные зависимости (файлы, консоль, ui, сеть, БД, ...)
Другие

Имена файлов, пути, порты, ... Неудобные зависимости (файлы, консоль, ui, сеть, БД,
сервисы
Формат файла
Алгоритм если его может понадобиться менять
Реализация структуры данных если её может понадобиться менять

КАКИЕ ЗАВИСИМОСТИ ДЕЛАТЬ ЯВНЫМИ?

Слайд 8

В ЧЕМ РАЗНИЦА МЕЖДУ DEPENDENCY INJECTION И DEPENDENCY INVERSION PRINCIPLE ?

В ЧЕМ РАЗНИЦА МЕЖДУ DEPENDENCY INJECTION И DEPENDENCY INVERSION PRINCIPLE ?

Слайд 9

public class Chessboard
{
public Chessboard()
{
var reader = ServiceLocator.Instance.Get();
var parser

public class Chessboard { public Chessboard() { var reader = ServiceLocator.Instance.Get ();
= ServiceLocator.Instance.Get();
this.cells = LoadBoard(reader, parser);
}
}

DIP ЧЕРЕЗ SERVICE LOCATOR

Слайд 10

public class Chessboard
{
public Chessboard(
StreamReader input,
IBoardParser boardParser)
{
this.cells = LoadBoard(input,

public class Chessboard { public Chessboard( StreamReader input, IBoardParser boardParser) { this.cells
boardParser);
}
}

DIP ЧЕРЕЗ ИНЪЕКЦИЮ ЗАВИСИМОСТЕЙ

Слайд 11

Обеспечивается разными способами
Dependency Injection
Service Locator

DEPENDENCY INVERSION…

Обеспечивается разными способами Dependency Injection Service Locator DEPENDENCY INVERSION…

Слайд 12

Скрывает реальные зависимости класса
Ухудшается читабельность
Увеличивается хрупкость
Заражает весь код, в котором используется
Наркотик, с

Скрывает реальные зависимости класса Ухудшается читабельность Увеличивается хрупкость Заражает весь код, в
которого трудно слезть

ПОЧЕМУ SERVICE LOCATOR – АНТИПАТТЕРН?

Слайд 13

DI CONTAINER

DI CONTAINER

Слайд 14

public class Robot : IRobot {   public Robot(IDistanceSensor distanceSensor) {   this.distanceSensor =

public class Robot : IRobot { public Robot(IDistanceSensor distanceSensor) { this.distanceSensor =
distanceSensor;   }
... }
public class OpticalSensor : IDistanceSensor {
...
}
IRobot robot = container.Get();

Как это работает?

Слайд 15

public HttpServer(IEnumerable handlers) { … }
public FileLoader(IFileFormat[] formats) { … }
public DocumentPage(IAction[] actions) { … }

А ЕСЛИ ЗАВИСИМОСТЕЙ МНОГО?

public HttpServer(IEnumerable handlers) { … } public FileLoader(IFileFormat[] formats) { … }

Слайд 16

Controller(IView view) BasicView(IController controller): IView

А ЕСЛИ ЗАВИСИМОСТИ ЦИКЛИЧЕСКИЕ?

Controller(Lazy lazyView)
BasicView(IController controller) : IView
var c

Controller(IView view) BasicView(IController controller): IView А ЕСЛИ ЗАВИСИМОСТИ ЦИКЛИЧЕСКИЕ? Controller(Lazy lazyView) BasicView(IController
= container.Get();

Слайд 17

var createMyClass = container.Get>();
MyClass c = createMyClass(42, “!”);
https://github.com/ninject/Ninject.Extensions.Factory/wiki

ФАБРИКА ВМЕСТО

var createMyClass = container.Get >(); MyClass c = createMyClass(42, “!”); https://github.com/ninject/Ninject.Extensions.Factory/wiki ФАБРИКА ВМЕСТО NEW
NEW

Слайд 18

Время жизни (InSingletoneScope, InThreadScope)
Именованные зависимости (Named)
Контекстно-зависимое инжектирование (WhenInjectedInto)
Конвенции и авторегистрация (FromThisAssembly ...)
Модульность

Время жизни (InSingletoneScope, InThreadScope) Именованные зависимости (Named) Контекстно-зависимое инжектирование (WhenInjectedInto) Конвенции и
конфигурации
Одна реализация для нескольких интерфейсов (Bind)
Generics
...

ПРОЧИЕ ОСОБЕННОСТИ

Слайд 19

В программе FractalPainter странно реализован Dependency Inversion…
Необходимо произвести рефакторинг по списку в

В программе FractalPainter странно реализован Dependency Inversion… Необходимо произвести рефакторинг по списку в README.md ЗАДАЧА FRACTALPAINTER
README.md

ЗАДАЧА FRACTALPAINTER

Слайд 20

Можно внедрять контейнер постепенно
Контейнер должен использоваться в одном месте, а не заражать

Можно внедрять контейнер постепенно Контейнер должен использоваться в одном месте, а не
код
Контейнер подходит для разных ситуаций
Bind to Class, Bind to Constant, Bind to Method
Singleton Scope, Factory, Lazy
When
Conventions

РАЗБОР ЗАДАЧИ FRACTALPAINTER