Как стать автором
Обновить
159.67
JUG Ru Group
Конференции для Senior-разработчиков

«При работе над инспекциями кода встречаешь Java-паззлеры каждый день»: Тагир Валеев о работе над IntelliJ IDEA

Время на прочтение 10 мин
Количество просмотров 11K


Одни знают Тагира lany Валеева по его докладам о Stream API, другие — по хабрапостам, третьи — по работе над статическим анализом кода (в проектах FindBugs и HuntBugs). А с августа он работает в JetBrains над IntelliJ IDEA, и это на многое повлияло: анализом кода он теперь занимается именно там, и его следующий доклад (на приближающихся JPoint и JBreak) будет как раз о создании инспекций кода в IDEA. Мы расспросили Тагира о том, каково разрабатывать проект, в котором разрабатывают всё остальное.

— Как ты начал работать над IDEA? Сам был активным пользователем и хотел развивать инструмент, или причины были совсем другими, и до этого сидел вообще в Eclipse/NetBeans?

— До работы в JetBrains я IDEA почти не пользовался. В основном сидел в Eclipse. Иногда приходилось работать в NetBeans, потому что мы писали RCP-приложение на нём.

Я хотел работать над анализом Java-кода, а для этого IntelliJ IDEA — идеальное место. Раньше я двигал FindBugs, потом начал писать свой статический анализатор байткода для Java HuntBugs, но всё-таки понятно, что в IDEA огромный пласт работы уже сделан, а главное — не придётся всё тащить самому. Приятнее делать что-то уникальное, а не догонять других. Ну и, конечно, анализатор кода, изначально интегрированный с IDE, гораздо более полезен, потому что часто можно сделать quick-fix, который в один клик исправляет проблему в коде. Просматривать вывод FindBugs (даже если он интегрирован с IDE) и исправлять всё вручную существенно ленивее. В результате люди перестают вообще заботиться о статическом анализе, даже если он у них выполняется на build-сервере.

— Существуют и случаи, когда анализ удобнее как раз без IDE — например, разработчик хочет быстро проверить пришедший ему чужой код. В ситуации, когда FindBugs завяз в легаси, а тебе теперь не до HuntBugs, есть ли ощущение, что при всём удобстве анализа в IDE также остаётся незаполненная ниша?

— Да, согласен, тут есть некий провал. Анализ кода в IDEA можно запустить из командной строки, не поднимая UI, кроме того, она интегрируется с TeamCity и UpSource. Но, насколько мне известно, интеграции с Jenkins или тупо maven-плагина нету. Можно было бы сделать хотя бы для IDEA Community Edition, где не встаёт вопрос проверки лицензии, но, по-моему, сейчас для компании это не является приоритетом. Более того, интеграция с IDEA — это selling point TeamCity и UpSource. С другой стороны, это выглядит несложной задачей. В принципе, любой энтузиаст мог бы подружить IDEA Community Edition и Jenkins, многие бы от этого только выиграли. Было бы удобно, если бы на любой пулл-реквест или коммит рисовалась табличка в Jenkins, где бы показывались новые и исправленные проблемы в коде.

— Работать над IDEA — это такой метауровень, «разрабатывать главный инструмент разработки». И поэтому у человека «изнутри» любопытно спросить: а чем на практике такая разработка отличается от обычной?

— Да, тут есть интересные особенности. Конечно, и в других случаях бывает, что разработчик сам пользуется проектом, который разрабатывает. Но при разработке IDEA это доведено до максимума. Обычно я обновляю основную инсталляцию IDEA каждый день или через день (это упрощает JetBrains Toolbox) с ночной сборки и работаю с самым свежим кодом, который сам вчера написал. Некоторые разработчики обновляют инсталляцию специальным скриптом прямо с текущего кода, выкачанного локально. Это помогает отлавливать многие баги до того, как их увидят внешние пользователи, или понять, что новая возможность не очень удобна. Ну и в целом приятно пользоваться тем, что сам сделал. К примеру, я писал несколько улучшений для плагина DevKit, который помогает разрабатывать саму IDEA или плагины к ней. На следующий день самому становится удобнее работать.

— А при работе над инспекциями ты ощущаешь, что они завтра же принесут тебе пользу при работе над следующими? И применяете ли их активно для рефакторинга уже существовавшего кода?

— Существующий код стараемся не трогать массово без необходимости, чтобы не усложнять историю git и не сломать то, что и так работает. Мне лично некоторые вещи хотелось бы применить глобально. Скажем, цикл с удалением элементов из коллекции по условию довольно неплохо заменяется моей инспекцией на Collections.removeIf, который не только короче и понятнее, но и, к примеру, для большого ArrayList работает существенно быстрее, чем удаление итератором. Итератор будет при удалении каждого элемента сдвигать внутренний массив, а removeIf сдвинет всё один раз. Если я начинаю трогать код, который давно никто не трогал, я, конечно, стараюсь его упростить, и инспекции мне в этом помогают.

Не все из моих инспекций пригождаются лично мне при разработке нового кода, потому что, если инспекция заменяет неоптимальный код на более оптимальный, мне проще сразу написать более оптимальный. Другие могли просто не знать, что есть более оптимальный вариант, но я-то знаю, раз инспекцию сделал. Тем не менее, преобразования стримов в циклы и циклов в стримы иногда помогают. Не всегда очевидно, какой вариант кода проще и красивее. Скажем, написал я стрим посреди метода и обнаружил, что он захватывает две изменяемые переменные. Менять код так, чтобы они стали неизменяемыми, неудобно. Скопировать их перед стримом в новые переменные некрасиво, лучше уж цикл. Ну я и воспользовался инспекцией, развернув стрим в цикл.

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

— В случае с инспекциями контринтуитивные запросы от пользователей нам особо не мешают: можно ведь сделать две инспекции, одна заменяет A на B, а другая заменяет B на A, и пусть пользователи решают, что им нравится. Многие действительно не любят или не понимают стримы и им приятнее развернуть стрим, написанный коллегой-хипстером, в цикл. Но есть и объективные недостатки у стримов: некоторых операций просто нет, труднее отлаживать, трудно кинуть проверяемое исключение или модифицировать локальную переменную. Скажем, написали вы стрим и тут поняли, что вам нужен досрочный выход по условию. Операция takeWhile появится только в Java 9, сторонние библиотеки вроде StreamEx босс использовать не разрешает. А тут в два клика можно стрим превратить в цикл и дописать нужный break. В общем, я глубоко убеждён, что это полезная фича.



— В недавнем выпуске «Без слайдов» Максим Шафиров признавал, что догфудинг при своей пользе для JetBrains всё же ограничен: одни проблемы ощущаешь на собственной шкуре очень хорошо, но на другие лично не натыкаешься. Часто ли ты сталкиваешься с ситуациями, когда люди используют IDEA совершенно не так, как ты, а в итоге им нужно такое, о чём ты и не догадался бы? Насколько тебе помогает опыт предыдущей работы, где ты сам видел IDE не с того же ракурса, что сейчас?

— Я часто вижу, что люди пишут исключительно странный код. Пишут три вызова методов там, где можно написать один. Пишут десять строчек, снимая лишнюю копию с коллекции, там, где можно написать три строчки и не копировать. Это видно по запросам в YouTrack (вот, например, недавно закрывал такой), по коду, который я вижу на GitHub, и даже по коду IDEA, который пишут другие разработчики. Видимо, многие программисты выучили несколько API-методов или классов и пытаются все задачи свести к ним. В этом плане очень полезно читать чужой код, потому что мне бы и в голову не пришло написать так странно. Видишь очевидную глупость в чужом коде, которую IDEA не подсвечивает — возникает мысль написать новую инспекцию.

Мне в некотором смысле помогает опыт работы в Eclipse. В целом у него Java-tooling заметно хуже, чем у IDEA, но это не значит, что он хуже по всем фронтам. Некоторых штук после Eclipse мне очень не хватает и, возможно, кое-что я сделаю, без чего страдаю.

— Ты активно общаешься с другими разработчиками (сидишь в чатике «Разбора полётов», твитишь, пишешь хабрапосты), и зачастую темой обсуждений становится как раз IDEA. Такое общение помогает в работе над ней, или это для души?

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

— Когда ты начал смотреть на IDE изнутри, оказалось ли что-то сюрпризом? Например, когда сначала годами думаешь «что ж вот это так по-идиотски сделали» — а потом внезапно обнаруживаешь, что есть веская и неочевидная причина.

— Что-то не припомню таких примеров. Я думаю, если что-то для пользователя выглядит по-идиотски, это нельзя оправдывать особенностями архитектуры. Лучше пусть внутри будет не очень красиво, снаружи-то IDE видит гораздо больше людей, чем изнутри.

— Когда выходит новая версия IDEA, люди бурно обсуждают бросающиеся в глаза вещи: подсказки с названиями параметров, недавнюю смену иконок и так далее. А как для тебя это выглядит изнутри: «все обсуждают вершину айсберга, не замечая главного», или это действительно и есть основное из происходящего?

— Трудно сказать, какое изменение главнее. Которое больше всего ускорило работу пользователя? На которое мы потратили больше всего времени? Которое вызвало самые восторженные отзывы? Конечно, делается и много вещей, которых никто не видит. К примеру, постоянно продолжается работа над разгрузкой UI-потока (Event Dispatch Thread) и разделением логики и отображения. Ещё в 2016.3 можно было взять блокировку на запись файла в UI-потоке, а потом, не снимая её, вывести UI-диалог. Взятие блокировки может подразумевать ожидание, пока файл отпустит другой поток. Сейчас с этим поборолись: write-lock’и в UI-потоке брать запрещено. Разумеется, пришлось перелопатить много кода, который пытался выводить UI во время блокировки: где-то удаляли лишние write-lock’и, где-то выносили UI-код из них. На это ушло много человекочасов, но пользователь заметит только небольшое увеличение отзывчивости IDE. Что тут бурно обсуждать?

— Кстати, любопытно спросить о смене иконок: а у тебя самого от неё какие ощущения?

— Я, если честно, ничего не заметил, потому что я не был пользователем IDEA. Либо новые иконки появились во внутренних билдах до моего прихода в компанию, либо это произошло в течение первых недель, за которые я не успел привыкнуть к старым.

Честно сказать, я не знаю, почему люди уделяют так много внимания иконкам. Во время работы в IDE я смотрю на код, а не на иконки. Чтобы открыть класс или файл, я не шарюсь в дереве проекта, а пользуюсь горячими клавишами вроде Ctrl+E, Ctrl+N, Ctrl+Shift+N. В дерево с иконками я иногда смотрю, когда создаю новую директорию или новый файл (хотя часто проще скопировать существующий файл через F5, ввести новое имя и удалить содержимое). Тулбар у меня скрыт, в меню я тоже обычно не залезаю, предпочитая Ctrl+Shift+A и ввод действия текстом (или конкретную горячую клавишу). Я пользуюсь IDEA недавно и, вероятно, ещё не оптимально. Думаю, со временем я буду видеть иконки ещё реже. Пусть они будут хоть в стиле Windows 3.1, мне особой разницы нет.



— К вопросу о том, что JetBrains активно пользуются своими собственными продуктами: а вот какие при работе над IDEA используются продукты не от JetBrains?

— Ну git, например. Используется Confluence, например, для публикации EAP’ов и для некоторых внутренних целей. Java не от JetBrains. Профилировщики какие-нибудь. Ну, веб-браузер…

— За 16 лет проекты неизбежно обрастают легаси-проблемами, мешающими двигаться вперёд. Какие у вас предпринимаются меры для борьбы с этим?

— В коде IDEA не всё так плохо. Гораздо больше хорошо, чем плохо. Есть очевидные проблемы (например, с API для плагинов). Кое-что нелогично раскидано по проекту. Но это всё не порастает мхом, а регулярно освежается. Меры обычные: порефакторить здесь, порефакторить там.

— В продолжение предыдущего вопроса: а каково вам живётся со Swing-интерфейсом в 2017-м, когда Atom и Visual Studio Code делают вообще на Electron? Это мешает или нет?

— Я почти не занимаюсь UI и вряд ли знаю о серьёзных сложностях в нём. Знаю, что многие проблемы Swing (например, отсутствие поддержки HiDPI) JetBrains активно исправляет в своём форке JDK. У меня есть некоторое предубеждение по поводу UI на HTML/JS, хоть и всё сейчас на нём. Там слишком много свободы, что ли, слишком мало порядка. Помню, в кулуарах Joker 2015 ребята из JetBrains обсуждали мысли переписать UI на JavaScript, а Никита Липский их отговаривал. Если я правильно понимаю, сейчас такой разговор уже активно не ведётся — значит, в принципе со Swing пока можно жить.

— Сейчас всё чаще слышно о Language Server Protocol — а вы в этом не видите смысла участвовать, или всё ещё может измениться?

— Не думаю, что это на сегодня приоритетное направление, но всё может поменяться. Запись в трекере на эту тему, конечно, есть.

— Известно, какую большую роль играет Stack Overflow в роли обычного разработчика. А с такими задачами, как у тебя, он оказывается полезен или нет?

— Я редко в работе нахожу ответы на Stack Overflow. Обычно на вопросы, в которых я совсем новичок. Скажем, понадобится мне поправить gradle-скрипт. Я их никогда не писал, но тысячи людей писали, поэтому тут Stack Overflow мне наверняка в чём-то поможет. А если я в чём-то уже неплохо разбираюсь, у меня обычно вопросы такие, на которые проще выяснить ответ другими способами. Например, заглянув в исходники или документацию: если предмет для меня не нов, я скорее всего уже примерно представляю, куда смотреть.

— На JPoint и JBreak ты выступишь с докладом о Java-инспекциях в IntelliJ IDEA — а можешь уже сейчас привести какой-то пример того, о чём собираешься рассказать там?

— Например, вы пишете инспекцию, которая предлагает использовать Map.getOrDefault, где это возможно. Скажем, у вас есть такой код:

public Number get(Map<String, Number> map) {
    return map.containsKey("foo") ? map.get("foo") : 0.0;
}


Инспекция предложит его заменить на такой:

public Number get(Map<String, Number> map) {
    return map.getOrDefault("foo", 0.0);
}

Здесь всё нормально, результирующий код правильный и семантически эквивалентный исходному. Итак, вы нашли в исходнике тернарный оператор, выяснили, что условие — это map.containsKey, map имеет тип java.util.Map, в истинной ветке map.get, квалификатор у map.containsKey и у map.get — одна и та же переменная, аргумент map.containsKey и map.get — одно и то же «чистое выражение», а в ложной ветке константа. Тогда мы подчёркиваем код и предлагаем заменить его на map.getOrDefault, где первым аргументом аргумент map.get, а вторым — константа из ложной ветки. Что мы не учли? Где Java может нам подложить свинью? На каком коде такая инспекция сломается? Вот подобные вопросы мы и будем разбирать в моём докладе.

— На JPoint 2016 ты с Барухом Садогурским и Евгением Борисовым представлял Java-паззлеры (и на JPoint 2017, возможно, будет продолжение). Многие воспринимают паззлеры как «это любопытные курьёзы, но на моей работе они редко сказываются» — а на твоей, получается, сказываются часто и сильно?

— При работе над инспекциями кода эти паззлеры каждый день. Любая инспекция может напороться на нетривиальный случай, когда применение квик-фикса делает код некомпилируемым или, что хуже, тихо без предупреждения меняет его семантику. Надо хорошо знать язык, чтобы подумать об этом до того, как начнут жаловаться пользователи. Разработчик IDE, конечно, должен знать все потайные уголки спецификации языка.



Если вы не видели прошлогодние выступления Тагира на московской JPoint и новосибирской JBreak, рекомендуем — зрители оценили их высоко:


Следующие JPoint и JBreak, где Тагир выступит с докладом об инспекциях, пройдут в апреле — а уже с 1 февраля билеты на них подорожают. Так что, если после интервью захотелось увидеть целиком его выступление и другие доклады этих конференций, сейчас самое время действовать.
Теги:
Хабы:
+36
Комментарии 10
Комментарии Комментарии 10

Публикации

Информация

Сайт
jugru.org
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Россия
Представитель
Алексей Федоров