Что не так с ИДЕ
До меня дошло, что не так с ИДЕ. То есть, я и раньше их не любил, но по косвенным причинам. Они тормозные, много кнопок, требуют регистрации и подписки и все в таком духе. Но это только внешнее.
На самом деле, мое пренебрежение исходит от их убогого предназначения. Задача ИДЕ – научиться понимать код и угадывать, что хочет программист. Поясню на примере с PyCharm, де-факто ИДЕ для Питона.
Предположим, есть у меня файл “foobar.py” где сверху написано import
datetime
. Открываю его в ИДЕ. Запускается много-много Джава-кода, который
парсит файл грамматиками. В результате ИДЕ знает, что импортирован модуль
времени. Теперь каждый раз после "datetime."
(с точкой на конце) будет
появляться выпадашечка с функциями этого модуля.
Не уверен, что выражаюсь ясно, но все же: здесь мне видится некто третий
лишний. У меня есть Питон. Есть программа на Питоне. Если я загружу ее в
интерактивный сеанс ipython
, то получу полный контроль над системой. Что
загружено а что нет, на какие классы и переменные могу сослаться и так
далее. Автодополнение по табу будет работать идеально, потому что его отдает
интерпретатор. А он, в свою очередь, берет данные из памяти самого Питона. Он
последняя, самая надежная инстанция.
В самом деле, кто лучше знает, что там в Питоне загружено: процесс Питона или посторонняя Джава?
Но нет, мы пишем код на Джаве, который пытается делать это лучше каноничной реализации. Иногда нормально выходит, иногда полная лажа. Когда написано “import time”, ошибки быть не может. А вот пример с импортом в рантайме:
try:
import json
except ImportError:
try:
import simplejson as json
except ImportError:
from django.tools import json
Это махровый легаси с тех времен, когда в поставке Питона не было модуля json (и
его сишной реализации). Проходилось шерстить сторонние библиотеки в надежде
найти что-то у них (например, Джанго тащила за собой реализацию json
в недрах
utils
).
Предположим, у меня установлены все три библиотеки. Вопрос, на какой именно
остановится ИДЕ? Она вообще это распарсит? Предположим, да. Но опять-таки, это
не будет честное выполнение кода. Ведь ИДЕ не исполняет код в настоящем
интерпретаторе. Если я напишу "os.system('rm -rf')"
, ничего не удалится.
Я уж не говорю о динамических вещах типа подключение модуля в зависимости от аргументов командной строки. Или вызов функций из проприетарной dll. Все это случается в полете. На момент редактирования кода ИДЕ ни хрена об этом не знает.
Вы с подобным не сталкивались? Поздравляю, а у меня было. Такое программирование сводится к обезьяне: поправил – запустил – упало, поправил – запустил – упало. Прямо как первый скрипт на Перле.
ИДЕ это в общем случае убогое подобие интерпретатора, который парсит текст и
собирает смысл по крупицам. Этакий программист-даун. Он знает, что есть классы
Person
и PersonManager
и даже какие аргументы им передавать, но что случится
в процессе работы – не знаю, не научили.
Это костыль, который мы сами воздвигли.
Или вот Докер: ты не можешь запустить 10 строк на Js или Питоне, потому что зависимостей на 30.000 файлов. Вместо того, чтобы доработать платформу и компилировать один файл, мы запихаем все говно в контейнер на 200 мегабайт и ладушки.
Джава-разработчик не поймет зачем в проде Докер. Лисп-программист не поймет зачем нужна ИДЕ. Потому что с бородатых времен любая Лисп-система запускается как машина с состоянием. Подключаешься к ней из редактора, загружаешь в машину код и… чудо! Редактор знает о системе абсолютно все. На той стороне не поделка на Джаве, а сама система, процесс, где прямо сейчас вертится ваш код. А в отдельном окошке (REPL) можно прогнать какой угодно сценарий.
Словом, улучшать нужно не ИДЕ, а целевую платформу. Чем меньше коммерческих костылей ей нужно со стороны, тем она совершенней.
ИДЕ для Питона должна быть написана на Питоне и взаимодействовать только с Питоном. Это я не на конкретный ЯП взъелся, замените Питон на что угодно. Если язык не может покрыть свои же нужды, не стоит им заниматься.
По иронии, удачные примеры прямо под носом, но мы же такие гордые, над скобочками шутим. Результаты налицо.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter
Alex Yakushev, 4th Oct 2017, link
Все круто, только Докер и для Джава-програмиста полезен :).
Vladimir Bormotov, 4th Oct 2017, link , parent
Докер - это признание того, что отрасль никак не может придумать, что делать с dll-hell.
В прошлом веке над Майкрософтом все смеялись, а теперь бац - вот вам Докер.
Но ровно та же проблема и на десктопах - в линуксе уже придумали и внедряют системы пакетирования приложений, которые тоже суть еще один вариант "нет, мы не знаем как быть, давайте мы всё нужное нам сами притащим, тут сбоку оставим, и всем будет хорошо"
Sergey Serebryakov, 4th Oct 2017, link
Если мы с первого раза набело пишем всю программу сверху вниз, то, конечно, интерпретатор в любой момент времени знает, что сейчас в области видимости и какие там значения. Однако в реальности мы редактируем код то выше, то ниже, переставляем куски местами, прыгаем курсором туда-сюда, в том числе между файлами. Чтобы интерпретатор мог делать подсказки в таком сценарии, он должен помнить историю изменений состояния с начала исполнения и проматывать её в зависимости от того, где сейчас курсор. Для "чистых" языков с поддержкой explicit side effects это до некоторой степени возможно, но в "обычных" языках для сколько-нибудь нетривиальных программ (которые читают с диска, отправляют сетевые запросы, пишут в stdout) это нереализуемо. У статического анализа свои компромиссы (в частности потому, что задача останова нерешаемая), но, по-видимому, их можно терпеть и идти навстречу (в том числе делая языки более IDE-friendly).
Ivan Grishaev, 4th Oct 2017, link , parent
Я не о том совсем. Когда в Лиспе я правлю код, то одна комбинация -- и он улетает в Лисп-машину и обновляет то, что было раньше. В каждый момент времени у меня актуальные данные о том, что в системе. Не нужна никакая история.
Sergey Serebryakov, 4th Oct 2017, link , parent
Я Лисп, к сожалению, не знаю, рассмотрим Питон. Я написал такой код:
Он быстро исполняется и после него у меня msg = "success". Теперь я правлю check = result == 0. msg теперь определено? Если да, тогда состояние некорректно, потому что не соответствует тому, что написано в коде. Если нет, значит check перевычислился и исполнение программы продолжилось с новым значением. Когда он перевычислялся, использовалось значение result. Оно переиспользовалось с первого запуска или исполнило запрос? Если переиспользовалось, значит оно хранилось в истории, потому что в конце мы сделали del или могли ещё как-то изменить. Если исполнило запрос - а запрос вернёт совсем другое значение в этот раз.
Ivan Grishaev, 4th Oct 2017, link , parent
Я не понял, к чему этот пример. ИДЕ не сможет понять, что здесь происходит. Если б это был Лисп, и бы выполнил этот кусок в интерактивном сеансе и сразу бы увидел результат. Заодно проверил бы, как ведет себя increment_and_get_from_network -- кидает ли исключение или отдает nil, что пишется в лог и тд.
А как мне поможет ИДЕ в примере выше -- вообще не ясно.
Sergey Serebryakov, 4th Oct 2017, link , parent
Пример иллюстрирует мой вопрос к идее использования РЕПЛа вместо ИДЕ: какой именно результат мы увидим, если в интерактивном сеансе исполним код, а потом отредактируем строчку? Если ответ - это "весь код исполнится заново", то пусть вместо increment_and_get_from_network у нас drop_database, или launch_nuclear_strike, или просто очень медленная функция.
ИДЕ проведёт какой-никакой статический анализ и скажет, что у нас вроде как есть переменная msg типа string. А РЕПЛ будет грохать базу каждый раз.
r00ger, 4th Oct 2017, link
По иронии, тут у вас комменты на джаваскрипте пишутся
Ivan Grishaev, 5th Oct 2017, link , parent
Не вижу криминала.
Ivan Grishaev, 5th Oct 2017, link , parent
Это переменная Шредингера: она и есть и нет ее одновременно. Если при написании кода ниже ИДЕ будет говорить, что переменная доступна, то это косяк. Программист будет писать код будто она есть, и потом в проде бахнет.
Насчет исполнения кода. Думаю, очевидно, что подобный код должен быть завернут в функцию, а не лежать на верхнем уровне модуля. И потом, все решает окружение. Локальная база, сервисы заглушки. Ничего страшного в том, чтобы грохнуть локальную базу чтобы проверить функцию.
Ivan Grishaev, 9th Oct 2017, link , parent
Ну, прекрасно, это не касается главного тезиса о том, что в ИДЕ ограниченный скоуп.