87
Инструментируй это Роман Дворнов Avito Минск 2015

Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

  • Upload
    others

  • View
    19

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментируй этоРоман Дворнов

AvitoМинск 2015

Page 2: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Работаю в Avito

Делаю SPA

Автор basis.js

Я…

За любую движуху, кроме голодовки ;)

Page 3: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

DEMO поговорим про боль и немного интриги

Page 4: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование кода

Page 5: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

«под инструментированием понимают возможность отслеживания или установления

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

записывать информацию для отслеживания причин их возникновения…»

5

en.wikipedia.org/wiki/Instrumentation_(computer_programming)

Page 6: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• Трассировка

• Отладка

• Регистрация событий

• Подмена кода

• Счетчики производительности

• ...

6

Области применения

Page 7: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это
Page 8: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Code coverageПример №1

Page 9: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Как узнать что исполнялось?

9

function foo(a) { if (a > 5) { return 1; } else { return 2; }}

Оригинальный код

Page 10: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Как узнать что исполнялось?

9

function foo(a) { if (a > 5) { return 1; } else { return 2; }}

function foo(a) { __visit(1); if (a > 5) { __visit(2); return 1; } else { __visit(3); return 2; }}

Оригинальный код Трансформированный код

Page 11: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

API (runtime)

10

var __count = [0, 0, 0, ...]; // столько нулей, сколько // частей в коде, которые // нас интересуют!

window.__visit = function(idx) { __count[idx - 1]++;};

Упрощенная версия

Page 12: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

После выполнения тестов в __count будет

необходимая информация

11

Page 13: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Пример результатов

12

__count = [3, 3, 0]

функция исполнялась 3 раз

ветка if исполнялась 3 раза

ветка else не исполнялась

Покрытие кода ~67%

Page 14: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

13

Проецируем данные на исходники

Page 15: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• трансформация оригинального кода

• запуск тестов

• агрегация данных или визуализация

• PROFIT!!!

14

Code coverage: все вместе

Page 16: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• трансформация оригинального кода

• запуск тестов

• агрегация данных или визуализация

• PROFIT!!!

15

это и есть инструментирование (делается автоматически)

Code coverage: все вместе

Page 17: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Не стоит путать с другими типами трансформаций, например, транспиляцией

16

Page 18: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Транспиляция – преобразование код в равнозначный код, например, ES6 → ES5

17

en.wikipedia.org/wiki/Source-to-source_compiler

Page 19: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование – дополнение кода другим кодом,

который делает что-то еще

18

Page 20: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование = код, добавляющий код в код

19

Page 21: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование = код, добавляющий код в код

19

Page 22: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

LoupeПример №2

Page 23: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Визуализация того, как работают некоторые части в JavaScript

(call stack, event loop, callback queue)

21

latentflip.com/loupe(там есть видео доклада, рекомендую)

Page 24: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

DEMO

22

Page 25: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• Инструментируем код

• отправляем код в Web Worker, где он исполняется

• по мере исполнения, в основной процесс отправляются сообщения о том, что происходит – это визуализируется

• немного «магии» ;)

23

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

Page 26: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

React Hot Loader

Пример №3

Page 27: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Модификация React-компонентовв реальном времени

25

gaearon.github.io/react-hot-loader/

Page 28: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

DEMO

26

Page 29: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• Достаточно сложно объяснить в двух словах

• Ключевое:

• исходный код инструментируется

• патчатся классы компонент

• подменяются методы классов при изменении исходного кода и делается полный re-render

27

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

Page 30: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Ищем концы

Пример №4

или с чего все начиналось

Page 31: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Начальная идея

29

Имея ссылку на объект уметь определять местоположение

фрагмента кода его декларации

Page 32: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это
Page 33: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

DEMO

31

Page 34: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

!

• Не завязано на фреймворк/библиотеку

• Библиотеки могут расширять возможности и предоставлять дополнительную информацию

32

Главное – идея

Page 35: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

33

За пределами браузера

Браузер dev-server

Редактор

ФайлКоманда в терминале

Запрос на открытие файла

Инструментированный код + source maps

Page 36: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Части решения

34

• Инструментирование кода

• Runtime API

• Инспекция DOM дерева

• dev-сервер

Page 37: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование

Page 38: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

36

Код КодAST (ESTree)

Парсинг

Трансформации (Babel)

Трансляция

Esprima

Делаем трансформацию кода правильно

Page 39: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

36

Код КодAST (ESTree)

Парсинг

Трансформации (Babel)

Трансляция

Esprima

Делаем трансформацию кода правильно

Просто добавь свой плагин

Page 40: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование делается плагином для Babel

37

github.com/restrry/babel-plugin-source-wrapper

Page 41: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Что делает плагин

38

var foo = $devinfo(function(a, b) { return a + b;}, { … });!

var obj = $devinfo({ foo: 1 }, { … });

var foo = function(a, b) { return a + b;};!

var obj = { foo: 1 };

Page 42: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Делается автоматическии только на этапе разработки

39

Page 43: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Runtime API

Page 44: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

41

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Page 45: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

42

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Используем WeakMap для хранения информации: - объекты как ключи - не трансформирует объекты - не создает утечек памяти

Page 46: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

43

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Основная функция регистрации, "добавляет" информацию только если ее еще нет у объекта

Page 47: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

44

window.$devinfo = (function() { var map = new WeakMap(); var api = function(ref, data) { if (!map.has(ref)) map.set(ref, data); return ref; }; api.get = function(ref) { return ref ? map.get(ref) : undefined; } return api;})();

Основное APIУпрощенный код

Получение информации, используется инструментами

Page 48: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

45

var obj = {};!

$devinfo(obj, { data: 123 });!

console.log($devinfo.get(obj));// > { data: 123 }

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

Page 49: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Возможность хранить информацию, можно

использовать для других задач

46

Page 50: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

DEMO

47

github.com/lahmatiy/t8

Page 51: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инспектирование DOM

Page 52: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• знать границу компонента, т.е. определять элемент-контейнер компонента (DOM узел)

• определять владельца компонента (view) по элементу-контейнеру (по DOM узлу)

49

Для инструмента нужно

Page 53: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• если у DOM узла есть свойство __view – значит это контейнер компонента

• в свойстве __view хранится ссылка на view

50

Решение в лоб

Но лучше использовать WeakMap (node ➝ view)

Page 54: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Крохотный патч для Backbone

51

!

var _setElement = Backbone.View.prototype._setElement;Backbone.View.prototype._setElement = function() { _setElement.apply(this, arguments); this.el.__view = this;};

Page 55: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Или с WeakMap

52

!

var map = new WeakMap();var _setElement = Backbone.View.prototype._setElement;Backbone.View.prototype._setElement = function() { _setElement.apply(this, arguments); map.add(this.el, this);};window.getBackboneViewByNode = function(el) { return map.get(el)};

Page 56: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Готовые решения

Page 57: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

54

Работает из коробки (нужен basis.js 1.5)

basis.js

Page 58: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

component-inspector

55

github.com/lahmatiy/component-inspector

Другие фреймворки

npm install component-inspector --save-dev

Page 59: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

React

56

Подключение в html перед React!

<script src="node_modules/component-inspector/dist/react.js">

</script>

<script src="react.js"></script>

Page 60: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Backbone

57

Подключение в html после Backbone<script src="backbone.js"></script>

<script src="node_modules/component-inspector/dist/backbone.js">

</script>

Page 61: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Свое решение? Запросто!

58

Page 62: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

59

!

<script src="node_modules/component-inspector/dist/base.js"></script>

Инициализация

<script> initComponentInspector({ // просто добавь API });</script>

Page 63: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

60

Описываем API initComponentInspector({ isComponentRootNode: function(node) { return Boolean(node && node.__view); }, getInstanceByNode: function(node) { if (node) { return node.__view; } }, … });

Page 64: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Можно определить многое

61

• isComponentRootNode(node) • getComponentNameByNode(node) • getInstanceByNode(node) • getInstanceRootNode(instance) • getInstanceClass(instance) • getInstanceLocation(instance) • ...

github.com/lahmatiy/component-inspector#api-free-build

Page 65: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

dev-сервер

Page 66: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• отдавать инструментированный код

• исполнять команды, например, открытие файла в редакторе

63

dev-сервер должен

Page 67: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

64

Вариант настройки: webpackИнструментирование webpack + babel + babel-plugin-source-wrapper !

Открытие файла в редакторе express или webpack-dev-server + express-open-in-editor

Page 68: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

65

Пример конфигурации для Webpack + React

tinyurl.com/pwj6bln

Page 69: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Вариант настройки: basisjs-tools

66

> npm install basisjs-tools -g> npm install basisjs-tools-instrumenter// создать конфиг basis.config> basis server

{ "plugins": [ "basisjs-tools-instrumenter" ] }

Сервер будет отдавать инструментированный код и встраивать необходимое в html

Page 70: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

• open-in-editornpm пакет для программного открытия файла в редакторе github.com/lahmatiy/open-in-editor

• express-open-in-editor расширение для Express для открытия файла по урлу github.com/lahmatiy/express-open-in-editor

• extract-code-fragment получение раскрашенного фрагмента кода из файла скоро

67

Побочные продукты

Page 71: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Проблемки

Page 72: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

69

Проблема №1«Захламляется» код

Page 73: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

70

Решение: Source maps

Page 74: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

71

Проблема №2Runtime API мешает отладке

Page 75: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

72

Решение: Blackbox Script

Page 76: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

73

Проблема №2Показывается не то место

Page 77: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

74

function createObj() { return $devinfo({ example: true }, { loc: "lib.js:…" });}

var obj = $devinfo(createObj(), { loc: "app.js:…"});

lib.jsapp.js

Нам нужно это место Но покажется это

Page 78: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

75

require('babel-plugin-source-wrapper')({ blackbox: [ "/path/to/lib.js" ]})

blackbox: [ "/bower_components/**", "/node_modules/**"]

По умолчанию:

Решение: blackbox в инструментере

Page 79: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

76

function createObj() { return $devinfo({ example: true }, { loc: "lib.js:…", blackbox: true });}

var obj = $devinfo(createObj(), { loc: "app.js:…"});

lib.jsapp.js

Решение: blackbox в инструментере

Теперь будет показываться это место

У такой информации меньший приоритет

Page 80: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

77

Проблема №4«Зашумляется» стек вызова

Page 81: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

78

ХотимВидим

Page 82: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

79

Решение: магия :)$devinfo(function()  {      …  },  {  …  })

($devinfo)(function()  {      …  },  {  …  })

Page 83: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Заключение

Page 84: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Инструментирование – метод, расширяющий возможности

разработки

81

Page 85: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Местами это сложно, но безумно интересно!

82

Page 86: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Попробуйте! Интересно, что получится у вас ;)

83

Page 87: Instrument that WSD · Инструментируй это Роман Дворнов ... Нам нужно это место Но покажется это

Вопросы?

84

Роман Дворнов @rdvornov [email protected] github.com/lahmatiy

tinyurl.com/wsd-ciComponent Inspector