Андрей Старовойт

Андрей Старовойт

Темы
Неделя
Mar 30, 2020 → Apr 5, 2020

Архив недели @anstarovoyt

Понедельник


Всем привет! Меня зовут Старовойт Андрей @anstarovoyt и я разработчик @WebStormIDE в @JetBrains. На этой неделе расскажу вам о том, как мы работаем: о команде, об IDE, о поддержке языков и о том, как менялся веб за последние пять лет (с точки зрения разработчика IDE).

Чтобы не возникло недопонимания — я Java-разработчик и знаком с веб-разработкой именно со стороны поддержки в IDE. Многие вещи, которые я буду рассказывать про IDE, применимы не только к WebStorm, но и к другим редакторам, например VS Code. Так что интересно будет всем

А что бы вы хотели услышать от меня на этой неделе? У меня, конечно, есть план, но я могу его не придерживаться, если подписчиков интересуют совсем другие темы.

Для начала разберемся с понятиями. IDE — Integrated Development Environment. Если совсем простым языком, то это текстовый редактор, который понимает код и старается всячески помогать: проверяет его на ошибки, делает автодополнение при наборе текста, помогает быстро запустить

WebStorm — “JavaScript IDE by JetBrains”. На самом деле, языком JavaScript дело не ограничивается. Мы пишем поддержку связанных языков (TypeScript, CoffeeScript), популярных фреймворков (Angular, Vue, React), линтеров (ESLint, TSLint,) и многого другого.

Практически все IDE от JetBrains выросли из одного продукта Intellij IDEA — и представляют из себя некоторый набор плагинов. Поэтому, когда мы говорим о JS-поддержке в GoLand, IDEA, RubyMine, PhpStorm, PyCharm то это та же самая поддержка, которую предоставляет WebStorm

Архитектурно весь код WebStorm (и других упомянутых выше IDE) можно разделить на базовый (платформенный) и код, отвечающий за поддержку конкретных языков/технологий. Есть целая команда, которая занимается развитием и улучшением платформы

Весь платформенный код у нас открыт и лежит на гитхабе как часть IntelliJ IDEA Community Edition github.com/JetBrains/inte… (осторожно, Java!)

Про платформу и задачи, которые там возникают есть несколько очень крутых докладов Алексея Кудрявцева youtube.com/watch?v=YzWr9C… youtube.com/watch?v=Ra2RSs… Осторожно, Java! Правда в гомеопатических дозах.

Многие языковые фичи могут иметь общую часть. Возьмем, например, Postfix Completion. Есть общая часть, которая лежит в платформе: интеграция в автодополнение, обработка нажатия tab, UI.Есть часть, реализуемая для конкретных языков:темплейты и условия их разворачивания
notion image

Вторник


На мой взгляд самое крутое, что почти все IDE (плагины) лежат в одном репозитории, вместе с платформой. Нет никаких ограничений на изменения в платформе, любой может дописать в платформу недостающую функциональность (конечно, с некоторым предварительным обсуждением)

Сегодня хотел бы поговорить про поддержку языков в IDE. Можно выделить два подхода: Первый это — реализация парсера языка на стороне IDE, второй — интеграция с существующим компилятором

Понятно, что существуют еще некоторые промежуточные варианты, но про них я расскажу чуть позже

В WebStorm и других IDE от JetBrains мы обычно реализуем парсер языка. Имея на руках синтаксическое дерево, можно делать всевозможные умные вещи: писать рефакторинги, инспекции, подсветку кода (с учетом семантики кода) и так далее

Понятно, что только парсером дело не ограничивается. Мы практически пишем в IDE компилятор языка (в плане понимания семантики)

У написания собственного парсера есть свои плюсы и свои минусы (тред)

Полный контроль на реализацией: к примеру, мы можем написать парсер так, чтобы он было более толерантен к ошибкам. В этом примере "->" должно обрабатываться как минус и знак больше, но мы сделали так, чтобы парсер обрабатывал это умнее
notion image

Прямая работа с деревом: почти все рефакторинги требуют изменений на уровне дерева. Но если дерево есть только у компилятора, то и рефакторинги должны писаться либо на стороне компилятора, либо очень сильно интегрироваться с ним

Переиспользование кода: у нас есть платформенный код, который оперирует базовыми интерфейсами, общими для всех поддерживаемых языков. Благодаря этому многие фичи работают с минимальным вложением усилий. Например, так реализован "Flip comma", общий для всех языков
notion image

Кросс-языковая интеграция: к примеру, для JSX-тегов у нас отрабатывает полноценная поддержка HTML, включая инспекции и фиксы. Это работает, потому что дерево JS включает в себя поддерево с HTML тегами, такими же, как в обычных HTML файлах

- Боль и страдания: для новых синтаксических конструкций нужно менять парсер в IDE. Если новая версия языка выходит раз в несколько лет, то это не так страшно, но если каждые пару месяцев (подсказка, TypeS...), то это непрерывная гонка

- Высокая сложность: кроме парсера (что уже не тривиально) мы вынуждены реализовать вывод типов и логику разрешения ссылок. Все эти механизмы должны работать по правилам, которые заложены в компилятор (например, по спецификации языка)

🔥Тред (Старовойт Андрей)
Раз уж мы начали говорить о поддержке языков, расскажите какая языковая фича JavaScript/TypeScript вас больше всего удивила? Для меня после Java это возможность писать в "case" целые выражения. У нас даже инспекции работали неправильно, тк разработчик не ожидал такой подставы
notion image

Среда


Вторая вещь, которая меня сильно удивила несколько лет назад — это то, что метки можно использовать с любым statement, а не только для циклов. А еще оно работает в Java, чему я был удивлен вдвойне. Этакий “go to” курильщика
notion image

@jsunderhood Как попадают в разработку IDE? Это не самая распространенная предметная область
Разработка IDE такая же область, как и любая другая. Можно прислать нам CV и попасть в команду, если у вас достаточно опыта. Если говорить обо мне, то в какой-то момент я понял, что мне интересен статический анализ, а компаний, которые этим занимаются не так много в мире twitter.com/TheMishkun/sta…

Может у вас истории поинтереснее? @art_spb, @en_Dal, @alex_zolotov

Еще немного о поддержке языков. Как я уже писал выше, синтаксического дерева недостаточно для полноценной поддержки языка в IDE. Нужно также понимать семантику языка. Простой пример (TypeScript)
notion image

Чтобы обработать эту конструкцию нужно: Понимать, что test(1) это вызов функции Понимать, что эта именно та функция, которая определена строчкой выше Понимать, что после вызова этой функции мы обращаемся к объекту с типом {result: string}

В этом плане с TypeScript дело обстоит гораздо лучше, чем с JavaScript. В нем есть более-менее строгие правила разрешения ссылок. Для JavaScript же все может быть очень сложно. Начиная от обычной декларации парой строчек выше, заканчивая window["te" + [] +"st"] = (p) => {}

В TypeScript вы, конечно, тоже можете написать такой код, но компилятор его не поймет и покажет ошибку в месте обращения к этой функции. Правда, с TypeScript есть другая проблема: очень сложный механизм вывода типов

Для JavaScript мы по возможности стараемся использовать вывод типов TypeScript (например, если есть файл “.d.ts”). Кроме TypeScript, анализируем JSDoc с выводом типов аналогичным Closure Compiler и некоторые популярные шаблоны написания JavaScript

🔥Тред (Старовойт Андрей)
Для многих языков, помимо парсера и механизма вывода типов, мы еще реализовываем Control Flow граф. Этот граф позволяет отслеживать изменения состояния программы (Data Flow Analysis), благодаря чему появляется возможность писать целый новый класс умных инспекций
notion image

Интересный факт, что реализация CF графа для TypeScript и JavaScript полностью совпадает. Потому что TypeScript не привносит никакого дополнительного поведения в Runtime

CF граф также используется для Type Guard (механизма сужения типов) в TypeScript

Чуть подробнее о том, как строится граф и как используется в TypeScript я рассказывал вот здесь: youtube.com/watch?v=qddYQL…

Простой пример CF графа
notion image

🔥Тред (Старовойт Андрей)
Возвращаясь к вопросам синтаксиса языков. В TypeScript довольно развитая система типов. Используете ли вы Mapped type / Conditional type / Predicate type в своем коде? Написание ".d.ts" файлов не берем в учет 🙂

Четверг


Сегодня расскажу про команду и то, как мы работаем

Над WebStorm трудятся 16 человек. Помимо разработки и тестирования, есть еще Product Manager, Product Marketing Manager, Support Engineer’s, Tech Writer

Команда рассредоточена по разным локациям. Есть люди, которые работают в офисах Питера, Мюнхена, Амстердама. Один разработчик работает удаленно из Польши

Благодаря такой распределенности мы, на мой взгляд, довольно просто смогли перейти на удаленную работу. Нам ведь и раньше приходилось обсуждать многие вещи онлайн, и вся инфраструктура была более-менее к этому готова

В разработке сложились зоны ответственности. Мы их называем подсистемами. Каждой подсистемой, в зависимости от размера, занимается один или несколько человек. Поддержка простого фреймворка не трудозатратна, в то время как поддержка того же TypeScript требует очень много ресурсов

Но, конечно, никто не мешает тебе прийти в другую подсистему и сделать там хорошо (с код ревью)

Так же есть некоторая внутренняя ротация. Если тебе надоело заниматься чем-то одним, можно договориться о смене ответственного и уйти заниматься другой подсистемой

Для коммуникаций внутри и между командами мы используем в основном Slack. Некоторые команды уже перешли на Space

🔥Тред (Старовойт Андрей)
О, вспомнил еще один вопрос про синтаксис TypeScript. Используете ли вы namespace (раньше использовалось слово module)? Если да, то для каких целей? Почему не ES модули?

Пятница


О, вспомнил еще один вопрос про синтаксис TypeScript. Используете ли вы namespace (раньше использовалось слово module)? Если да, то для каких целей? Почему не ES модули?
Из ответов можно сделать вывод, что те, кто использует namespace, делают это для склеивания деклараций twitter.com/jsunderhood/st…

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

У нас открытый issue tracker, куда кто-угодно может прийти с жалобой или просьбой добавить новую фичу. В трекере есть возможность голосовать за задачи, и если мы видим, что какая-то задача собирает много голосов, мы понимаем, что это важная вещь для наших пользователей

Линк youtrack.jetbrains.com/issues/WEB вдруг кому интересно :)

В трекере 95% задач, над которыми мы работаем, открыты для всех, их можно посмотреть, покомментировать, проголосовать 5% – это что-то совсем внутреннее. “Порефакторить так-то класс" или что-то очень крутое, что мы не готовы анонсировать сразу

В этом плане все очень близко к тому, как разрабатываются Open Source проекты

🔥Тред (Старовойт Андрей)
В команде есть Product Manager Катя, которая старается следить за новостями в мире JavaScript. Она помогает решить, что нужно добавить поддержку новой технологии или инструмента в продукт. Или что конкретная задача более приоритетна, чем другие

Кроме того, у владельцев подсистемы обычно есть глубокое понимание всего, что в ней происходит. Исходя из этого понимания, разработчик сам может решать, что сейчас необходимо сделать какую-то задачу

Например, люди, которые занимаются поддержкой JavaScript, сами понимают, что нужно следить за предложенными фичами в ECMAScript (ECMAScript proposals) и поддерживать их в IDE, начиная с некоторой stage

Еще один источник информации это Developer Advocate’ы, которые часто делятся с нами обратной связью (либо своей, либо от пользователей)

И последнее, и на мой взгляд, очень крутое — это EAP (Early Access Program) Здесь будет небольшой тред о том, что это

EAP — это версия IDE, которой может воспользоваться любой желающий (там встроена лицензия на один месяц)

В активной стадии разработки мы стараемся выпускать EAP каждую неделю, прямо из девелоперской ветки (с некоторой предварительной проверкой, что эта версия работоспособна)

EAP-программы позволяют быстро протестировать новые фичи на небольшой группе пользователей и получить обратную связь, что нравится/не нравится

Кроме тестирования новой функциональности, EAP-версии также помогают быстро узнать о каких-то регрессиях

Благодаря EAP-ам пользователь может непосредственно влиять на то, как будет выглядеть фича в финальной версии

Многие пользователи предпочитают именно EAP-версии. Потому что кроме того, что они бесплатны, они всегда содержат самые последние фичи и самые последние баг-фиксы

Очевидные минусы: Сами версии ограничены по времени. Даже если у вас есть лицензия, вам придется обновляться через месяц. Билды могут быть нестабильными

У VSCode, кстати, что-то подобное называется Insiders

🔥Тред (Старовойт Андрей)
Если говорит про внутренние источник задач, то поскольку команда постоянно работает с продуктом, то у них тоже часто появляются идеи по улучшению

В JetBrains есть несколько frontend-команд, которые пользуются WebStorm и тоже дают обратную связь

Про то, откуда появляются задачи поговорили. Остался вопрос приоритетов. Основные факторы влияния: Актуальность и перспективность технологии Голоса в трекере Количество пользователей технологии Польза

Нужно понимать, что у нас в трекере тысячи задач и мы никогда не сможем закрыть их все. И дело не в том, что продукт состоит из одних багов, а в том, что есть огромное количество технологий, которые мы поддерживаем, и с годами их количество только растет

Поддерживая новую технологию, мы практически сразу получаем фидбек в несколько десятков bugs и feature requests

Иногда их статус неоднозначен: с точки зрения разработчика, он просто не поддержал какую-то функциональность (например, рефакторинг выключен для каких-то случаев), в то время как пользователь видит эту неполноту поддержки и считает это багом

Почему не делаем какие-то задачи* Нет уверенности о реальной потребности Слишком мало пользователей Противоречие с устоявшимися принципами Сложно сделать с текущей архитектурой *в конкретный момент времени Украдено из доклада Кати и Дениса youtube.com/watch?v=3FiU9b…

🔥Тред (Старовойт Андрей)

Суббота


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

Тот самый альтернативный способ — это использование некоторого Language Server, например, LSP (но им дело не ограничивается)

Тред про достоинства и недостатки Language Server

Универсальность. Написав сервер один раз, можно относительно легко добавить поддержку технологии в огромное количество редакторов

Один источник правды. LS обычно делается поверх компилятора, поэтому получаемые данные всегда согласованы с результатами компиляции

Изолированность. LS обычно представляет из себя внешний процесс, с которым IDE общается посредством некоторого интерфейса (например, stdout). Если процесс начал работать медленно, то это никак не влияет на работу редактора / поддержку других технологий

Простота. Это скорее относиться к LSP. Для базовой реализации сервера нужно написать поддержку всего 10-15 команд

- Изолированность (да, это еще и минус). Поскольку поддержка технологии “сама в себе”, то она ничего не знает о других языках, и как с ними взаимодействовать

- Ограниченность. IDE может получить только ту функциональность, которая есть в Language Service. Например, если LS не поддерживает переименование или рефакторинги, то и IDE не сможет этого делать

- Скорость. На запуск процесса и поднятие модели требуется довольно много времени. Коммуникация между процессами тоже не мгновенная

🔥Тред (Старовойт Андрей)
Есть еще одна тонкость, связанная с использование LS: обычно хочется, чтобы подсветка кода в редакторе была моментальная. Но с использованием LS добиться этого невозможно (опять же, из-за минуса "скорость"). Как решать эту проблему?

Под "подсветкой кода" я имею ввиду подсветку ключевых слов и других синтаксических элементов

Ответ такой: обычно есть какой-то отдельный механизм, отвечающий за синтаксическую подсветку. VSCode, например, использует модифицированные TextMate банды

Один из примеров использования LS у нас — это Dart. Протокол взаимодействия WS и Dart Analysis Server был разработан совместно с командой из Google, благодаря чему многие фичи специфичные для наших IDE работают в Dart. Например, Postfix Completion или In-place переименование

Но несмотря на то, что в Dart используется LS, там все же реализован парсер языка на стороне IDE, для решения вопросов подсветки и форматирования

В поддержке TypeScript мы получаем и показываем в редакторе сообщения об ошибках из TypeScript Language Server, но для рефакторингов и инспекций мы всегда используем собственную модель

Плавно переходим к вопросам поддержки фреймворков, на примере Angular

У Angular есть свой языковой сервис Angular Language Service.WebStorm какое-то время использовал Angular LS, но мы решили отказаться от него, в пользу собственной поддержки

Поддержка состоит из модель проекта и понимания синтаксиса

Модель проекта хранят информацию о модулях, компонентах и связях между ними. Благодаря этому могут работать такие фичи как автодополнение и автоимпорты компонента в модуль
notion image

Для понимания синтаксиса у нас написан специальный парсер шаблонов Angular. Парсер строит обычное HTML дерево, но с вставками из Angular атрибутов и интерполяций. Для HTML элементов у нас отрабатывает обычная поддержка HTML, для интерполяций модифицированная поддержка TypeScript

🔥Тред (Старовойт Андрей)
И небольшой опрос в предверии завтрашней темы разговора. Если вы используете Yarn, перешли ли вы на Yarn 2 (berry)
🤔 42.0% Использую Yarn 1
🤔 3.1% Перешел на Yarn 2
🤔 55.0% Не использую Yarn

Воскресенье


Сегодня я хотел бы поговорить о том, как менялись web-технологии за последние 5+ лет, в контексте разработки IDE

Логично начать разговор с JavaScript (точнее ECMAScript). Как вы думаете, что за язык на приложенной картинке?
notion image

Многие узнают ActionScript 3. Но на самом деле, это еще и ECMAScript 4, спецификация языка, которая так и не была выпущена. ES4 включал типы (номинативная типизация), классы, интерфейсы, пакеты (что-то вроде ES модулей, но идейно ближе к тому, что есть в Java)

В TS и ES6 используется немного другой синтаксис (без ключевого слова function)
notion image

Кроме ES4 также была спецификация ES4X, которая предлагала синтаксис работы с XML в JavaScript коде, подобный JSX в React
notion image

А теперь самое интересное: эти спецификации были написаны в 2003-2004 годах. Получается, что многие идеи, на которых строится современный web, появились еще 15 лет назад

А еще все эти скриншоты были сделаны в WebStorm, потому что WS поддерживает ES4 и E4X... Хорошо, что все это было не напрасно, и поддержка ES4 нужна еще и для ActionScript 3. У IDEA до сих пор есть некоторое количество пользователей, которые пишут с использованием Flex (Flash)

Наличие классов, интерфейсов, XML-выражений в ES4/E4X на начальных этапах помогло быстро добавить поддержку подобных фич для TS, ES6 и JSX. Но на данный момент от этого больше головной боли, чем пользы

Ну и для тех, кто не знаком с историей ES4: спецификацию сочли слишком революционной, и вместо нее приняли ES5. Часть фич, предложенных в ES4 была переработана и добавлена в ES6 (спустя 10 лет), а другая часть видимо никогда не будет реализована

🔥Тред (Старовойт Андрей)
Между ES4 и ES6 прошло больше 10 лет. Все это время разработчики пытались облегчить себе жизнь и самостоятельно сделать удобный синтаксис. Поэтому стали появляться разные языки и технологии, которые закрывали эту брешь. Из самых популярных: CoffeeScript Babel Отчасти TypeScript

Про TypeScript вроде все понятно, а вот про Babel и CoffeeScript хочу написать подробнее

Babel — это головная боль разработчика IDE. Любой может добавить в JavaScript недостающую ему синтаксическую конструкцию. И, конечно, IDE ничего не будет знать о ней, показывая ошибки парсинга

Все поддержать невозможно. Мы стараемся поддерживать самые популярные плагины и драфты спецификации ES, когда они выходят из Stage 1

🔥Тред (Старовойт Андрей)
CoffeeScript для меня язык-загадка. Его синтаксис довольно сильно отличается от JavaScript, но каким-то образом он очень быстро стал популярен. Возможно, это связано с его лаконичностью. Или с тем, что альтернативы в тот момент не было 🙂

Мой любимый пример популярности этого языка — вот этот pull request в Node.js "Use CoffeeScript!": github.com/nodejs/node-v0…

Понятно, что это шутка, но все же

Кроме того, у CoffeeScript были диалекты, развивающие его идеи: Coco LiveScript IcedCoffeeScript Этим не каждый язык может похвастаться

Cвою популярность CoffeeScript потерял примерно так же стремительно, как и набрал. Есть предположение, что просто появились более удачные альтернативы (TypeScript). Кроме того, часть фич появилась в нативном виде в ES6 Кстати, если вы не знакомы с его синтаксисом, вот пример:
notion image

В WS есть поддержка CoffeeScript, но до диалектов мы так и не дошли — популярность технологии сошла на нет. В 2017 года вышла версия 2.0 с поддержкой JSX и фичами ES6, но не сказать, что язык с тех пор стал сильно популярнее

🔥Тред (Старовойт Андрей)
Мы подошли к одной из главных революций в web. В 2015 году вышел ES6 (ECMAScript 2015). Кроме языковых фич был еще один революционный момент — уход от модели "пишем огромную спецификацию, согласуем 5-10 лет и выпускаем новую версию"

Теперь, язык релизится раз в год, и в него попадают все готовые на данный момент новые фичи

В настройках WS есть опция выбора версии языка (раньше пунктов было гораздо больше). Этот выбор нужен для того, чтобы пользователь случайно не воспользовался фичей, которая не входит в нужную версию. Например, классы в ES5
notion image

При новой модели этот список стал менее актуален, потому что реализация фичи (в Babel или в одном из браузеров, или в TypeScript) всегда появляется раньше, чем ее добавляют в спецификацию. Кроме того, часто мы точно знаем, что фича попадет в язык, но не всегда понимаем когда

Поэтому сейчас просто есть разделение “новые фичи ES6+”, ES5 и некоторые специфичные диалекты

С переходом на новую модель релизов появилась некоторая определенность в том, как и куда будет язык развиваться; какие фичи нужно поддержать прямо сейчас, а с какими можно повременить

🔥Тред (Старовойт Андрей)
Теперь небольшой тред про то, как я помню развитие Node.js

Я пришел в команду WS в 2014 из Java Enterprise разработки. Меня очень удивило, что такая экспериментальная технология как Node.js, оказывается, во всю используется при разработке в вебе. “Экспериментальность” технологии подчеркивала ее версия 0.xx

В наши дни, я думаю, даже самые ортодоксальные backend-разработчики знают, что весь веб использует Node.js для решения самых разных задач

У нас в кодовой базе можно проследить повышение популярности Node.js для разработки веба по тому, как постепенно часть Node.js плагина переползала в базовый JavaScript плагин

Сейчас Node.js плагин добавляет очень специфичные для Node.js разработки вещи, вроде run-конфигураций и дополнительных пунктов меню. Все остальное мы считаем необходимым для JS-разработки, неважно для какой платформы — web, mobile или Node.js

Наверно, один из поворотных моментов в развитии Node.js был кризис, связанный с появлением io.js

В двух словах, для тех, кто не знаком с этой историей: в конце 2014 часть людей из команды Node.js сделала форк из-за того, что Node.js практически перестал развиваться

Форк просуществовал не очень долго — примерно полгода. Но в результате этого Node.js вышел из версии 0.xx и стал развиваться гораздо быстрее

Нам в свое время пришлось оперативно добавить поддержку io.js, а потом так же быстро выпилить ее. Но я сегодня проверил, оказывается в кодовой базе до сих пор можно встретить код, связанный с io.js
notion image

🔥Тред (Старовойт Андрей)
Ну а теперь Looking forward to Deno Расскажите, что вы думаете о Deno? Пробовали / нет? Взлетит / нет?

@jsunderhood Мне всегда казалось (могу ошибаться), что популярность CoffeeScript была в первую очередь обусловлена его ролью языка-компаньона в Ruby on Rails. Ruby-разработчикам «непривычный и непохожий на JS синтаксис» был как родной почти. 🙃
Возможно, но мне казалось, что этим дело не ограничивается. Кстати, поддержку CoffeeScript у нас писала команда RubyMine twitter.com/shaukote/statu…

Моя трансляция подошла к концу. Спасибо всем, было интересно 🙂 С вами эту неделю был Старовойт Андрей @anstarovoyt из @WebStormIDE Если остались какие-то вопросы (или я что-то пропустил и не ответил), смело пишите мне в личный твиттер

В напутствие, обращаюсь к тем, кто использует наши IDE. По статистике только 20-30% пользователей используют одну из главных фич IDE “Quick Fix”. Не будьте такими, нажимайте Alt+Enter как можно чаще!
notion image

Ссылки