"Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

28
Dependency Injection. Javascript. Сергей Камардин

description

Слайды доклада "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Transcript of "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Page 1: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Dependency Injection. Javascript.

Сергей Камардин

Page 2: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Задача из жизни

1. Разместить на карте зарегистрированных пользователей;

!

2

Page 3: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

«JS Way»Locator.prototype.locateUsers = function(users) { // Инициалиация сервиса карт loadScript("..."); client.init(...); ! // Создание карты var map = new client.Map(...); ! // Отображение на карте маркеров users.forEach(...); }

3

Page 4: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Задача из жизни

1. Разместить на карте зарегистрированных пользователей;

2. Поменять поставщика карт;

4

Page 5: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Решение: АбстракцияAbstractMapService.prototype = { ! createMap: function() { throw new TypeError("Not implemented"); }, ! createMapMarker: function() { throw new TypeError("Not implemented"); } !}

5

Page 6: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

ИмплементацияAbstractMapService.extend({ ! createMap: function(id, options) { // }, ! createMapMarker: function(map, options) { // } !});

6

Page 7: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Locator.prototype.locateUsers = function(users) { // Create map service // Could be an Fabric Method, Service Locator, DI var mapService = new ConcreteMapService(...); ! // Create map var map = mapService.createMap(...); ! // Run each users, making markers users.forEach(...); }

7

Page 8: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Single responsibility?Locator.prototype.locateUsers = function(users) { // Create map service // Could be an Fabric Method, Service Locator, DI var mapService = new ConcreteMapService(...); ! // Create map var map = mapService.createMap(...); ! // Run each users, making markers users.forEach(...); }

8

Page 9: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Проблемы

• Невозможно написать юнит тесты;

• Использование сервиса карт во многих местах в коде;

• Избыточная функциональность локатора;

• Reusability.

9

Page 10: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Задача из жизни

1. Разместить на карте зарегистрированных пользователей;

2. Поменять поставщика карт;

3. Перенести локатор в другой проект, как плагин.

10

Page 11: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

ResultLocator.prototype = { // injection setMapService: function(mapService) { this.mapService = mapService; }, ! locateUsers: function(users) { // Create map var map = this.mapService.createMap(...); ! // Run each users, making markers users.forEach(...); } }

11

Page 12: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

12

Page 13: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

ResultLocator.prototype = { // injection setMapService: function(mapService) { this.mapService = mapService; }, ! locateUsers: function(users) { // Create map var map = this.mapService.createMap(...); ! // Run each users, making markers users.forEach(...); } }

13

Вот оно

Page 14: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Routine// Create MapService var mapService = new MapService(...); !// Create Locator var locator = new Locator(); !// Inject mapService locator.setMapService(mapService); !// Use locator locator.locateUsers(users);

14

Page 15: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Inversion of Control

• Dependency Injection

• Service Locator

• Factory Method

IoC container:

15

Page 16: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Dependency Injection

• Constructor injection

• Setter injection

• Interface injection

16

Page 17: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Hard Coupling

17

Page 18: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Coupling

18

Page 19: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Loose Coupling

19

Page 20: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Плюсы• Каждый объект отвечает за свою функцию;

• Соблюден принцип инверсии зависимостей;

• Простая конфигурация объектов;

• Безболезненная смена имплементаций;

• Легко писать юнит тесты.

20

Page 21: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

dm.js

• Javascript Реализация IoC;

• Работает в node.js и браузере;

• Легко расширяется (любые загрузчики скриптов и Promise/A+ библиотеки);

• Простая конфигурация (в духе Symfony).

21

Page 22: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Конфигурация "locator": { path: "path/to/locator/implementation", calls: [ ["setMapService", ["@maps"]] ] } "maps": { path: "path/to/map/service/implementation", arguments: [{ id: "my-app-id" }] }

22

Page 23: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

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

dm .get("locator") .then(function(locator) { locator.locateUsers(users); });

23

Page 24: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Тестированиеit("should create map", function() { var mapStub, locator; ! mapMock = sinon .mock(new AbstractMapService) .expects("createMap") .once(); ! locator = new Locator(); locator.setMapService(mapMock); ! locator.locateUsers(...); ! mapMock.verify(); });

24

Page 25: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Syntax! "example": { "path": "...", "arguments": [{ "service": "@service", "method": "@service:method" "result": "@service:method[1,2,3]", "resource": "#path/to/my.tpl#", "path": "http://%{api_path}" "build": "build_no_#{file.txt}" }] } !

25

Page 26: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Альтернативы

• Wire.js

• Angular’s DI

• Тупо контейнеры

26

Page 27: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Где и для чего это можно использовать?

27

Page 28: "Dependency Injection. JavaScript.", Сергей Камардин, MoscowJS 15

Спасибо!

github.com/gobwas/[email protected]

Сергей Камардин