IPFCP, ой, то есть ICFPC-2020

Ровно 11 часа назад закончился ICFPC 2020. Так как я предусмотрительно взял выходной на остаток дня, готовьтесь, сейчас буду РАССКАЗЫВАТЬ. Отчет за прошлый год тут.

Тэ минус семь дней

За неделю до соревнования организаторы начали выкладывать затравочки. Выглядели они примерно так:

Больше сообщений здесь.

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

Все это сопровождалось довольно милыми инсценировками от лица сотрудников вымышленной уральской обсерватории. Примерно такими:

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

Перечитав свой отчет за прошлый год, я также решил подготовиться инфраструктурно. Чтобы не тратить ценное время на javax.swing.JFrame jframe = new javax.swing.JFrame() во время соревнования. Хоть задание и неизвестно, можно сделать что-то универсальное, типа запускателя задач, загрузки реплеев, и так далее. Как-то так выглядело:

По выравниванию кнопок и дерганью панелек можете оценить, какой из меня Свинг-программист (никакой). Спойлер: тоже не пригодилось :)

Опять же, по следам прошлого года, я решил брать не Кложу, а Джаву. Соображение было такое, что байтики перекладывать в Кложе все равно не особо удобно, скорость программы перевешивает скорость разработки, а Раст я так и не выучил за год. Короче, компромис.

Под это дело я завербовал двух местных единомышленников (@intelliyole и @pdrobushevich, спасибо вам, если вы это читаете!), мы приехали в офис JetBrains в Мюнхене, я нарисовал нашему телеграмчику логотип и мы стали с ужасом ждать пятницы.

Команда называлась Please disable AdBlock
Команда называлась Please disable AdBlock

Тэ ноль

В момент старта соревнования... ничего не произошло. Точнее, выложили еще пачку картинок, и... все! Самое удивительное ощущение от соревнования, что вот оно, началось, а что делать — непонятно! Мы готовы, сидим, на низком старте, все JIT-ты прогреты, а куда программировать — непонятно!

Офигиваем от отсутствия задания.
Офигиваем от отсутствия задания.

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

А вот это просто милая отсылка к Пионерам, сразу видно, культурные люди соревнование проводят:

Тэ плюс 4:30

Только в 19:30 (!) наконец-то выложили задание. Стало можно запрогать хоть что-то. @Yole написал нам первую версию интерпретатора, которая смогла посчитать функцию 2^N на инопланетном языке и ушел спать. Правда, galaxy.txt она считать отказалась, а почему — непонятно.

Я, как настоящий человек-сова на кокаине, подхватил эстафету, потыкал Джавную версию и сел писать свою версию на Кложе. И это, скажу я вам, совсем другие ощущения. Как будто ты вышел на трек в кирзовых сапогах, и даже какое-то время в них бежал, и вдруг сменил их на удобные спортивные кроссовки. Не то чтобы в Кложе какие-то особенные фичи я заиспользовал, нет: самый обычный код, парсинг строки, тусовка массивов. Просто там все удобнее сделано! Циклы, ифы, функции, коллекции. Даже в сравнении с самой последней 14-й Джавой, со всеми ее рекордами, стримами, ломбуками и стейт-оф-зе-арт ИДЭ от работодателя. Последний раз на Кложе я писал в 2018, с тех пор поработал на Расте, Джаве, Котлине, C++, но за эти три дня ощутил снова, как в первый раз: Кложа — язык, наиболее близкий к форме мыслей программиста. Пишешь как думаешь. И это, ребята, дорогого стоит. И это еще до того, как начнутся по-настоящему продвинутые фичи. Короче, писать можно на чем угодно, но получать удовольствие, по-настоящему, — только от Кложи.

За ночь с первого дня на второй я этот интерпретатор написал. Это, собственно, субъективно, и была лучшая часть соревнования. Во-первых, пять-восемь часов самозабвенного кодинга под звуки спящих птиц, медленно всходящего солнца, ночных мусоровозов и неврозных автосигнализаций.

Во-вторых, я наконец-то пощупал лямбда-исчисление руками. То есть я про него конечно слышал, но глубоко не вникал. Тут же мы собственно компьютер на нем написали, по пути разобравшись, как люди выкручиваются, чтобы простые и привычные конструкции в него засунуть. Вот это B, C, K, W system и вот это SKI combinator calculus и вот это Logic and predicates и вот это Pairs. Скажем, cons/car/cdr очень остроумно придуманы:

true  := λx.λy.x
false := λx.λy.y
cons  := λx.λy.λf.f x y
car   := λp.p true
cdr   := λp.p false

То есть cons (pair) это такая частично-вычисленная лямбда от трех аргументов, замкнутая на два. Третий аргумент — это функция, которую cons потом к первым двум аргументам и применит. Собственно, чтобы получить первый аргумент из cons (car), мы ему передаем функцию от двух аргументов, которая возвращает первый и игнорирует второй, cons ее вызывает, и вуаля: мы достали голову списка!

Я этого как-то не знал, и было очень интересно узнать. Действительно остроумно же! Жить так нельзя, конечно, но для теории программирования важно все равно.

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

и таком:

и вот спустя часов восемь возни с двухбуквенными идентификаторами, ручным декодированием бинарных кодировок, собирания в уме списков из cons-ячеек, программа наконец запускается и СОВЕРШЕННО НЕОЖИДАННО выводит В ТЕРМИНАЛ, одно из самых некрасивых мест на планете, такое:

Более того, спустя еще несколько часов выклянчивания подсказок в чате, исправления багов, приделывания таки свинг-окошка на экране ВНЕЗАПНО рисуется такое:

И это, скажу я вам, офигенный драматургический момент. Как выход из платоновской пещеры практически.

Задокументировано!
Задокументировано!

Тэ плюс 20 часов

На этом хорошие новости, да и соревнование в целом, для меня закончились. Оказалось, что запустить галактику — полдела. Это обязательное условие, но оно не засчитывается никак. Чтобы получить хоть одно очко, нужно что-то с этой галактикой сделать. Только неизвестно что. Помните старые поинт-энд-клик квесты вроде Петьки и Василия Ивановича, где нужно из дамской сумочки, валенка и мясорубки догадаться собрать пулемет?

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

Типа, вот так вот. Милая пиксельная графика, да! Но никаких дополнительных пояснений, контекста, намеков, ничего вообще нигде было. Что это? Что это значит? Что с этим можно сделать? Надо ли вообще что-то с этим делать? Продвигаюсь ли я вперед или топчусь на месте? Ситуация осложнялась тем, что интерпретатор написал ты сам. То есть ты никогда не знаешь, где действительно загадка, где просто «фантазия художника», где задание, где тебе пытаются что-то сказать, а где просто оформление, где баг твоей реализации, а где баг организаторов (было и такое).

Например. В левом верхнем углу галактики (важное место, да?) нарисовано:

Что читается как: ap ap mul pwr2 34 ?. Что не очень много смысла имеет, потому что даже по количеству ap неверно. Вот как это понимать? И что с этим делать? И так в каждом квесте в лучшем случае (тут хотя бы прочитать можно).

Насколько это сложно? Из двухсот начавших соревнование команд только одна (!) сообразила, что нужно было делать, и только через 11 часов после начала соревнования. Вторая подтянулась на T+20, всего к моменту окончания лайтинг раунда «что-то» сделали 5 команд. Всего ПЯТЬ команд смогли сделать ПЕРВЫЙ шаг (и тольк две из них — второй и далее). Кто-то из них в чате писал, что не знает, что именно они сделали. Даже спустя все три дня я до сих пор не знаю, что конкретно требовалось сделать и за что давались очки.

Тэ плюс 24 часа

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

Тэ плюс 48 часов

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

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

Примерно так выглядят те крупицы знаний, которые сбросили нам организаторы:

И это, собственно, момент, где я из соревнования по большому счету выбыл. То ли я тупой, то ли мой мозг как-то по-другому устроен, но с самого начала соревнования я не разгадал НИ ОДНОЙ загадки и ни до чего сам не догадался. И это не преувеличение, я не скромничаю и не имею в виду «очень мало догадался». Нет, буквально НИ-ЧЕ-ГО. ВСЁ происходящее я понимал или из дискорд-чата, где другие такие же бедолаги делились крупицами знаний, либо из подсказок организаторов, которые обычно выдавались на сутки позже для совсем тупых вроде меня.

А вот один из организаторов сжалился надо мной и подписал стрелочками для тупых, что один зеленый квадрат — это туториалы, а другой идентичный квадрат — «мультиплеер»:

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

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

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

Что понравилось

Принудительный ликбез по лямбда-исчислению.

Душевные театральные постановки.

Отличная пиксельная графика и стильные интерфейсы настолько минимальными средствами.

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

Что не понравилось

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

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

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

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

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

Другая очевидная проблема завязанности на сервер: ошибки 400, таймауты, сброс стейта игры, внезапное возрождение предыдущего стейта и полное отсуствие контроля над всем этим. Когда ты не уверен в том, насколько хорошо работает твой эмулятор, твой прокотол общения, твой бот, добавление в этот микс случайных не зависящих от тебя ошибок не очень помогает понимать происходящее.

Отладки и ошибок нет от слова совсем. Что-то не так? Пошел нахуй. Вот тебе, список из нуля: (0). Нет, серьезно. Так выглядят ошибки. Список из нуля. Не просто ноль. Список. (cons 0 nil). На любой чих или это, или 400 иди нахуй, без сообщения.

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

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

Очень большая задержка в обновлении ладдера. После отправки своей версии требовалось несколько часов (!), чтобы узнать, как выступила одна из твоих версий.

Шрифт JebBrains Mono вместо Fira Code на сайте 😘

Что удивило

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

Что у меня что-то не влезло в монитор :)

Внезапно, меня поблагодарили в титрах. Мама, я теперь медиа!

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

Себе на будущее

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

Нет, свою жизнь надо автоматизировать, и чем раньше, тем лучше. Конкретно в этом случае мне потребовалось некоторе время, чтобы понять, что вся та сложная виртуальная машина на 320 кб лямбд для отображения стейта, да и для игры вообще, не нужна. То есть она как бы нужна, но не нужна. Это сложно объяснить, короче. Мораль такая, что свой визуализатор будет нужен.

Напоследок вот вам глаза «Ивана Зайцева, астронома», которые смотрели на нас из каждой ссылки на его гитхаб. Пусть и на вас смотрят, прямо в душу:


Почему JetBrains не напишет легковесную IDE

Еще в 2011 я публично отказался от ИДЕ и так с тех пор и живу: TextMate, Vim, Sublime, LightTable, VS Code, снова Sublime.

И вот год назад я устроился в JetBrains. Нет, мое отношение не поменялось: я все еще считаю, что в ИДЕ программировать не надо. У меня на столе усердно копится папочка Annoying IDE(A), а Джаву и Котлин я все так же пишу в Sublime Text.

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

Сейчас, посмотрев на Idea, и на Java-тулинг, и на Android Studio, я понимаю, что это принципиальное противоречие: в самой идее IDE заложена сложность, кривость и неудобство. Легковесная IDE не может существовать, потому что мир вокруг сложен.

Давайте подумаем, что ИДЕ нам дает. Syntax highlighting, Go to definition, Find usages, Show hierarchy, Structural rename, и допустим Run configurations, то есть возможность все это как-то запускать (в том числе и под дебаггером). Все это сами по себе вполне легковесные функции, так-то. Легко представить их чисто интерфейсно в, скажем, в Vim или VS Code, ничего принципиально сложного или развесистого они в себе не несут. Так в чем же проблема?

Проблема в том, что чтобы они работали, нужно вот прям все-все знать о проекте в целом. Язык программирования, допустим, маленький и фиксированный, с ним просто. Поэтому Syntax highlighting, для которого дальше одного файла смотреть не нужно, есть в самых легковесных редакторах. А вот как проект настроен и как билдится, вот тут-то адок и начинается. Миллионы билд-систем, некоторые из которых императивные и тюринг-полные, два миллионна фреймворков, миллион в квадрате интеграций, все это кривое, косое, уникальное, как блядь снежинка, общается друг с другом не пойми как, пишет файлы, теряет файлы, не видит очевидного, лезет куда не нужно, зависит друг от друга, ломается и занимается при этом довольно тривиальными вещами, что обидно.

Особенно меня впечатлила Android Studio. Она как бы на основе Idea, но делается гугловцами. Гугл, как известно, принципиально не может ни во что простое и понятное, но тут это возведено в принцип. Android Studio — это не продукт, это папка scripts на всех языках мира, собранная напрямую с машин разработчиков гугла, поверх которой натянут разве что чудом не разваливающийся интерфейс, который хочется пристрелить из жалости. Если бы в мире Mad Max писали программы, их писали бы именно как Андроид Студию.

При этом Андроид Студия это и есть ИДЕ в самом чистом виде: адок, который хоть как-то работает и который хоть во что-то скачиваемое упакован. Это и есть его основная польза. Проблема не в том, что ИДЕ плохо сделана, проблема в том, что от нее хотят работы с вещами, которые сами по себе безумно сложные. Почему они сложные — ну, ответ в человеческой природе, человек слаб, и да, это сложность на пустом месте, только для ИДЕ это данность, а не пространство для дизайна. Как только ИДЕ станет легковесной, она перестанет быть ИДЕ.

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

Продолжаем обобщать и передергивать

Евгений Трифонов накатал ответку на мой старый Software Disenchantment! На что у меня есть несколько замечаний, по мелочам и по существу.

Готов поверить, что Word в 2020-м запускается медленнее, чем консольный редактор vi в 1983-м

Интересное искажение восприятия, в котором все консольное считается ультра-быстрым, а все гуевое по-умолчанию медленным. Word очень неплохо оптимизирован на startup time как раз. Вот видео посовременнее, вот из 2010 (на железе 2010!). Как и веб-страница facebook. Несмотря на раздутость по функциям обоих. А те же vim/emacs, обвешанные плагинами, могут вполне себе долго запускаться. Или вот, например, command-line prompts, которые рисуются до 1000мс после КАЖДОЙ команды.

Да, приложения за 10 лет выросли в разы. Но объём места за то же время вырос в СОТНИ раз. То есть жить стало в десятки раз лучше.

Ну вот к этому-то и был мой основной вопрос. Мы получили выигрыш в 100 раз за счет hardware. К hardware вопросов нет. Но потеряли 10 раз в software. И хотя в сумме мы вроде как в выигрыше, к software вопросы остались! В чем причина? Неужели это обязательно? Хорошо что жить стало в десятки раз лучше, но могло бы ведь и в сотни? Так почему не стало? Мы точно знаем что могло, потому что старые приложения сохранились и работают — быстро, четко, компактно на современном железе. Зачем делать хуже, если мы уже знали, как делать лучше?

Моя цель здесь — не раскритиковать конкретный пост, а показать общий подход: мы часто заявляем «приложения разбухли/затормозили без веских причин», не до конца понимая эти причины.

У меня кстати вопросы к размеру приложений пропали после того, как фейсбук переписал мессенжер. То есть раньше я думал, там действительно что-то неладно, что такие толстые приложения получаются. Типа, фотку олега тинькоффа в 4k забыли удалить. Или статически влинковали Oracle DB, причем сразу четыре разные версии. Но нет, это банально количество кода. Переписанный с нуля текстовый чатик начинается с 360 000 строк кода в фейсбуке. Это все обычные cкомпилированные классы, просто их так вот много. Вот столько они пишут. Большие компании — большие проблемы, I guess.

А если поискать более глубокие причины, то найдется очень простой ответ: единственный более-менее промышленно практикуемый способ работы с кодом — добавление нового кода. Не улучшение, не переделывание, не замена, не удаление. Добавление. Вот и имеем что имеем.

Да, легенды говорят, где-то в далеких горах еще существует rewrite from the scratch, и он действительно может улучшить положение дел, но это скорее экзотика, о которой видят сны электропрограммисты.

(Про то, что бывают и полезные улучшения) Когда в Android ввели Adaptive Battery («умное» определение, каким приложениям можно есть аккумулятор в фоне), замеряли ли вы, изменилось ли энергопотребление вашего телефона?

Без комментариев

Yeah, Android is..interesting. Reminders come late, sometimes hours late. Dig deep in the settings in order to MAYBE fix it. It's a battery optimization thing

Who thought of that? We'll optimize battery life by NOT REMINDING YOUT IN TIME ABOUT THINGS YOU ASKED TO BE REMINDED OF!

Когда Google Play Protect в фоновом режиме заботится о вашей безопасности, вспоминаете ли вы, что раньше этого не было?

Здесь это приводится как пример оправданного улучшения и даже чуть ли не прогресса, но я лично наоборот, вспоминаю, что у меня iOS и macOS и там как-то без антивирусов все тоже неплохо работает. Так что да, постоянно задумываюсь, что с андроидом и виндоус не так, что им необходимантивирус.

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

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

Заявления об «испортившемся софте» звучат так, будто раньше разработчики экономили вычислительные мощности, а сейчас они все плевать хотели на оптимизацию.

Я думаю, разработчики не сильно изменились в плане количества усилий. Но старые программы рассчитывались на старые компьютеры, и потому на современных летают. Вопрос, собственно, только в том, почему тогда не летают новые?

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

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

Производительность JavaScript через подзорную трубу

Ха-ха-ха, производительность и JavaScript в одном предложении, лол! Славу Егорова бесконечно уважаю, но надо правильно понимать message его докладов: они про то, что чтобы заставить JS в каких-то, очень специально отобранных случаях, достойно себя вести, нужно быть минимум compiler инженером, который над самим V8 и работает.

Кому лучше от древнего мастерства пятиярусных кроватей, если при этом пригласить друга в гости некуда? Не пора ли овладевать новым мастерством выбора king size-кровати?

Намек на нетрадиционные отношения? Одобряю!

По-моему, из-за Slack переживают в основном айтишники, которым оперативка нужна для других тяжёлых задач.

Ну у не-айтишников просто в целом нет денег на такие макбуки, на которых бы Slack вообще запустился.

Slack — это и есть рояль. Окей, он ест много памяти, но слышали ли вы, чтобы не-айтишники жаловались на него, как когда-то жаловались на Photoshop? По моим ощущениям, у обычных пользователей уже достаточно пространства, чтобы этот «рояль» не мешал им «пройти по комнате». Да, можно заменить на пианино и сэкономить место. Но если живёшь во дворце, и с годами площадь дворца становится ещё больше, то зачем?

Зачем вообще останавливать раздутие программ? Например, чтобы телефон или ноутбук 2017 года, с которыми все прекрасно физически, не превратились в тыкву три года спустя? Они же не изнашиваются за 3 года, процессор смазывать не нужно, пиксели из экрана не выпадают, память не засоряется. Нет НИ ОДНОЙ причины менять телефоны и ноутбуки так часто, кроме софтверной. Если железо ТАК сильно продвинулось (а оно продвинулось), я бы хотел воспользоваться этим преимуществом и покупать ноутбук за $200, а не за $1000, например, и чувствовать себя адекватно. Пользоваться программами, например. Я многого прошу, да?

(про Year 2000 problem) Но потом, много лет спустя, другим людям пришлось потратить кучу ресурсов на то, чтобы разобраться с последствиями этого решения и предотвратить проблемы.

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

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

Я же прошу не о выдрачивании всего и вся, не о неделях работы ради 0.01% выигрыша, не призываю срочно переходить на C++ и бегать с дизассемблером каждое утро. Мне хочется приземленных совершенно вещей: чтобы программы под себя не ходили, например. В том же переписывании мессенжера видно, что все их суперуспешные по стандартам индустрии достижения, которые они получили, связаны только с тем, что они порезали абсолютно дикую хуйню и ересь из прошлой кодбазы и просто сделали нормально. Это не какие-то супертехнологии, а базовые совершенно вещи: переиспользовать код! Юзать одну базу, а не десять! Планировать! Разговаривать между отделами!

Моя претензия лишь к тому, что в связи с этими проблемами возникает какая-то радикальная секта, верящая в скорый конец света из-за разрастания софта. В этой секте переписывают историю («раньше всё быстрее работало!»), недопонимают происходящее («а почему это Windows с годами так выросла, там же ничего особо и не поменялось»), говорят о разработчиках незаслуженные вещи («они не хотят ничего оптимизировать») и ударяются в крайность «давайте экономить каждый байт, даже когда это сделает пользователям хуже». Давайте не будем так делать.

Ну а я закончу цитатой из твита @amyhoy:

users
will
never
create
DEMAND
for
better
software
you
have
to
fucking
CHOOSE
DISCIPLINE
to
create
it

Композируй это

Познакомился с Jetpack Compose. Это такой новый фреймворк «декларативного» UI для Андроида от Гугла. Потому что Гуглу, как обычно, мало одного нового «декларативного» фреймворка для Андроида (Flutter), и они решили делать сразу несколько. А чтобы ни кто не путался, делают их максимально похожими. Серьезно, авторы за ланчем обмениваются идеями и добавляют в оба.

Почему «декларативный» в кавычках? «Декларативные» UI-фреймворки — это новая волна, начатая Реактом и продолженная Flutter, SwiftUI, и вот теперь Jetpack Compose. Декларативные они в очень пост-ироничном смысле: упор в них как раз делается на описание UI в коде. А код, даже чисто функциональный, никак не может быть декларативным. Иерархия примерно такая:

  • Декларативный.
  • Чистый функциональный.
  • Императивный.

Понятно, что все эти фреймворки по уши сидят в императивности. Вот SQL декларативный. Prolog декларативный. Блин, даже XML/HTML/templates декларативные! А в том, чтобы позвать функцию, получить результат и обработать его, подергав попутно удобно подложенные глобальные процедуры, ничего декларативного нет. Но XML из моды вышел, А СЛОВО КРАСИВОЕ, чего слову пропадать?

Так вот, «декларативные» фреймворки, как их называют, содержат что-то вроде VDOM, а точнее концепцию top-down rerendering. Это когда твоя функция должна посчитать, как в текущий момент UI должен выглядеть, полностью с нуля (сгенерить VDOM), а задача фреймворка — привести UI в соответствие с этим представленим путем минимальных модификаций. В противовес старой ООП-UI модели, где эта задача ложилась на программиста и он неизбежно ныл и косячил. Раньше: panel1.close(); new panel2().open(), сейчас fun Window() = if (x) new panel1() else new panel2(); rerender(Window()); Мутабельный граф внутри все равно есть, только ходит с ним общаться сам фреймворк, ну, потому что код довольно однообразный был все равно.

Декларативность тут в том смысле, что фреймворк только описывает, как ему хотелось бы видеть UI, а не создает его самостоятельно. Ну натянуто, конечно, но хотя бы видна мысль. Почему первый «декларативный» фреймворк называется React, а не Declare, например, я если честно не знаю. Он ведь ни в одном месте даже не реактивный.

Так вот, особенно смешно в контексте спора за чистоту терминов смотреть именно на Compose, где весь API построен на мутейтящих глобальное состояние ПРОЦЕДУРАХ (ага, они еще бывают). То есть буквально () -> Unit. Код предполагается писать вот так (на выделение не смотрите, просто скриншотил в туториале):

Почему у Column такой большой отступ я вообще понятия не имею, в Котлине с форматтингом вообще плохо
Почему у Column такой большой отступ я вообще понятия не имею, в Котлине с форматтингом вообще плохо

Человек, опытный в Котлине, может заподозрить тут потенциальную возможность здравого смысла. Например, в Котлине есть все инструменты, чтобы Text() внутри, скажем, Column, на самом деле не просто вызывал функцию Text(), а дергал бы какой-то хитрый метод на внешнем скоупе (колумне как раз) с неявным ресивером и что-то куда-то там добавлял (количество неявностей в таком дизайне оставим без обсуждения). Но нет. Text(), как и все остальное здесь, – обычные процедуры. Зови в любом месте. Где позвал, там компонент и добавится. Императивочка-с.

Экспозиция закончилась, можно наконец перейти к сути поста. Идея делать такое АПИ — видимо, призрачное счастье разработчиков. Действительно, что может быть проще, чем написать:

Column {
   Button()
   Text()

Максимально лаконичное API, да? Но если присмотреться, мы увидим, что Column принимает не список детей, а замыкание. Почему это? Спросите вы. А потому что это гребаные процедуры, вот почему. Придумав такое API, ты невольно загнал себя в угол — его нужно держать строго определенным образом, и никак иначе. Удобно в простых примерах, а дальше начинаются сложности.

Мы, программисты, привыкли, что в коде можно делать много разных вещей. И нам это нравится! Можно принимать значения, передавать значения, трансформировать значения, обрабатывать значения. Но вы поняли, наверное, уже, к чему я веду, да? Компоуз решил нас этой радости, потому что его API ничего не принимает и не возвращает. Там нет значений. Его API можно только позвать, конец истории. Нельзя написать функцию, которая сортирует компоненты. Которая вставляет разделитель в список компонентов. Нельзя даже нормально вложить один компонент в другой без создания анонимной лямбды. Потому что и компонентов-то нет. Только лямбды. 

А лямбды это что? Это худший из возможных форматов хранения данных. Хуже структур, понятно, и даже хуже чем ООП. Лямбда — это черный ящик, черная дыра, максимально негибкое, неудобное и безполезное явление, на которое ни посмотреть, ни потрогать, ни сообщение послать, ни разобрать, ни распечатать, ни сравнить, а только обернуть в другую такую же гребанную лямбду или передать дальше. Лямбды невозможно упростить — они всегда только растут, толстеют, как слои лука у Шрека или жировые прослойки на твоей слоеной архитектуре. Максимально вредный объект, особенно как основа API. И поверьте, внутри Композа (да и снаружи) этих лямбд хоть лопатой жуй, и они все анонимные, и ничего не принимают и не возвращают, и от неявных ресиверов зависят, и друг друга заворачивают и разворачивают (ха-ха, шучу, лямбду нельзя развернуть!) и они анонимные все! А, это уже было. Ну вы поняли.

Лирическое отступление. Вообще общую адекватность автором можно оценить по вот такому интересному коду:

Это чтобы если ты пишешь a.ref=b то произошло бы на самом деле b?.value=a. Чем первое лучше второго я боюсь даже спрашивать. Серьезно, за психическое здоровье опасаюсь, если узнаю ответ.

Другой пример странного, кхм, изобретения, это то что они перегрузили (!) оператор (!!) унарный (!!!) плюс (!!!!) делать что-то нетривиальное. То есть оператор конечно довольно бестолковый, но все равно — что???

)

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

В каком-то интервью Артемий Лебедев объяснил, в чем проблема эргономичных вещей, не конкретных, а вообще, по жизни. Почему они не становятся мейнстримом. Потому что их создатели думают об одном каком-то, пусть даже основном, способе использования, и гипероптимизируют под него, забывая про все остальные. Так же и тут. Самый удобный АПИ у нас уже есть — это функции с явным списком аргументов и возвращаемым значением. И все. Конец истории. Лучше не будет. Серьезно. Не надо мудрить, хитрить, не надо придумывать «более удобный DSL», не надо аннотации придумывать, не надо компилятор форкать, не надо вообще программисту помогать вызывать функции. Лучше все равно не сделаете, а проблем на разгребание всего этого — создадите. Лучшая помощь — оставить нас в покое и дать писать обычный код. Будете проектировать свой UI-фреймворк — не ошибитесь.


СтрижПИ

Если вдруг вы еще не знаете, примерно полгода назад Эппл анонсировало новый UI фреймворк — SwiftUI. Событие очень серьезное, и как iOS разработчик со стажем я тут же переключился на него — сначала попробовать, а потом уже и выпускать production приложения. Спустя полгода и два заапрувленных релиза, хочу поделиться с вами мыслями о SwiftUI.

Во-первых, то, что Эппл выпустило нормальный реактивный data-driven UI фреймворк, заслуживает исключительно всяческих похвал. Правильный тренд, правильный подход, _почти_ интерактивное превью, все вовремя и к месту. Нам, iOS-программистам, чего-то такого сильно не хватало.

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

VStack(
    Image(uiImage: image),
    Text(title),
    Text(subtitle)

можно было писать

VStack {
    Image(uiImage: image)
    Text(title)
    Text(subtitle)

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

Работает это благодаря вот такому вот прекрасному интерфейсу:

То есть не только не очень понятно зачем так усложнять себе жизнь, но еще и больше 10 элементов не засунешь. Может быть создатели руководствовались правилом 7±2 и решили, что пользователи айфона не смогут всерьез осознать более 10 одновременных элеметов на экране.

То что в этом интерфейсе пропилена специальная дырка для if напрягает если честно еще больше:

Не самим фактом дырки, а вопросом, где же собственно дырки под все остальное?

(на самом деле, если хочется больше 10 элементов, есть целый специальный компонент — ForEach, который — уберите детей от экрана! — принимает список)

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

Ладно. Допустим они хотели, чтобы код красиво выглядел на презентации. Но логику надо соблюдать? Например, вот тут на мой взляд смешались макароны и стрекозы:

VStack(alignment: .leading) {
  Text("abc")
    .font(.subheadline)
    .padding(.all)

.font() устанавливает свойство (шрифт), а .padding() заворачивает Text view в Padding view, возвращая новый тип view. То есть почему не сделать однообразно? Свойства — методами, контейнеры замыканиями?

VStack {
   Padding {
       Text("abc")
           .font(.subheadline)
   }
}.alignment(.leading) 

Есть и совсем странные места, например, NavigationView берет заголовок не из собственного property, а из первого лежащего в нем ребенка!

NavigationView {
   List {...}
       .navigationBarTitle(Text("Rooms"))

Но это все конечно цветочки. Главный консерн у меня по поводу того, сколько всего SwiftUI делает сам, «магически». Например, можно написать:

Text("abc").padding() 

и все. Какой именно паддинг? А какой-то дефолтный. Еще и зависящий от ситуации. Хуже того, можно вообще ничего не писать:

HStack {
   Text("★★★★★")
   Text("Avocado Toast).font(.title)
   ...

И все равно обнаружить дырку вот тут:

Процитирую чувака со сцены:

SwiftUI didn’t slam all of the stack’s children against each other. It left some space between these two because Adaptive Spacing™ is in effect.

То есть SwiftUI сам решил что в этом месте нужна дырка и добавил ее. Как он это решил? На основании чего? Вы скажете «просто дефолт», но все сложнее! Насколько я понимаю, SwiftUI не чурается залезть внутрь ваших вьюх и если он узнает лежащие там компоненты, он может принимать разные решения в разных ситуациях. Например, отступить не от bounding box, а от text baseline, если он у вас где-то в глубине есть: 

Или если написать

List {
   Button { Text("Add room") }

То кнопка будет черненькая:

А если теперь поменять стиль списка (не кнопки!):

List {
   Button { Text("Add room") }
}.listStyle(.grouped) 

То уже синенькая!

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

Во-первых, на дефолты нельзя полагаться, потому что они будут меняться. Пока ты изловчился сделать на сегодняшних, Эппл выкатывает завтрашние и они становятся еще умнее и перекрашивают кнопки, втыкают больше паддингов, ставят контролы с другой стороны и т.п. Помните CSS reset? Может показаться, что в случае с браузерами это проблема исключительно потому, что браузеров много и они не могли договориться. SwiftUI же один, чего тут волноваться? Очень просто: во-первых, устройств у Эппла много и на всех дефолты разные. А во-вторых, через два года Эппл решит что пора обновлять свой design language и выкатит другие дефолты и все приложения поплывуууут в дальнее плавание. 

Вторая причина в том, что с умным поведением нужно бороться, что тоже очень неприятное занятие. Я прекрасно помню бессонные ночи, когда я (в вебе) изо всех сил пытался убрать какие-то левые зазоры под картинками, выровнять текст с иконкой ровно как тебе нужно, пытался убить непойми откуда взявшийся вложенный скролл, победить наезжающие друг на друга float: left иллюстрации и подобное. Потому что ситуация ровно такая же: веб предлагает набор высокоуровневых дефолтов и «умной» логики лайаута, которые иногда работают, а иногда как кость поперек горла, вытаскиваются только хирургическим путем.

И третья причина в том, что с таким подходом разработка никогда не завершится. Ты не знаешь, сколько еще «умных» дефолтов ты пропустил и как они могут потенциально испортить тебе жизнь, сейчас или в будущем. Обнаружить, что у Васи на древнем третьем айпаде и вчера вышедшей новой iOS (и только на такой комбинации) «умный» SwiftUI показывает дырку в 30 пикселей вместо 20 и из-за этого едет половина верстки, бегать за такими проблемами — занятие для молодых и сильных.

Так что с тех под я предпочитаю вещи явные, прямые и тупые, как кусок водопроводной трубы: если я забыл воткнуть зазор между картинкой и текстом, то я сам дурак и не будет никакого зазора. Если я воткнул зазор в 20 пикселей, он и останется в 20 пикселей, что бы ни случилось. Более того, об этом в коде будет явно написано буквами.

Да, такой код не будет выглядеть так красиво со сцены Steve Jobs Theater. Зато он будет делать ровно то, что в нем написано, его можно понять, предсказать, найти, разобраться и поменять. Потому что ДОБАВЛЯТЬ простые и предсказуемые компоненты просто. А вот ОТМЕНЯТЬ чужую умную непрозрачную логику тяжело. Потому что она чужая, умная и непрозрачная.

P.S. Disclaimer: People being people, многим важно не только ЧТО написано, но и кто это пишет. Некоторые не готовы слушать аргументацию человека, который не программирует на Swift минимум пять лет без отпуска. Некоторые игнорируют любую критику, автор которой не может похвастаться собственноручно задизайненым языком или (хотя бы) полноценным UI-фреймворком. Поэтому во вступлении я немножко слукавил. Конечно я никой не iOS разработчик, я даже на Swift (языке) никогда не писал и слабо представляю, что там стоит за атмосфера. Swift UI изучал только то статьям и презентациям. Я даже попробовать его не могу, потому что он требует Каталины, а на ней не работают никакие программы. Но зато я давно и плотно интересуюсь темой UI фреймворков, да и программирую не первый день, так что верить мне можно.

P.P.S. Верить никому нельзя.

Кто бреет брадобрея?

Мое любимое развлечение — собирать ссылки на известные парадоксы в популярной культуре, которые автор, сам того не замечая, переврал. Классический случай «слышал звон, да не знаю где он».

Один из примеров был в игре Portal 2:

Does a set of all sets contain itself?

И вот буквально сегодня попалось в Вечной жизни смерти:

– У нас есть веревка, толщина которой неодинакова. На то, чтобы она сгорела от одного конца до другого, требуется час. Как, используя эту веревку, отмерить пятнадцать минут? Помните – толщина у веревки разная!

На этот раз дети не торопились отвечать – они глубоко задумались. Вскоре поднял руку мальчик:

– Надо сложить веревку пополам и поджечь ее одновременно с двух концов.

АА кивнула:

– Иди сюда, – и поставила мальчика позади себя рядом с первой девочкой.

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

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

В примерах выше слова пересказаны по памяти почти абсолютно точно, с мельчайшими ошибками (в первом ВСЕГО ЛИШЬ частицу «не» забыли! — мелочь для обычного литературного текста в обычных обстоятельствах), но эта мельчайшая ошибка разрушает самую суть. Остается как бы пустая скорлупа без смысла, соломенный самолет, приманивающий миротворческие грузы.

Good times create weak men

Есть такой очень важный доклад Jonathan Blow - Preventing the Collapse of Civilization. Смотреть прям обязательно. Это такой Software Disenchantment только с анализом причин и выводом.

Так вот, в нем утверждается что современные программисты, стоя на плечах гигантов, утратили способность писать фундаментальные вещи и вообще простой, быстрый, надежный софт. Good times create weak men:

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

При этом тревогу никто не бьет: всем кажется, если мы умели делать X, а научились делать Y, то теперь мы умеем делать и X, и Y. Что не совсем верно, потому что знания (экспертиза!) сами по себе вообще говоря не передаются (это одна из самых важных и новых для меня мыслей доклада), а необходимости практиковать X нет, соответственно он благополучно забывается. Docker и Electron — самые популярные технологии сегодняшнего дня. Обе не про что-то новое или фундаментальное, а про то, чтобы тихонько спрятать сложность под ковер, понять, разобраться или изменить которую у нашего поколения уже не получается.

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

Все это немножко отдает дедовским ворчанием, и вообще как-то не ощущалось без хороших наглядных примеров. Пока я не набрел на annoying.technology, клон нашего grumpy.website. Ребята не побоялись поставить себе macOS Catalina, и вот где, оказывается, цирк!

Переключение чатов тормозит: https://annoying.technology/posts/e500c236b5e2853a/

Вместо следующего трека показывается через-один-следующий https://annoying.technology/posts/ee91b37183818d7b/

Песни показываются по два раза https://annoying.technology/posts/991e8babac1f6dc4/

Рендеринг разъезжается https://annoying.technology/posts/802dfae3517d4419/

Элементы списка не выделяются https://annoying.technology/posts/da8e5b3f56d9f767/

Клик на элементе выбирает другой элемент https://annoying.technology/posts/04769fafdac16826/

Программа конфликтует сама с собой https://annoying.technology/posts/c1f50e78a65d2ce3/

Программа рандомно отписывает от подкастов https://annoying.technology/posts/5c942a7b43a4a8b4/

Скачка не завершается https://annoying.technology/posts/50a5965493785fdb/

И это только первые две страницы!

Что показательно, это не какие-то случайные заскоки или ушлые маркетинговые решения. И не то чтобы они пытались что-то инновационное сделать. Нет, это самые простые и банальные вещи, какие только могут быть, вещи, которые компьютеры делали 30 лет без особых проблем, которые ipod с ЖК экраном и мощностью в 1/10 наручных часов успешно решал, и они их фейлят. Ты просишь человека открыть шкаф, а он обосрался. Не в смысле не смог, а буквально наложил в штаны вместо этого. Примерно такой уровень сложности задачи.

Вот как программируют современные программисты. Как думаете, сколько этот код продержится? https://twitter.com/argentumko/status/1210532125637611521
Вот как программируют современные программисты. Как думаете, сколько этот код продержится? https://twitter.com/argentumko/status/1210532125637611521

Причем, как правильно замечено в одном из постов, это не какие-то маргинальные программы непойми кого. Это флагманские Эппловые продукты, с помощью которых вообще-то в первую очередь рекламировалась эта самая новая ось. То есть не применим аргумент недосмотрели, не было времени, занимались чем-то другим — нет, можно быть уверенным, что огромное количество ресурсов было потрачено и огромное количество глаз смотрело именно на эти самые приложения. И ВСЕ РАВНО НЕ СМОГЛИ!

Понимаете? Понимаете, насколько все плохо? Одна из самых влиятельных технологических компаний в мире, которая может нанять кого угодно и в каких угодно количествах, бренд которой построен на супер качественном и вылизанном софте, компания, которая не выпускает «бета продуктов», которая МОГЛА в прошлом (документальный факт), НЕ СМОГЛА! Не «не захотела», не «выбрала неверное направление», не «переоценила свои силы», не «промахнулась с первого раза» а тупо, банально хотела, очень хотела, но не смогла.

И такое, ну, вообще вокруг нас. Новый Gmail работает хуже старого. Новый Твиттер медленнее и косячнее старого. Новый Youtube рисует меньше, а тормозит больше. Про macOS и iOS мы уже поговорили. Даже когда ситуация и задача фиксирована, а качество все падает и падает. Это даже не worse is better, потому что ничего нового не производится, место на рынке не делится, компания, принципы, приоритеты, пользователи не меняются. Буквально, те же самые люди делают тот же самый продукт. И выходит хуже и хуже.

Вот что печально.

Будущее программирование-2

Интересно, что хоть я в своем предыдущем посте явно и написал, что работа в облаке и работа в браузере — две совершенно перпендикулярных оси, я все равно получил пару комментариев от людей, которым кажется, что ЕСЛИ ты хочешь чтобы IDE работала в облаке, НЕОБХОДИМО, чтобы она работала в браузере.

если у тебя браузер лишь отвечает за фронт, то ресуркоёмкие вещи (индексация всякая, подсказочки, рефакторинг, компеляция) можно отдать серваку (по-моему пока ms додумались до language server, не?).
Не секрет, что многие считают идею очень прожорливой, поэтому мне кажется это было бы отличным выходом запихнуть иде в браузер где все сложные и ресурсоемкие операции выполнются на сервере, а тебе предоставляется только окошко терминал.

Поэтому я на всякий случай повторю еще раз:

Можно сделать локальную, прожорливую ИДЕ нативно. Классика: IDEA, Eclipse, Visual Studio. Подход прост и понятен всем.

Можно сделать облачную ИДЕ в браузере: Cloud9, Jupyter. Это то, что считалось будущим программирования, но пока стало очень нишевой штукой. Но это НЕ единственный возможный вариант.

Можно сделать локальную, прожорливую ИДЕ в браузере. Это то, что сделали VS Code и Atom. Не очень понятно, что они от этого выиграли, кроме того, что попали в волну, когда всем показалось, что будущее за JavaScript.

Можно сделать облачную ИДЕ с нативным приложением. Примеров ИДЕ пока нет, но самому подходу сто лет, называется тонкий клиент, отлично себя зарекомендовал.

Никто не мешает отгружать вычисления, ворочать облачными ресурсами и делать все остальное, НЕ будучи засунутым в браузер. Еще раз: браузер это довольно странная, во многом ограниченная и компромиссная платформа, которая дает leverage простым веб-страницам, но стоит начать делать что-то чуть более сложное (да, приложения, причем ЛЮБЫЕ приложения, даже самые элементарные), как она тут же начинает путаться под ногами и мешать.

Ну серьезно, подумайте, вот начали вы облачную ИДЕ делать, чем браузер вам поможет? HTTP-клиентом? Серьезно, там больше НИЧЕГО нет, одни ограничения.

Да, у веб-страниц есть ОЩУЩЕНИЕ что они легковеснее, чем нативные ИДЕ. Но это только ощущение. Если нужна максимальная производительность, то внезапно оказывается, что JS очень медленный язык, грузит он не так уж и мало, интерпретирует долго и КАЖДЫЙ РАЗ.

Единственное, почему, как мне кажется, в умах облачное == браузерное это репутация нативных ИДЕ как прожорливых монстров. Но это просто XCode или там Idea так написаны, как супер-комбайны «все и сразу». Они портят репутацию нативных ИДЕ, но это не значит что любые нативные ИДЕ должны быть такими. Нативные приложения могут быть легкими, шустрыми, простыми. Так мало кто делает, но это возможно и гораздо проще, чем заставить быстро работать браузер.

Будущее программирование

Я тут сделал доклад в JetBrains (внутренний, сорян) про будущее IDE. И после доклада было много вопросов из серии “Но ведь будущее определенно за Х, а вы его даже не рассматриваете”. Отвечаю.

— Почему вы не делаете IDE для браузера?

Visual Studio Code Online
Visual Studio Code Online

Делать IDE в браузере особого смысла нет. Да, лет десять назад, на волне успеха Google Docs всем казалось, что сейчас вообще все переедет в веб: и фотошоп, и обработка музыки, и монтаж видео, даже игры пытались. И, разумеется, программирование. Оказалось (внезапно, да) что браузер это довольно неудобная и ограниченная фигня и сидеть в нем добровольно никто не хочет. То есть это и так было понятно, просто лет десять назад казалось, что щас гугл с майкрософтом напрягутся и подтянут веб до нужного уровня. Тогда думать так было нормально. Сегодня это уже наивно, потому что мы видим, что по факту никто ничего никуда не подтянул, наоборот, закручивают гайки и делают из веба платформу для документов. 

Ну и десять лет назад, может быть, кому-то и казалось, что веб это дивный новый мир, но сегодня уже совсем не так ясно, зачем вообще лезть в браузер? От попадания туда у приложений не возникает магически каких-то волшебных свойств, которые невозможно было бы организовать на десктопе. Наоборот, многие полезные свойства гарантированно теряются: шорткаты сильно ограничены, drag-n-drop, файлы, интеграция в систему, перформанс. Зачем, мистер Андерсон, зачем? Если будущее приложений (вообще любых, кстати) и лежит где-то, то точно не в браузере.

— Но ведь есть WebAssembly!

Естественно, в таких дискуссиях неизбежно всплывает веб-ассемблер. Что тоже мне не очень понятно: веб ассемблер это такой способ запустить C++ в браузере. Но тут мы приходим опять же к вопросу: а зачем вообще запускаться в браузере? Что там есть такого, чтобы сначала усложнять себе жизнь, а затем эти проблемы героически решать?

— Но ведь если IDE написать для браузера, ты сразу сможешь запуститься на любом устройстве?

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

Нет, ребята, запинать код — не такая уж и проблема. Проблема — это чтобы продукт выглядел уместно в той среде, где запускается. Чтобы вел себя адекватно. Чтобы интегрировался. Поэтому write once, run anywhere это довольно наивная утопия, посмотрите хотя бы на кошмар UI-библиотек на Java. Гораздо здравомысленнее выглядит подход Flutter, которые сразу говорят: под каждую платформу виджеты свои, пишите дважды. Да, это тяжеловато разработчикам, зато прекрасно для тех, кто будет приложением пользоваться. Оптимизировать разработку продукта под время/удобство разработчика вообще путь в никуда. А если писать UI-код под каждую платформу заново звучит страшновато, то посмотрите на разработчиков игр — они под каждую консоль просто всю игру заново пишут, иногда это даже разные команды. И ничего, живут как-то, игры выходят, оптимизируются под особенности железа, используют фичи платформы. Игроки довольны.

— Ноутбуки говно, будущее за планшетами, ультимативной мобильностью и работой из купе поезда Москва-Владивосток. А что, разве нет?

Да, раз в год в интернете очередной персонаж объявляет год отказа от ноутбуков и программирования на айпаде. Да, так можно сделать. Можно найти способ, придумать, извернуться. Вопрос только: зачем?

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

Но время прошло. Айпаду уже почти 10 лет, и за это время стало понятно, что у каждого из устройств есть свой sweet spot. Для телефона это приложения, доступ к которым нужен на бегу. Для ноутбука — серьезная офисная работа. Для планшета — чтение и рисование? Так или иначе, у каждой задачи есть свой максимально удобный форм-фактор, максимально подходящий набор приложений, максимально подходящая обстановка. Скажем, для рисования это действительно экран с пером, а не ноутбук, не аудиоколонка и не телефон. Для прослушивания музыки — умная колонка, а айпад с ноутбуком будут overkill. А вот для программирования — десктоп с большим монитором, настоящей клавиатурой и мышкой/трекпадом. Все остальное — компромисс.

Да, можно программировать и на ноутбуке, почти ничего не потеряв. Можно программировать и на айпаде. Можно и на телефоне, наверное, и даже на часах. Вопрос же не в том, как может извернуться человек. А в том, что вот перед вами программист, решивший остаток своих дней посвятить созданию программ. Предположим, чисто гипотетически, что например IntelliJ IDEA УЖЕ существует для всех на свете возможных платформ, включая MiFit. Так вот, зачем, какая сила даже чисто теоретически может этого человека заставить выбрать устройством работы с кодом айпад, а не нормальную рабочую станцию? Даже при прочих равных. Ну не сможет он, бедняга, поехав в отпуск и оставив ноутбук на работе, поправить десять строчек кода. Сможет только (и будет) смотреть мультики с детьми. Настолько ли это большая проблема? Настолько ли частая? И та ли эта ситуация, вокруг которой мы должны строить будущее для всех остальных?

Спасибо, кстати, что хотя бы никто не спросил, почему мы ничего не планируем для VR-а.

— За чем же тогда будущее? На что ориентироваться?

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

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

Во-первых, компьютеры никуда не денутся именно для программистов. Может быть, часть каких-то приложений будет постепенно уходить с них на другие форм-факторы (телефон, планшет, часы), но не IDE.

Кросс-платформенная разработка важна как минимум для трех главных платформ: macOS, Windows, Linux. Пользуясь случаем, хочу напомнить, что настоящий язык по-настоящему кросс-платформенной разработки — никакая не Java, и все еще не JavaScript и уж конечно не WebAssembly, а C++. Вот уж что-то, что действительно runs anywhere.

Скорость всегда будет одной из главных фич любой программы, и уж конечно IDE. Взлет Sublime Text, Atom и VS Code связан не с успехом JavaScript, а с тем, что ждать, пока запустится Visual Studio/XCode/Eclipse/IDEA нет ну никаких сил. Если хотите расширить доступность вашей IDE — надо не выпускать ее под iPad, а лучше снизить потребление памяти вдвое. Пользуясь случаем, напомню, что по части скорости обскакать Atom/VS Code все еще есть куда (с Sublime Text уже сложнее).

Наравне со скоростью всегда будет цениться хороший UX. Буквально, если вам нужно ворваться на рынок IDE — просто берете и делаете нормально. Тут как-то даже и конкуренции особой нет.

Вот, например, я потихоньку собираю скриншоты проблем в Idea и VS Code (для отдельного поста):

Пользуясь случаем, напомню, что количество фич ≠ хороший UX. Мало сделать правильные фичи, нужно еще удержаться и не делать неправильные/ненужные/бесполезные. Feature bloat — анти-фича, и это как раз та дыра, куда сейчас летит VS Code. У них слишком много рук и слишком много свободного времени, поэтому на запуске она уже выглядит как зведолет. А значит, это еще одна возможность обскакать лидера рынка.

В общем, если будете вдруг делать IDE — успехов!

Облака и коробки

Я с Дропбоксом чуть ли не с самого открытия. Посмотрите какую милоту они рассылали в 2009:

Вышло приложение под айфон 3! Уииии!

Великая вещь, революция, без него не было бы ни Google Drive, ни iCloud Drive, ни OneDrive, ни Yandex Drive, ой, простите, Yandex Disk.

Сейчас он, конечно, не то что незаменим, но очень уж удобен, плюс привычка. У меня там лежат все документы и все билеты на поездки — все доступно сразу с любого утюга, и доступ есть и у меня, и у жены. Было несколько случаев, когда приходилось логиниться прям с компов в посольствах или отелях, чтобы достать какую-то очень важную, но забытую бумажку.

Потом пошли звоночки. В 2016 Дропбокс выпустил Paper — свой редактор документов, типа Google Docs (на самом деле hackpad, конечно). Ну окей. При чем тут Дропбокс, синхронизация файлов? А ни при чем, просто сделали вот. Ладно. Не помогает, но вроде как и не мешает.

Ага-ага, как-то так и проходят все наши рабочие совещания. Собираемся вокруг стола и коллаборативно редактируем документ, каждый со своего телефона/планшета/ноута. Разговаривать тоже не разговариваем, прям в комментах переписываемся. Зачем покидать интерфейс, если он такой секси? (выглядел он и правда не так старперски, как Google Docs)

И вот в 2017 Дропбокс делает редизайн. Прикольно, свежо, но... При чем тут Дропбокс, опять же?

Поясню. Гений дизайна Дропбокса в том, что это абсолютно утилитарная штука, которая очень-очень нужна и которой почему-то не было. Тот редкий случай, когда вещь продает ТОЛЬКО ее функция. Ну типа как соль, или картошка — сколько ее не рекламируй, купят ее ровно столько, сколько нужно дома. Поэтому хороший дизайн облачного диска — максимально невидимый дизайн. У него не должно быть интерфейса, иконки, сплеш-скрина, емейл-рассылок, попапов, нотификаций. Ты не должен про него вспоминать в принципе. Пока он выполняет свою фунцкию, это просто часть компьютера, чем невидимее, тем лучше.

Ну и стало понятно, что надо валить. Дропбокс собирается превращаться из невидимой штуки в громкий, назойливый, кричащий ПРОДУКТ, наворачивать продажи, растить юзер базу всеми правдами и неправдами, короче, всячески о себе напоминать. А мы этого не хотим.

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

А вот и линеечка продуктов на 2019. Скупай-поглощай!
А вот и линеечка продуктов на 2019. Скупай-поглощай!

И вот в начале года покупаю я себе новенький телефон. Ставлю привычно Dropbox. И что вижу? Дропбокс теперь может работать только на 3-х устройствах!!! А у меня УЖЕ девять, и это я не особо старался. По мелочи в основном.

Тут надо упомянуть про бизнес-модель того самого Дропбокса. Я, при всей моей гигантской к нему любви денег ни разу не заносил. Потому что у них совсем дебильная сегментация — либо сиди на бесплатных 2 Gb, что конечно преступно мало, либо покупай сразу 2 Tb за 120 Eur/year, что как бы чуть больше чашки кофе. А посередине ничего нет. Так что я сидел с бесплатным.

Помню, в какой-то момент я даже табличку составлял, в которой считал, какой хостинг эффективнее. Кроме Google Drive, конечно, им в принципе нельзя пользоваться, его как будто студенты писали. Сейчас не знаю, но пару лет назад у него на Маке иконка была кривая и не-ретиновая!

Это на 2015 год
Это на 2015 год

Короче, надо мемуар этот сворачивать. Выбрал Эппл. Типа, у меня и так все устройства Эппл, последним как раз новый телефон стал, плюс у них 50 Gb всего за 59 руб./мес, типа, в 10 раз дешевле. Я, как человек, десять лет умещавшийся в 7 Gb Дропбокса, больше и не прошу!

Это был stupidly good deal, и план был безупречен. Уж Эппл-то не будет пихать фичи в синхронизатор файлов! Уж Эппл-то сделает его настолько ненавязчивым, насколько это возможно.

Сделал. Блин. Я в него все перенес. Рабочие проекты, документы, поездки — все, как я привык, тока теперь в Эппле. И что?

Во-первых, если Дропбокс находился в ~/Dropbox, то где находится iCloud Drive? Конечно же в ~/Library/Mobile Documents/com~apple~CloudDocs. Мало того что это хрен напечатаешь, хрен изменишь, мало того что это чисто эстетически некрасиво, в пути есть еще и пробелы! А что у нас происходит, если какой-нибудь bash-скрипт обнаруживает себя в папке с пробелами? Правильно, он обсирается! Что предсказуемо со мной и случилось.

Ладно, но мы же умные. Хардлинков в APFS нет, но есть Soft links. Линкуем ~/Library/Mobile Documents/com~apple~CloudDocs в ~/iCloud и вуаля! Теперь это можно хотя бы набрать в терминале. Но! Особо умные скрипты делают что? Сначала резолвят себя до канонического пути, а потом уже обсираются!

Смешно? Мне не очень. Раньше я хранил Fira Code (которая билдится через venv) и tonsky.me (bundler) в ~/Dropbox/ws, с iCloud я теперь так не могу. И ничего, ничегошеньки сука с этим не сделаешь!!! Как бы мне ни хотелось сказать, что фиксить эти проблемы должны разработчики тех скриптов, а не Эппл, какого-то конкретно виноватого здесь нет, а до всех не достучишься. Увы, это уже просто факт жизни — папки с пробелами в шелле не работают. Привет изобретателям shell command language. Текст победит!

Но и Эппл тоже молодцы. Что мешало положить iCloud Drive в нормальное место? Да ничего не мешало! Но мы же умные, думаем outside of the box. Поэтому положим его хрен знает куда, чтобы ты не мог найти свой диск ни в каком файндере или терминале, а потом, осознав что людям может все-таки понадобиться в него заходить, потому что нахрена мне диск в который я ничего не могу положить/достать, накодим еще миллион строк кода чтобы в файндере была специальная иконка, в диалогах iCloud рисовался тоже отдельно, типа это что-то специальное. Ау, это просто папка!

Кстати, знаете, что будет, если попросить macOS синкать содержимое вашего рабочего стола через iCloud? Нет, она не начнет его синхронизировать. Как говорили в великом Generation Kill, “That would be not retarded enough”. Она ваш десктоп тоже спрячет в свой говнопуть так, что никак кроме опять же специально обученного файндера вы его не найдете. То есть это ломает все, абсолютно все альтернативные способы навигации по ФС, начиная от терминала, конечно, продолжая альтернативными файл-менеджерами, не-нативными диалогами, кросс-платформенным софтом. Просто потому что fuck you, that’s why.

Ладно. Во-вторых. У него реально нет интерфейса. Ну то есть прикольно, конечно, все максимально прозрачно, но если например сейчас не очень подходящий момент для синхронизации (слабый wifi или раздаешь с мобилы), то нет кнопки, чтобы поставить iCloud на паузу. Положил гигабайт на другом компе неделю назад — будь добр выкачать! На слабых ноутах это еще и ставит систему раком. Терпи.

В третьих, я же тут не один живу! С Дропбоксом у нас в семье выработалась система, когда мы шарим все документы и билеты через общие папки. Удобно, всегда под рукой, всегда знаешь где смотреть.

Ну и с iCloud хотелось бы устроить так же. Иду я значит шарить папки. Низя. Не желает ли милорд проапгрейдиться до Семейного плана за жалкие 200 rub/month. Ну ладно, не совсем то что я хотел, но уже как бы ввязался до определенной степени. Че уж, раскошелимся. Раскошелился. Создал семью. Стал организатором.

Иду в Files. Жму Share (потому что у Эппл традиционно все функции прячутся в Share, это типа More). Ну как бы ничего не вижу. Ладно. Читаю. Пишут, а Share-то и нет! Вселенский фейспалм. Не сделали. Эппл. Не сделали. Ололо. Вся моя схема разом рухнула. Два iCloud Drive-а не подключишь. Под одним аккаунтом не зайдешь, потому что: ИНТЕГРАЦИЯ! ЭКОСИСТЕМА! Если ты не хочешь одновременно с этим также читать чужие сообщения и пароли, лучше все-таки логиниться каждому под своим аккаунтом.

И вот о чудо. В какой-то статье читаю, что это ПОКА нет шаринга. Но типа будет. В iOS 13. Которая как раз выходит через неделю! Это конечно идеальный тайминг, потому что если бы я этого не прочитал, я бы точно что-нибудь разбил поблизости.

Ладно. Жду iOS 13. Выходит. Обновляю в тот же вечер. Иду в Share наутро. Не вижу никакого общего доступа. Но можно поделиться папкой через iMessage. Ладно, думаю, это же Эппл. Наверняка они как-то хитро это интегрировали, что все настолько самоочевидно и simply works (tm) что пока не загуглишь не поймешь. Шарю папку по iMessage. И что получаю?

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

Пора идти в Гугл для тупых. Оказывается. Оказывается. Оказалось, что планы на фичу были. Даже в бетах она вроде как была. Но Эппл передумал и убрал. До iOS 13.1. А я сижу у разбитого корыта. От Дропбокса ушел, а в Эппл не пришел.

Самое обидное знаете что? Что для шаринга папок и делать-то ничего не нужно. Точнее, все уже сделано. У вас уже полноценная синхронизация между N устройствами. Добавить еще одно, независимо от того, кому оно принадлежит, ТЕХНИЧЕСКИ не представляет никакой проблемы. Технически это просто еще один клиент, точно такой же, как все остальные.

Но мне кажется я знаю почему эта фича так долго откладывается. Дело в том, что инженеры—наберите сейчас праведного гнева в грудь—инженеры Эппла решают, куда бы еще хитрее запрятать шареные папки. А то ~/Library/Mobile Documents/com~apple~CloudDocs слишком уж быстро вычислили.

UPD: 13.1 вышел, шаринг не добавили, отправку папок zip-архивом отключили обратно. Удивляться не приходится :(

UPD2: С момента написания поста iCloud отказался в критически важный момент загружать документы на телефоне (при прекрасном LTE коннекте). Просто крутил ползунок как дебил битый час и все. Apple Photos, как оказалось, не умеют шарить фотки. Так что моя логика «все равно за iCloud платить, т.к. там фотки с айфона хранятся» разлетелась в щепки. Ну что же, пора снова составлять табличку и выбирать провайдера, походу.