
Источник
На Frontend Conf 2018 Алексей рассказал, как потеряв кучу времени сейчас, в конечном счете его сэкономить потом. Этот доклад не о чувстве скуки и не о том, как бороться с монотонными и рутинными задачами, а о том как потратить время по максимуму — сколько есть, все потратить, и посмотреть, что из этого получится. В расшифровке доклада опыт написания инструментов для отладки, тестирования, оптимизации, скафолдинга и валидации под разные проекты. Бонусом Алексей расскажет о ряде уже существующих инструментов и о пользе, которую они приносят. Давайте выяснять, надо ли вообще на это тратить время.
О докладчике: Алексей Охрименко — разработчик в Avito Frontend Architecture, где немного улучшает жизнь миллионов людей. Ведет подкаст «5 min Angular», а в свободное ото сна и подкаста время организует Angular Meetup вместе с ребятами из Тинькофф, и выступает с огромным количеством разных и спорных докладов.
Где можно потерять время?
Нулевой шаг — купить Mac/iMac и тут же начать терять время, или поставить Linux на ноутбук и потерять в нем вообще все рабочее время, меняя конфиги. Также очень рекомендую начать с Gentoo.
Есть 8 пунктов, на которые мы можем потратить время.
- Терминал.
- Проектирование.
- Создание проекта.
- Кодогенерация.
- Написание кода.
- Рефакторинг.
- Тестирование.
- Отладка.
Приступим к основательной потере начав по порядку.
Терминал
Где на терминале можно потратить наше время, чтобы потерять все? Организуйте рабочее пространство — создайте папки «Моя работа», «Мои хобби-проекты» и раскладывайте все в них. Поставьте себе Homebrew, чтобы устанавливать дополнительный софт, который еще будет упомянут.

Поставьте iTerm2, а дефолтный терминал на Mac — выкиньте.

Поставьте дополнения, например, oh-my-zsh, которые идут вместе с набором очень крутых плагинов.

Поставьте tmux — terminal multiplexer. Это программа для терминала, которая позволяет в одном окне открыть несколько окон и дополнительно поддерживать сессию. Обычно, если вы закрыли терминал, все ломается и заканчивается, а tmux будет продолжать работать, даже если вы все выключили. Если не разу с tmux не работали — рекомендую обзор от Студии DBMS.

Прописывайте aliases. Каждый раз, когда в терминале вы написали что-то больше одного раза — напишите себе alias, пригодится. Два раза — уже много, обязательно будет третий, шестой и десятый.

Поставьте дополнительные инструменты, например, jmespath или сокращенно — jp. Его можно установить через brew и делать интересные query-запросы в JSON-файлы.
brew tap jmespath/jmespath
brew instal jp
К примеру, у вас лежат packed JSON-файлы, вы можете по всем пройтись и узнать какие версии React в ваших приложениях и проектах.

Автоматизируйте свою работу — не открывайте одни и те же файлы много раз!
А теперь поговорим куда это все потратить. Все, что выше — это небольшая потеря времени, потерять больше можно в Shell Scripts.
Shell Script
Это язык программирования, в основном для bash, со своим синтаксисом.
#!/bin/bash
for dir in ‘ls $YOUR_TOP_LEVEL_FOLDER’;
do
for subdir in ’Is $YOUR_TOP_LEVEL_FOLDER/$dir’
do
$(PLAY AS MUCH AS YOU WANT);
done
done
Язык полноценный — некоторые люди создают игры и веб-серверы, что делать не советую. Я рекомендую всю работу, на которую затратили время, потратить еще раз и написать все это полноценно в файле. Зачем? Все знакомые девелоперы, которые давно работают в индустрии, просто создают себе свой GitHub репозиторий для конфигураций, и размещают туда конфигурацию для своего TMUX — terminal multiplexer, Shell Scripts для инициализации.

Зачем тратить еще кучу времени на то, что уже один раз сделано? Затем, что вы перейдете на другую работу, вам поменяют компьютер на работе, сгорит материнская плата и вы будете снова тратить день-два-три, чтобы настроить environment. Когда у вас есть такой репозиторий, настройка и установка всего займет 10 минут.
Проектирование
Обычно все сразу очень воодушевлены: «Да, проектирование! UML-диаграммы!», но когда я говорю слово UML вслух, многие знакомые программисты замечают:
— В 2018?! Что с тобой? UML — это страшный пережиток прошлого. Зачем ты откапываешь труп? Брось лопату!
Но UML очень полезен. Например, на Scrum-митинге Java-разработчик слушает, как Python-программисты обсуждают архитектуру бэкенд-фичи. Он грустно потирает голову и понимает, что ничего не понимает, а просто теряет час своего времени. Java-разработчик не может взаимодействовать с Python-программистами — не скажет, как писать код, использовать классы, миксины или что-то еще. Он просто не участвует в деле. В нашей компании есть JavaScript, Python и Lua. В моменте 2/3 людей скучают: сначала одни 2/3, потом другие. Эту проблему решает UML.
UML — это универсальный абстрактный визуальный язык для проектирования систем, который позволяет игнорировать особенности языков.
Приведу два моих любимых примера.
Sequence Diagrams
Эти диаграммы помогают показать историю взаимодействия во времени.

По вертикальной оси Y вниз идет временная зависимость: сначала получаем запрос на аутентификацию, потом даем ответ, и дальше кладем что-то в логи. По горизонтальной оси X происходит уже непосредственное взаимодействие между героями — участниками какого-то события.
Лично я периодически использую Sequence Diagrams для описания аутентификации процесса в приложениях. При этом я, JS-разработчик, нахожу общий язык с бэкендом Python, Lua и Java. Мы все друг друга понимаем и знаем, как в результате будет работать код, и не заморачиваемся по поводу конкретной реализации того или иного языка.
Class Diagram
Эти диаграммы тоже очень полезны. В JavaScript есть классы, в чем смысл диаграмм? Но есть же TypeScript, и с его помощью можно получить интерфейсы, абстрактные классы — полноценное представление конечной архитектуры.

Минута проектирования экономит неделю кодинга.
PlantUML
Я пользуюсь Java-библиотекой PlantUML. С ней вы можете использовать некий непростой dsl, в котором указать, к примеру, что List наследуется от AbstractList, Collection — от AbstractCollection, а также взаимодействие, агрегирование, свойства, интерфейсы и все остальное.
@startuml
abstract class AbstractList
abstract AbstractCollection
interface List
interface Collection
List <|— AbstractList
Collection <|— AbstractCollection
Collection <|— List
AbstractCollection <|— AbstractList
AbstractList <|— ArrayList
class ArrayList {
Object[ ] elementData
size()
}
enum TimeUnit {
DAYS
В результате получу конечную диаграмму.

Все это работает хорошо, есть плагины для Visual Studio Code.
Есть еще одно интересное приложение.
StarUML
Мы рисуем простейшую диаграмму: здесь есть базовый класс, от которого наследуется тестовый класс.

Дальше используем StarUML. Он стоит не слишком дорого и умеет экспортировать в Java. Инструмента, который бы UML-диаграммы экспортировал в TypeScript-код, нет, но мы можем экспортировать как раз с помощью StarUML в Java-код.

JSweet
Потом применим JSweet — библиотеку, которая позволяет конвертировать Java-код в TypeScript или JavaScript-код.

Java-код…
import java.until.*;
/**
*
*/
public class BaseClass {
/**
* Default constructor
*/
public BaseClass(){
}
/**
* some attribute
*/
protected String baseAttribute;
}
… с помощью JSweet конвертируем в TypeScript-код:
/* Generated from Java with JSweet 2.0.0 — <a href="http://www.jsweet.org/">http://www.jsweet.org</a> */
/**
* Default constructor
* @class
*/
class BaseClass {
public constructor) {
this.baseAttribute = null;
}
/**
* some attribute
*/
baseAttribute : string;
}
BaseClass["_class«] = «BaseClass»;
Здесь есть дополнительный параметр
_class
— это особенность работы Java, подобное можно удалять. В результате мы получили готовый boilerplate TypeScript-кода из диаграмм — базу, на которой можно работать. Причем эта база спроектирована и ясна всем.Тратить время на проектирование UML однозначно стоит.
Создание проекта
Кто конфигурирует Webpack каждый раз и создает webpack-config в новом проекте — ребята, что с вами?! Все хорошо? Вам нужна помощь? Если вас держат в заложниках — напишите координаты в комментариях, мы вышлем вертолет спасения.
Самый простой способ избежать подобного и каждый раз не конфигурировать одно и то же — это создать общий репозиторий на GitHub локально или поднять GitLub CI, склонировать этот репозиторий, зайти в него и удалить папку git.
git clone something
cd something
rm -rf .git
Теперь у нас есть эталонный проект, из которого клонируем. Таким подходом можно получить очень дешевый Bootstrapping.
Yeoman — deprecated. Slush — deprecated
То, что Yeoman deprecated — слишком самоуверенно. Он не deprecated, просто его все меньше и меньше используют, как и Slush. Это два одинаковых инструмента, просто с разной базой: Yeoman — это Grunt и кодогенерация. Slush — это Galp и кодогенерация.
Несмотря на то, что инструменты интересные, сейчас чаще используются другие.
Angular CLI, Create React App, Vue CLI
Кто работает с Angular — используют Angular CLI. Create React App — кто работает с React. Vue CLI — любители Vue.JS.
Большинство уже пересели на эти инструменты. Один из главных аргументов, почему стоит работать именно с CLI — это унифицированность. Если вы забудстрэппили ваш проект с помощью CLI, то уверены, что человек, который придет после вас, будет знать структуру проекта: команды, фичи, что можно запускать end-to-end и юнит тесты. Эти инструменты очень хороши.
Стоит ли тратить время на bootstrapping проектов именно с помощью CLI, а не Yeoman? Да, не сомневайтесь.
Кодогенерация
У нас есть некая кодовая база. Обычно, когда запускаем проект, мы создаем сначала Routing, а потом Redux — как же без него? В каждом фреймворке есть специализированный инструмент кодогенерации. В Angular — это CLI Schematics. Во Vue CLI — отдельная секция для генерации плагинов Vue CLI plugins: можно в секции плагинов сгенерировать некий код для наших проектов.
Redux CLI
Я хочу остановиться на React и Redux CLI, потому что из моей практики кодогенерацией меньше всех занимаются именно React-программисты и на это больно смотреть. Каждый раз, когда люди создают одни и те же файлы и жалуются, что с Redux тяжело работать, надо создавать кучу всего. Так есть уже инструменты!
Это Redux CLI, который за вас создаст dock-файл, в котором будут и эффекты, и редьюсеры, и соответствующие экшены, и «глупые» компоненты, и «умные» компоненты. Дополнительно вы можете сгенерировать свои компоненты или кодовую базу с помощью Redux CLI. Ставится Redux CLI просто, вы можете как создать проект с его помощью, так и проинициализировать уже в готовом, например, созданном с помощью Create React App.
npm i redux-cli -g
blueprint new <project name>
blueprint init
blueprint g dumb SimpleButton
Есть еще один универсальный инструмент, который не зависит от фреймворка — Plop.
Plop

Я узнал о нём недавно. Plop делает тоже самое, что и предыдущий: проинициализировав этот инструмент, можно создать все необходимые базовые компоненты. Указываете из каких компонент состоит ваше приложение и просто генерируете их. Так вы не тратите время на создание основной кодовой базы. Имея user story и спецификацию можно нагенерировать базовый функционал, тесты, основные стили — сэкономите огромное количество работы.
Все инструменты придется настраивать — я периодически настраиваю под React Blueprint, делаю свою библиотеку компонентов, но это время окупается.
Написание кода
Здесь будет банальщина.
Code snippets
Code snippets позволяют написать небольшой фрагмент, ключевое кодовое слово, и получить готовый кусок функционала. Например, можно создать Angular-компонент, написав
@Component
.
Для React и Vue есть такие же code snippets.
С банальными code snippets есть проблема. Чем профессиональнее разработчик, тем меньше он использует code snippets — просто потому, что уже знает, как всё пишется и ему лень их создавать. Он уже запомнил, как пишется этот компонент.
Напомню, наша цель — потратить время, при этом не сделав ничего полезного. Поэтому садимся и пишем code snippets. Здесь можно потратить бесконечно большое количество времени, и цель будет достигнута.
Лично мне snippets пригодились, когда я работал с i-bem.js:
modules.define("button<i>«,</i> [«i-bem-dom»], function(provide, bemDom) {
provide(
bemDom.declBlock(
this.name,
{
/* методы экземпляра */
},
{
/* статические методы */
}
)
);
});
В этой декларации нет ничего сложного, но синтаксис не похож ни на Angular, ни на React, ни на Vue, и его очень тяжело запомнить первые сто раз. На сто первый запоминается. Я мучался, потратил кучу времени, и потом начал массово создавать эти компоненты просто за счет того, что использовал code snippets.
Для тех, кто работает с WebStorm, это не сильно полезно, просто потому, что в нем нет такой большой экосистемы плагинов и, в основном, всё включено изначально — это полноценный IDE.
VScode extensions / VIM extensions
С редакторами Visual Studio Code и VIM ситуация другая. Чтобы получить от них какую-то пользу, надо ставить плагины. Чтобы найти все хорошие плагины и поставить их можно потратить несколько суток — плагинов безумно много!

Я убил на их поиск безумное количество времени, что и вам рекомендую. Можно сидеть часами, искать, смотреть на них, на красивые анимированные гифки — чудо! Напишите в комментариях, если хотите, чтобы я поделился всеми, что у меня есть.
Есть инструменты, которые автоматически подсвечивают complexity кода, какие тесты проходят, какие нет, когда прямо в коде видно причину непрохождения, какой код прошел или нет, автокомплиты, автопрефиксеры — всё это в плагинах.
Здесь можно потратить очень много времени, и мы нашей цели достигнем. Конечно, плагины немного не относятся к написанию кода, но представим, что они помогают нам его написать.
Рефакторинг
Это моя любимая тема! Причем настолько, что у меня есть отдельный доклад про рефакторинг: «Рефакторинг — Где? Куда? Когда? Откуда? Почему? Зачем и Как?» Я в нем подробно рассказываю что это такое и как с ним работать.
Сразу предупреждаю, рефакторинг — это не то, что вы обычно себе представляете. Обычно под этим подразумеваются: «Я улучшил кодовую базу и добавил новую фичу». Это — не рефакторинг. Если у вас сейчас когнитивный диссонанс — посмотрите доклад и он пройдет.
AngularJS Grunt -> webpack
Про рефакторинг хочу рассказать одну поучительную историю. У нас был очень старый AngularJS-проект, который собирался с помощью Grunt банальной конкатенацией. Проект был написан во времена первой и второй версий Angular. Соответственно, там все было очень просто: файлы конкатенировались, потом uglify, и все. В какой-то момент мы поняли, что надо переезжать на Webpack. У нас огромная legacy кодовая база — как ее перевести на Webpack?
Мы сделали несколько интересных заходов. Первое — обратились к библиотеке lebab.io.
Lebab.io
Эта библиотека позволяет конвертировать код из ES5 в ES6, причем очень хорошо. Она берет старую кодовую базу и превращает ее в новую: вставляет импорты, использует новые строки, классы, выставляет
let
и const
правильно — все делает за вас. В этом плане очень хорошая библиотека.
Мы поставили этот плагин, прогнали код файла через Lebab.io. После этого просто взяли шаблоны Mustache и код, который под новый Angular 1.6 и 1.5 с компонентным подходом, выглядел по-другому. С помощью регулярок мы вытащили необходимые куски, с помощью Mustache отрендерили наш шаблон по-другому и прошлись циклом по всем нашим файлам.
var object_to_render = {key: «value», ...};
fs.readFile(path_to_mustache_template, function (err, data) {
if (err) throw err;
var output = Mustache.render(data.toString(), object_to_render);
fs.saveFileSync(path_to_mustache_template);
}):
В результате мы сконвертировали огромное количество legacy кода в современный формат и быстро подключили Webpack. Для меня лично история очень поучительная.
Jsfmt
Это инструмент, который позволяет форматировать кодовую базу и искать по ней не обычным поиском, а семантически. Мы подключаем нашу библиотеку, файловую систему, считываем файл и хотим что-то найти. Ниже абстрактный пример, мы сейчас работаем с Angular.
var jsfmt = require(‘jsfmt’);
var fs = require(’fs’);
var js = fs.readFileSync(’component.js’);
jsfmt.search(js,"R.Component(a, { dependencies : z })").map((matches, wildcards) => {
console.log(wildcards.z);
});
Так выглядит наш запрос:
<b>R.Component</b> (a, { dependencies: z })
R/Component
— это собственная библиотека R
и некий Component
.Эта часть выглядит очень странно:
R.Component<b> (<u>a</b></u>, { dependencies: <b><u>z</b></u> })
Это не похоже не валидный JavaScript — и так и есть. Мы вставляем маленькие буквы, как плейсхолдеры, и говорим Jsfmt, что нам не интересно, что там находится: объект или массив, строка или boolean-значение, null или undefined — не важно. Нам важно получить ссылки на a и z, после чего, когда мы пройдемся по всей кодовой базе, найдем все варианты z. К примеру, мы можем найти все зависимости у этого компонента. Благодаря этому можно делать сложные рефакторинги.
С помощью инструмента мне удалось отрефакторить огромную кодовую базу семантическим подходом с помощью деревьев и анализа.
Мне не пришлось писать сложные запросы, сложные регулярки или парсить синтаксическое дерево — я просто сформировал запрос и указал, что на что поменять.
Два дополнительных инструмента
В рефакторинге есть простая вещь, про которую я должен сказать. Если вы хотите что-то отрефакторить, то в Visual Studio Code выделите код, и появятся подсказки и варианты рефакторинга, которые есть. К примеру, extract-метод, inline-метод.

В WebStorm есть контекстное меню, которое можно вызвать с помощью комбинации клавиш в зависимости от конфигурации, и отрефакторить кодовую базу.

В целом, у WebStorm большее количество команд, он сейчас более развит, чем Visual Studio Code.
Тестирование
Теперь самое интересное и воодушевляющее:)
Selenium IDE
Сначала небольшая история. Пришли ко мне как-то тестеры и говорят:
— Мы пишем end-to-end тесты, хотим автоматизировать их, и у нас есть Selenium IDE.
Selenium IDE — это просто плагин для Firefox, который записывает ваши действия в браузере. Он запоминает все ваши шаги — клики, скроллы, вводы, переходы, и эти шаги вы можете проиграть заново. Но это еще не все. Можно заэкспортировать то, что вы записали, например, в Java или в Python, и запустить автоматизированные end-to-end тесты с помощью Selenium IDE.
Звучит супер, но на деле Selenium IDE сам по себе работает не идеально, и к тому же на тот момент у нас еще был ExtJs.
ExtJs
Если у вас был ExtJs — сочувствую и обнимаю. Selenium IDE записывает всегда самый уникальный селектор. На наших элементах — это id. Но ExtJs для каждого элемента генерирует рандомный id, не знаю зачем. Эта проблема у ExtJs идет с нулевой версии.
ExtJS = <div id="random_6452"/>
В результате наши тестеры с утра открывали приложение, записывали все, потом, не перезагружая страницу, периодически прогоняли ее, пытаясь понять, сломался ли бэкенд, к примеру. Они обновляли бэкенд, а фронтенд не трогали. Главное было — не нажать refresh, потому что после этого генерировался новый id.
Тут же тестерам пришла одна гениальная идея. Selenium IDE умеет экспортировать свои записи в HTML-формат — мы же умеем работать с HTML, у нас есть шаблонизаторы — давайте попробуем это сделать!
Google Chrome Extension
Быстро создали Google Chrome-расширение и тут же нашли шикарный метод
elementFromPoint
. document.elementFromPoint(x, y);
Банально записывая движение мышки на окне и вызывая потом elementFromPoint, когда срабатывал клик, я находил координаты элемента, на который кликал. Дальше обязательно нужно было создать некий селектор, как-то выделить конкретно этот элемент. Id пользоваться нельзя — что же делать?
Пришла идея — дополнительно вешать на компоненты специальные test-id. Для компонента создавался абстрактный тестовый id, который был нужен только для тестов.
data-test-id="ComponentTestId«
Он генерировался только в тестовом окружении и по нему мы делали
select
по data-атрибуту. Но этого не всегда хватало. К примеру, у нас есть компонент, но внутри еще есть div
, span
, icon
, иконка в i-теге. Что с этим делать?Для этого «хвоста» мы дополнительно генерировали
XPath
:function createXPathFromElement(elm) {
var allNodes = document.getElementsByTagName(’*’);
for (var segs = [ ]; elm && elm.nodeType = 1; elm = elm.parentNode)
{
if (elm.hasAttribute(’class’)) {
segs.unshift(elm.localName.toLowerCase() +
’[a)class = «’ + elm.getAttribute(‘class’) + ‘ »] ‘);
} else {
for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
if (sib.localName = elm.localName) i++; };
segs.unshift(elm.localName.toLowerCase() + ’[’ + i + ’]’);
};
};
return segs.length ? ’/’ + segs.join(’/’) : null;
};
В результате формируется уникальный XPath-селектор, который состоит, в успешном случае, из data-атрибута селектора по data-атрибуту с названием компонента:
<b><u>.//*[@data-test-id=’ComponentName’]</b></u>/ul/li/div/p[2]
Если внутри компонента была еще какая-то сложная структура, дополнительно по строгому XPath все выделялось — без id. Мы избегали id, потому что работали с ExtJs.
Этот XPath можно было легко протестировать. Мы все записывали, экспортировали обратно в HTML-документ, загружали обратно в Selenium IDE и прогоняли.

Мы создали Chrome Extension, который просто генерировал формат записи Selenium IDE, но по-своему, не так, как это делает Selenium IDE. Там же мы добавили много умных проверок прокрутки спиннера, успешной загрузки приложения — добавили дополнительные нюансы, которые Selenium IDE не учитывает. Благодаря этому у нас появились полностью автоматизированные end-to-end тесты.
Единственное, что после этого оставалось сделать тестерам — открыть любую версию приложения, кликнуть, загрузить в Selenium IDE, проверить, сохранить это как Python-код, радоваться повышению зарплаты и премии и говорить мне «спасибо».
Для unit-тестов не могу обрадовать людей из React и VueJS сообществ — простите! Я не знаю о подобных инструментах для React и VueJS — возможно, они и есть. Обрадую только тех, кто с Angular.
SimonTest
Существует плагин SimonTest в Visual Studio Code для Angular.

Если вам нужно написать unit-тест на ваш компонент — указываете на этот компонент и говорите сгенерировать каркас вашего unit-теста. После чего появится весь необходимый каркас:
- будут созданы все необходимые зависимости, они будут замоканы и указаны все необходимые свойства для корректного тестирования;
- будут созданы тесты на методы с базовой проверкой и базовым функционалом.
Останется лишь добавить проверку бизнес-логики и какой-то логики вашего компонента, или бизнес-логики вашего приложения в этот компонент. Просто нажав генерацию, мы получаем полноценный каркас для unit-тестов.
Потратьте время на тестирование — это будет на зря.
Отладка
Первые 80% времени в разработке не так страшны, как последние 80% в отладке.
Где на отладке можно потратить время, когда у нас нет еще исключений и проблем? Что на этом этапе можно интересного поделать и потратить кучу времени?
Chrome DevTools
Здесь мы можем проверить производительность, получить какие-то данные и отладить наш код, чтобы понять, как он работает в реальности, особенно если кодовая база старая.

Какие альтернативы Debugger вы знаете? Фулл-стек или бэкенд-программисты просто обязаны знать альтернативу, которую используют для отладки. Есть Profiler, но он больше для определения производительности, есть Dumps, но нас интересует работа в runtime, а есть инструмент именно для мониторинга, который позволяет понять, что происходит и что идет не так.
Tracing
Для начала — концепция трассировщика: записываются все события в реальном времени. В runtime записывается весь лог всего: произошел клик, который вызвал событие, после вызова события — promise, потом setTimeout, после setTimeout еще один promise. Все эти события ловит трассировщик.

Spy-js vs TraceGL
Изначально существовало два основных конкурента: Spy-js и TraceGL. Эти конкурирующие трассировщики могли в реальном времени показать, что происходит с программой. Отличие от Debugger в следующем: допустим, ваша кодовая база состоит из тысячи строк — сколько раз ее нужно проходить? Долго, тяжело, муторно — и вы не всегда сможете выловить баги.
Проблема отладчика, например, на многопоточном бэкенде — если вы начинаете блокировать, то некоторые вещи просто не находите. Если у вас многопоточная программа, которая делает deadlocks — вы не поймаете deadlock с помощью отладчика, потому что события будут приходить в другой последовательности.
В JS иногда происходит то же самое, поэтому трассировщики помогают. Они позволяют видеть реальную картину в реальном времени. Вы просто анализируете deadlocks и все.
Spy-js купил WebStorm, очистил репозиторий, новые версии больше не выкладываются. Изменения появлялись только в spy-js. TraceGL купил Mozilla. У разработчика были огромные планы, он обещал, что в Firefox появится супер-трассировщик. TraceGL был крутой, но потом, видимо, начальство решило внедрять новые фичи инкрементально и они так и внедряются до сих пор. Следов TraceGL в Chrome не видно и, скорее всего, не будет никогда.
Возрадуйтесь, обладатели WebStorm, потому что именно там есть Spy-js. Он настраивается очень легко: вы создаете некую конфигурацию Spy-js, запускаете ваш проект, после чего начинаете ловить все необходимые события в реальном времени и можете анализировать их. Дополнительно WebStorm предоставляет еще ряд интересных фич: он совместим с TypeScript, CoffeeScript, дополнительно показывает последние данные выполнения. Если вы прогнали код с помощью Spy-js, после того, как программа завершилась, можно посмотреть, какие переменные и какие значения были в ваших аргументах. В этом плане инструмент шикарный.
В любом новом проекте, в который приходил, я включал трассировщик и через 5 минут знал, как работает проект: архитектура, устройство, элементы взаимодействия, какие события происходят. Несколько минут — и я эксперт в любой кодовой базе, просто потому что в реальном времени видел и понимал, что происходит.
Что теперь у нас в арсенале?
- Мы потратили кучу времени на настройку и написание скриптов для терминала.
- Для проектирование мы потратили время на картинки, которые в результате мы все-таки превратили в код, но не в полноценный, а только в каркас бизнес-логики.
- Создание проекта. Мы соскафолдили проект с помощью инструментов.
- Кодогенерация — сгенерировали некоторое количество кода, базовые компоненты, то есть сделали черновую работу;
- Мы сами код не написали, но при этом все подготовили: поставили все плагины и сниппеты.
- На рефакторинге можно убивать бесконечное количество времени, и мы это сделали, но воспользовались умными инструментами — это немного не то, что я хотел.
- На тестировании хорошо потратили время — создали свой собственный тестовый рекордер.
- На отладку можно потратить столько времени, сколько хотим! Отлаживать можно бесконечно.
Зачем мы всё это делали? Процитирую профессионала из мультика «Крылья, ноги и хвосты»:
— Все равно ты не взлетишь! Запомни: лучше день потерять, потом за 5 минут долететь! Вперед!
Доклад Алексея — один из лучших на конференции 2018 года. Уже через пару недель пройдет Frontend Conf. в составе РИТ++. Понравилось? Присоединяйтесь! Приходите на Frontend Conf РИТ++ в мае, подписывайтесь на рассылку: новые материалы, анонсы, доступы к видео и больше крутых статей.
Опрос. Стоит ли тратить время на..
Комментарии (13)
JustDont
13.05.2019 12:50Статья, более чем наполовину состоящая из сомнительных рецептов.
> окружение операционной системы
Всё зависит от того, как часто вы меняете систему, и какова вероятность того, что под новый проект вам будет нужно примерно такое же окружение. Если вы меняете систему раз в несколько лет (насколько часто у тебя в рабочей машине горит матплата, %юзернейм%?) — писать конфиги будет так же эффективно, как и не писать: в следующий раз вам скорее всего придётся в конфиг всё равно посмотреть, чтоб убедиться, что всё там написанное всё еще актуально и нужно.
> проектирование
Единственный навык программиста, который тут нужен — это не UML рисовать. Это сказать обычным русским (английским) языком по белому, что ты тут собрался делать. Если этого навыка нет — диаграммы в достижении взаимопонимания в команде не помогут. Если есть — то диаграммы, а тем более конкретно UML — не обязательны, потому как не в них соль.
Генерация кода из UML в одну сторону — лично для меня выглядит бессмысленным времяпровождением. Вы сразу можете запроектировать всю архитектуру хоть сколько-нибудь сложного (difficult) модуля? И она у вас потом не меняется? А если меняется, то всё это рисование достаточно бессмысленно, несколько обновлений — и картинки уже не будут соответствовать коду. Вы хотите получить из картинок начальный объем кода? А почему бы сразу не написать этот начальный объем кода в виде кода? Другие люди не поймут? Как я выше сказал, тут главное — это способность пояснить ход своих мыслей на обычном русском языке, а прочитать черновые намётки интерфейсов на питоне и java-разработчик сможет, не надо выставлять его идиотом. Структуры и интерфейсы на большинстве языков выглядят довольно схоже.
Один из главных аргументов, почему стоит работать именно с CLI — это унифицированность. Если вы забудстрэппили ваш проект с помощью CLI, то уверены, что человек, который придет после вас, будет знать структуру проекта: команды, фичи, что можно запускать end-to-end и юнит тесты.
Для того, чтоб в проекте была команда билда и запуска — в проекте должна быть команда билда и запуска, а не CLI. Будет там или не будет CLI — дело десятое. Для того, чтоб в проекте можно было запускать end-to-end и юнит тесты — в проекте должны быть end-to-end и юнит тесты. А не CLI.
CLI — это не более чем стандартная обвязка, которая вам практически в 100% случаев не нужна вся, но вы её всё равно устанавливаете всю, потому что иначе нельзя. CLI не добавляет понимания, как это всё работает и что делают её отдельные составляющие, и если вы чем-то из CLI не умеете пользоваться и не пользовались — то «человек, который придёт после вас» не найдет после вас ничего. Просто потому, что находить будет нечего.
CLI — это диктатура определенного инструментария от людей, которые не у вас в команде и не решают ваши задачи. Вы можете её использовать, если вы детально понимаете, чем конкретно вы пользуетесь, и что это всё вам наилучшим образом подходит. Если не понимаете или не подходит, навязывание CLI — это просто карго-культ.
Каждый раз, когда люди создают одни и те же файлы и жалуются, что с Redux тяжело работать, надо создавать кучу всего.
Для меня это звучит как весомый повод не использовать Redux. Он не единственный, честно.
Писать бойлерплейт из-за выбранного инструмента, и жаловаться на это (и бороться с этим инструментами кодогенерации) — это, на мой взгляд, то же самое, что отстрелить себе ногу из дробовика, и, крича о том, что чё-то больно, разрабатывать механический костыль.k12th
13.05.2019 13:02Судя по тому, как вам не нравится CLI, вы использовали только create-react-app:)
JustDont
13.05.2019 13:11Нет, тут чуть другая история — я просто уже несколько раз был тем самым «человеком, который придёт после вас». Приходил, и… видел проект, созданный через create-react-app, в котором по факту почти все фичи create-react-app не использовались, а те что использовались — были сконфигурированы с очень печальным пониманием происходящего.
Такой уровень использования CLI работе не только не помогает, но даже еще и вредит. Причем очень заметно.k12th
13.05.2019 13:58Ну надо сказать что CRA очень не гибкий по сравнению с остальными инструментами, да и фичами не так чтоб богат. Поэтому впечатление складывается не очень.
JustDont
13.05.2019 14:04Ну как сказать… Ангуляр я совсем не уважаю, но дело с ним довольно серьезно имел, и дело с CLI ангуляра тоже — и я не вижу фундаментальных различий. Более того, CLI ангуляра — это вот как у автора статьи с редаксом, оно более богато на фичи и навороты, но эти фичи и навороты — они как раз для того, чтоб мужественно преодолеть проблемы, самим ангуляром и создаваемые (бойлерплейт, модульность, итд).
CRA куда проще и банальнее — именно потому, что сам реакт очень простой и банальный, там не надо колдовства и кодогенерации (по крайней мере пока вы редакс не притащили).
nrgian
15.05.2019 19:55Всё зависит от того, как часто вы меняете систему
Система может сдохнуть в самый разгар проекта, когда времени нет.
Лучше иметь под рукой способ.
Если же по вашему рецепту — то придется каждый раз полностью вспоминать с нуля. Это долго.
k12th
13.05.2019 13:01Я мучался, потратил кучу времени, и потом начал массово создавать эти компоненты просто за счет того, что использовал code snippets.
Для тех, кто работает с WebStorm, это не сильно полезно, просто потому, что в нем нет такой большой экосистемы плагинов <...>Но позвольте, в WebStorm точно так же можно создавать свои сниппеты "из коробки" с незапамятных времен, при чем тут плагины? Более того, там есть настраиваемые шаблоны для файлов.
obenjiro
13.05.2019 14:38Тут просто не достаточно хорошо выразил свою мысль. Главное в этом абзаце следующее
всё включено изначально — это полноценный IDE.
Просто хотел сказать что WebStorm нет особой необходимости искать и ставить плагины.
PS: сам предпочитаю VSCode. Легче работать с большим кол-вом проектов (5-10 одновременно открытых проектов между которыми постоянно переключаюсь)
poxvuibr
14.05.2019 12:00Я посмотрел выступление по поводу рефакторинга и там есть слова, что "Если делаете что-то неправильно и знаете об этом, то делайте это что-то одинаково неправильно везде, чтобы потом было легче рефакторить!". Я уж думал, что я один так думаю, было приятно встретить единомышленника.
questor
Ряд советов хороши, например, tmux — хорошее дело.
Есть ряд советов, которые не даны. Например, не упомянут «настройте один раз линтинг». Я бы сказал, что это вещь, которая очень сильно бесит и хочется плюнуть пока настроишь всю связку vscode с prettier для линтинга, но когда сделаешь — чувствуешь, как много ресурсов высвободилось.
И, не программистский совет: освойте слепой десятипальцевый набор.
obenjiro
Вот только сейчас понял, что для меня этот шаг казался супер очевидным, настолько, что даже не стал его упоминать. Но явно стоило :)