Есть такая штука как инструментирование кода. Мало кто знает о ней, даже пользуясь результатами ее применения. Между тем, с инструментированием можно делать много всего интересного и, главное, полезного. Например, это может вам помочь лучше понять код или сделать процесс разработки более эффективным. Примеры инструментирования кода и принципы его работы.
5. «под инструментированием понимают
возможность отслеживания или установления
количественных параметров …, а также
возможность диагностировать ошибки и
записывать информацию для отслеживания
причин их возникновения…»
5
en.wikipedia.org/wiki/Instrumentation_(computer_programming)
6. • Трассировка
• Отладка
• Регистрация событий
• Подмена кода
• Счетчики производительности
• ...
6
Области применения
9. Как узнать что исполнялось?
9
function foo(a) {
if (a > 5) {
return 1;
} else {
return 2;
}
}
Оригинальный код
10. Как узнать что исполнялось?
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;
}
}
Оригинальный код Трансформированный код
11. API (runtime)
10
var __count = [0, 0, 0, ...]; // столько нулей, сколько
// частей в коде, которые
// нас интересуют
!
window.__visit = function(idx) {
__count[idx - 1]++;
};
Упрощенная версия
15. • трансформация оригинального кода
• запуск тестов
• агрегация данных или визуализация
• PROFIT!!!
14
Code coverage: все вместе
16. • трансформация оригинального кода
• запуск тестов
• агрегация данных или визуализация
• PROFIT!!!
15
это и есть инструментирование
(делается автоматически)
Code coverage: все вместе
17. Не стоит путать с другими
типами трансформаций,
например, транспиляцией
16
23. Визуализация того, как работают
некоторые части в JavaScript
(call stack, event loop, callback queue)
21
latentflip.com/loupe
(там есть видео доклада, рекомендую)
25. • Инструментируем код
• отправляем код в Web Worker, где он исполняется
• по мере исполнения, в основной процесс
отправляются сообщения о том, что происходит –
это визуализируется
• немного «магии» ;)
23
Как это работает
29. • Достаточно сложно объяснить в двух словах
• Ключевое:
• исходный код инструментируется
• патчатся классы компонент
• подменяются методы классов при изменении
исходного кода и делается полный re-render
27
Как это работает
41. Что делает плагин
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 };
44. 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
Упрощенный код
45. 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 для
хранения информации:
- объекты как ключи
- не трансформирует объекты
- не создает утечек памяти
46. 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
Упрощенный код
Основная функция регистрации,
"добавляет" информацию только
если ее еще нет у объекта
47. 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
Упрощенный код
Получение информации,
используется инструментами
52. • знать границу компонента, т.е. определять
элемент-контейнер компонента (DOM узел)
• определять владельца компонента (view)
по элементу-контейнеру (по DOM узлу)
49
Для инструмента нужно
53. • если у DOM узла есть свойство __view –
значит это контейнер компонента
• в свойстве __view хранится ссылка на view
50
Решение в лоб
Но лучше использовать
WeakMap (node ➝ view)
59. React
56
Подключение в html перед React!
<script src="node_modules/component-inspector/dist/react.js">
</script>
<script src="react.js"></script>
60. Backbone
57
Подключение в html после Backbone
<script src="backbone.js"></script>
<script src="node_modules/component-inspector/dist/backbone.js">
</script>
69. Вариант настройки: basisjs-tools
66
> npm install basisjs-tools -g
> npm install basisjs-tools-instrumenter
// создать конфиг basis.config
> basis server
{
"plugins": [
"basisjs-tools-instrumenter"
]
}
Сервер будет отдавать
инструментированный код и
встраивать необходимое в html
70. • open-in-editor
npm пакет для программного открытия файла в редакторе
github.com/lahmatiy/open-in-editor
• express-open-in-editor
расширение для Express для открытия файла по урлу
github.com/lahmatiy/express-open-in-editor
• extract-code-fragment
получение раскрашенного фрагмента кода из файла
скоро
67
Побочные продукты
77. 74
function createObj() {
return $devinfo({
example: true
}, {
loc: "lib.js:…"
});
}
var obj = $devinfo(createObj(), {
loc: "app.js:…"
});
lib.jsapp.js
Нам нужно это место Но покажется это
79. 76
function createObj() {
return $devinfo({
example: true
}, {
loc: "lib.js:…",
blackbox: true
});
}
var obj = $devinfo(createObj(), {
loc: "app.js:…"
});
lib.jsapp.js
Решение: blackbox в инструментере
Теперь будет показываться
это место
У такой информации меньший
приоритет