• Три часа

    Хорошо, если бы режиссерам кто-нибудь объяснил: три часа для фильма — это много.

    Что бы ты ни добавил, какой бы сюжет ни закрутил, какую бы графику ни навертел — получится затянуто.

    Все трехчасовые фильмы, на которые я ходил, были затянуты. “Однажды в Голливуде” — затянуто, занудно. “Довод” — затянуто, занудно. Нелепые сцены, ответвления сюжета. Второй “Аватар” — затянуто, одно да потому.

    На “Дюну” и что-то другое кассовое я не пошел, потому что научен опытом. Взяли любимую игру детства и поставили в трейлер Pink Floyd — искушение было сильно, но нет. Три часа — это знак, что режиссер не смог упокавать образы во что-то емкое и решил проблему количеством, а не качеством.

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

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

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

  • HTMX

    Этот пост — попытка объединить заметки об HTMX в Телеграме во что-то целостное. Написать статью о нем за один подход не вышло, поэтому пришлось по частям.

    HTMX — это библиотека для серверного рендера HTML. От современных React и Vue она отличается тем, что не хранит состояние на клиенте и не занимается рендером на JavaScript. Она посылает запрос к серверу и получает кусок HTML — в особых случаях несколько кусков, — которые вставляет в нужное место DOM.

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

    Htmx — не единственная в своей области библиотека. Есть еще HotWire, LiveView и другие. Под HTMX я имею в виду не конкретную библиотеку, а серверный рендер в принципе; просто HTMX звучит короче.

    Первая заметка об HTMX касалась числа запросов на сервер. Порой говорят: HTMX требует больше запросов, потому что забирает состояние с сервера. А в React-приложении ты выгреб состояние и хранишь на клиенте — улыбаешься.

    Это неправда. Когда в HTMX открываешь диалог, происходит один — и только один — запрос. Когда открывается диалог в приложении на Vue, происходит 14, — прописью, четырнадцать — запросов. Буквально на днях я правил фронтенд по работе, и там был именно такой случай. Цифры я взял какие есть, без преувеличений.

    Другой пример: дашбоард сайта Use Multiplier совершает 235 запросов. Если отфильтровать по слову “graphql”, останется 35 запросов. Выходит, JavaScript-разработчикам нужно 35 сетевых сессий, чтобы построить документ. Не многовато ли?

    Что же выгодней: один запрос или их десятки?

    В такие минуты искренне желаю, чтобы фронтендеров заменил HTMX. Они делают интернет хуже: больше запросов, больше трафика, больше расход CPU, дольше время ожидания. Таким разработчикам не место в профессии.

    Вторая мысль об HTMX такая: часто говорят, что это “хайп” (в кавычках, потому что не люблю это слово). Очередная вещь, которая пройдёт зенит и уйдёт из повестки.

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

    В этом году исполняется 10 лет с публикации исходного кода React.js. У Реакта и аналогов было достаточно времени, чтобы показать себя. Результаты есть, но не ошеломительные. Да, по сравнению с Backbone.js делать интерфейс стало проще, однако рано или поздно все сводится к одному: проект тонет в каше из компонентов, а состояние разбросано, как субстанция, попавшая на вентилятор.

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

    За эти десять лет мы получили одно — возросшую сложность разработки. Современный сайт обязательно содержит пачку npm-модулей, их сборщик, компоненты на React/Vue и бог знает что еще. В каждой фирме эту кухню готовят по-разному; вся она глючная и хрупкая.

    Еще печальней, что фронтендеры, получив инструменты, не научились ими пользоваться. Фронтам нужно 35 запросов Graphql на страницу; 14 запросов на открытие диалога. Одна и та же сущность запрашивается по пять раз. Это полная капитуляция, расписка непригодности разработчика. Если нужно 35 запросов на страницу, в команде не думают о качестве, а просто закрывают тикеты. Это просто данность.

    За это время я видел только одну удобную обертку над React — это кложурный re-frame. В нем скрыли острые углы Реакта и свели разработку к простому принципу: база, подписка, событие. Просто настолько, что дальше уже невозможно. Конечно, и на re-frame можно сделать проект неподдерживаемым, но кривая сложности у него более покатая.

    HTMX и его аналоги — это отказ от всего, описанного выше. Это отказ от хрупких npm/js-артефактов. Это отказ от команды фронтендеров, которым платят 10-20 тысяч долларов в месяц — на эту сумму можно купить тысячи машин в облаке. Это отказ от сложности коммуникаций, когда бекенд выкатил фичу, а фронты доберутся до нее через месяц. Это отказ от двух источников правды — сервера и состояния на клиенте — в пользу одного. И много от чего другого отказ.

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

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

    Серверный рендер по существу очень прост. Сервер выдает HTML, который вставляется в нужное место DOM. Кустарная реализация занимает не более ста строк, поэтому неудивительно, что серверный рендер тихо делает свою работу — без кричащих статей на Hacker News, звезд на Гитхабе и остального.

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

    Не каждый знает, что серверный рендер был одно время в Твиттере. Первые 20 твитов грузились как часть страницы, а при скролле выгребались куски HTML, в которых были новые 20 твитов и так далее. Хорошо это помню, потому что у меня был пет-проект по парсингу Твиттера. С HTML было относительно удобно: распарсил, прошелся Xpath-селекторами и готово. Серверный рендер в Твиттере ввели после того, как люди стали массово жаловаться на клиентский рендер — он был столь ужасен, что пара вкладок раскручивала вентиляторы на полную.

    Пользуясь случаем, скажем отдельное спасибо фронтендерам за это.

    Кроме Твиттера, серверный рендер использовал ваш покорный слуга. Было это 13 лет назад в Чите, в славной компании ООО Энергосбыт. Возле моего кабинета стоял терминал для показа каких-то роликов. Я решил сделать из него облегченную версию личного кабинета без авторизации. Вводишь лицевой счет и номер квартиры и видишь задолженность и показания счетчиков. Можно передать текущие показания. Принять деньги, увы, было нельзя из-за отсутствия купюроприемника.

    Интерфейс терминалов — это обычный Хром, запущенный с ключом --kiosk (по крайней мере раньше он так назывался). В режиме киоска браузер растягивается на весь экран, прячет курсор и противится попыткам свернуть его или открыть системные менюшки. Беда в том, что если во время запроса обрывалась связь, Хром показывал страницу “Oh no!” с диназавром, и нужно было нажать кнопку “Обновить”. Сейчас Хром обновляет ее по таймауту, а тогда нет.

    Ясное дело, я не мог бегать каждый час к терминалу смотреть, все ли с ним в порядке. Нужно, чтобы все работало на аяксе, но одна мысль об этом бросала в ужас. На дворе 2009 год, никаких реактов нет и в помине. jQuery в зените популярности, развивается Backbone.js — попытка навертеть MVT-фреймворк поверх jQuery. Окинув этот зоопарк, я решил задачу проще: на каждый запрос отвечал куском HTML, который вставлялся в центральный элемент на странице. Это было неоптимально, потому что в обновлении нуждались не все элементы, но разницы не было.

    В итоге я контролировал все на сервере, а клиент был минимально прост. Разработка заняла неделю, и вскоре терминал стоял в самом проходном месте города. Им пользовались, все было хорошо. Ради интереса представил разработку сегодня: npm/yarn, React/Vue, папка node_modules, хрупкие сборки и конечно компоненты, компоненты, компоненты. Команда фронтендеров, недели и месяцы работы. Неподдерживаемый результат в конце, смена команды и переписывание.

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

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

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

    Второй момент — с HTMX усложняется серверный рендер. Раньше вы отдавали данные клиенту, а как он их выводил, вас не касалось. А теперь вы за это в ответе.

    Предположим, вы достали из базы число покупок пользователя. Чтобы вывести фразу “У вас X покупок”, нужно учесть случаи:

    • X равно нулю или NULL, и тогда фраза будет “у вас нет покупок”;

    • учесть множественность: “1 покупка” и “N покупок”;

    • для второго случая учесть склонения: “3 покупки, 5 покупок, 21 покупка”.

    Нужно писать функции, таблицы склонений, стемминг и остальное. Что-то есть в библиотеках, но без их адаптации не обойтись.

    Еще интересней даты и форматы чисел, валют. Раньше ты выплюнул JSON с Unix timestamp, и остальное тебя не касается. А теперь, перед тем как рендерить, нужно узнать локаль пользователя — из запроса, кук или сессии — и передать ее во все подобные функции. Это усложняет процесс.

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

    HTMX усложняет обработку ошибок. Если что-то пошло не так, нужно вывести сообщение внутри элемента или в отдельной области при помощи техники OOB — out of boundaries. Это когда сервер возвращает несколько HTML-элементов, и они вставляются в разные места страницы. Кроме того, можно задать реакцию на неудачный AJAX-запрос на уровне библиотеки. Я не буду подробно все расписывать, скажу лишь, что об обработке ошибок в HTMX нужно думать с самого начала и придерживаться одного подхода. Иначе будет разброд и шатание.

    Тесты. Одно дело тестировать JSON, другое – HTML. Его нужно парсить, обходить проблемы склонений и форматов, применять рекулярки и XPath. Все это менее удобно, чем данные в JSON. Схемы – ваш лучший друг в случае с JSON, а какие схемы могут быть в HTML?

    Последний и наиболее важный недостаток — это двойной API. Как правило, бекенд предоставляет апишку не только сайту, но и мобильному приложению и третьим фирмам. Удобно, когда бекенд — это чистое API, и все это понимают.

    Теперь вы приходите к начальству с предложением сделать HTMX-апишку для серверного рендера. А зачем? — спросит начальство. На бекенде у нас REST/GraphQL, пусть сайт и ходит к нему через API. Этот довод почти невозможно проломить, потому что все сходится: бекенд общается с миром через JSON, у каждой платформы свой клиент. Что можно ответить?

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

    Поэтому не в каждой фирме дадут добро на серверный рендер. Протащить его в прод — та еще задача.

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

    Для начала вспомним React и Vue. Сильно упрощая, можно сказать, что их работа сводится к следующему. Мы переносим состояние с сервера на клиент и показываем в браузере. В теории нам не нужно беспокоится от отрисовке: реактивные фреймворки делают это за нас, когда мы изменяем состояние.

    Звучит хорошо, но таким образом мы завязаны на состоянии. Каждый, кто немного программировал, знает, что самое сложное — контролировать состояние. Поэтому так популярны Advent of Code и похожие задачи: для программистов это своего рода отдых. В них почти нет состояния: тебе дают одну структуру данных, и ее нужно переколбасить в другую. Нет базы, Кафки, Редиса и всего этого.

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

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

    Давно я читал в интернете: отдайте клиенту его данные, и пусть делает что хочет. Это не работает хотя бы из-за размера данных. Представим, вы активно пишете на каком-нибудь Твиттере или StackOverflow. За три года у вас скопилось 10 тысяч заметок. Вы хотите вывалить их клиенту при загрузке страницы? А заодно его друзей, рекомендации и прочее?

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

    Все это мартышкин труд. Вы никогда не угадаете, что конкретно нужно клиенту в текущий момент. Выгружать все — дорого и долго. Остается запрашивать данные точечно: последние 10 статей, последние 50 комментариев. А если порции данных небольшие, зачем их хранить, если можно просто показать? Так мы уберем состояние, из-за которого одни сложности.

    Ликвидация состояния — важный шаг вперед: управлять клиентом становится проще. Помните аналогию с Advent of Code и функциональными языками? С HTMX я испытал похожие чувства. Да, оказывается, так можно: отдаешь HTML, который без какого-либо состояния отображается на клиенте.

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

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

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

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

    В компаниях, где процесс налажен правильно, он протекает так. Дизайнер делает макет в Фигме или иной программе. В ней указаны состояния страницы и сценарии перехода. Например, при нажатии на кнопку “добавить в корзину” четко указано, какие элементы изменятся и на что.

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

    Бекендеры принимают нарезанный HTML и оживляют его на сервере. При этом им запрещена любая отсебятина. Если бизнес-процесс не вписывается в дизайн, все трое — дизайнер, верстальщик, бекендер — собираются и решают, что исправить. Исправления вносятся во все три источника: дизайн, верстку, бекенд.

    При таком подходе принцип HTMX остается в силе. Бекендеры не выдумывают дизайн на ходу, они действуют в рамках, которые ставит им дизайнер. Верстальщик служит промежуточным звеном между дизайном и его реализацией на бекенде.

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

    Так был устроен процесс в Wargaming, где я когда-то работал. И хотя там были свои косяки, мне кажется он единственно верным. Что ещё в нем хорошего — он не привязан к конкретным технологиям, и HTMX отлично на него ложится.

  • HDMI в тренде

    Раз в полгода телевизор докладывает, что сегодня в тренде… порт HDMI 1. При этом ни в один из HDMI портов ничего не воткнуто. Откуда он это берет? Неужели настоящие данные, собранные с устройств — люди играют в приставки, смотрят пиратки с ноутбуков?

    Этот порт, как говорит телевизор, “недавно в…”. Очень полезные сведения. Еще бы понять, что значит “в…”. Калека-дизайнер оставил квадрат пустым, а на текст выделил сотую часть. Не влезло, но ничего: обрежем и добавим многоточие.

    Забавно, как текут абстракции: в понимании телевизора порт HDMI — это приложение, поэтому участвует в трендах. Напоминает одну игру, где можно было чинить лошадь гаечным ключом. А что, транспорт, значит можно чинить.

    Проблема “умных” вещей в том, что они пытаются быть умнее, чем есть на самом деле. Нет-нет и вылезет какая-то тупизна, от которой нет слов. Только вздохнёшь и идёшь дальше.

  • Нейромазня

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

    Верю, что доживу до момента, когда нейросеть объяснит, зачем мне этот кот. В какой текст его вставить, к чему подавать и что им объяснить.

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

    Чувак пишет статью о четвертом измерении и ставит такое:

    Какой-то алмаз, в нем пузыри, блики, крошки, капли смолы, планеты.

    Другая картинка: вензеля, стекла, то ли башня, то ли корабль. Что это вообще?

    Конечно, у женщин осиная талия и шестой размер груди. И нет трусов. По улице только такие и ходят.

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

    Как вы уже поняли, ничего полезного в нейромазне нет. Это мусор, который заполняет интернет, и нет от него спасения.

    Пара ссылок про иллюстрации:

  • Списки в In Design

    Опять Индизайн. Уж наверное, если сделали длинный список, нужно упорядочить его по алфавиту, нет? Секунд двадцать искал пункт Units в подвале, а он еще до середины находится. Интересно, что глаз скользит по списку, замечает Units, и тут же теряет, потому что мозг ожидает его не там. Сущее издевательство.

  • Удаленка, но есть нюанс

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

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

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

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

    Может быть, вы пошли на обед, обдумывая новый сервис. В это время тимлид и коллега из офиса тоже пошли в “Жареный жир” и славно поболтали. К возвращению в офис уже все решено, формальности обговорены. На следующий день на созвоне вы излагаете свое видение сервиса, не зная, что в этом нет смысла. Вас вежливо выслушают и скажут, что решение отличное и его приберегут для будующих проектов. А пока что Джон уже приступил к разработке, и мы с нетерпением ждем.

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

    Бывают, конечно, и маленькие победы: путем рефакторинга удается заменить самописный треш на библиотеку или, наоборот, отказаться от жирной библиотеки в пользу десятка строк. Если в фирме совсем все плохо, правильные решения говорят лучше тысячи слов. К примеру, нормальное тестирование, которое можно развернуть локально, не прибегая к удаленным машинам; линтинг, внутренний гайд разработки и прочее.

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

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

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

  • Запуск InDesign

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

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

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

    В итоге сидишь и тупишь в пустоту, пока что-то там не загрузится. Однако если нажать Ctrl+O, откроется диалог выбора файла. Выходит, программа прекрасно работает, даже если главный экран не загрузился! Если выбрать в диалоге файл с проектом, он откроется мгновенно. Можно не ждать эти 10 секунд, а открыть файл ручками и работать. Это подтверждает второе видео:

    Такие вот интересные программы Адоба.

    Чем-то это напоминает современные веб-приложения: программа загрузилась, но это присказка, не сказка. Мы только загрузили скрипты, далее они выгребут свое дерьмо с серверов и только затем покажут приложение. На телевизорах такое постоянно: первый прогрес-бар показывает загрузку приложения на уровне ОС, а приложение запускает второй прогресс-бар для загрузки своего барахла.

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

    Подозреваю, что упомянутый главный экран — ничто иное, как Хром + Node.js + React. Это видно по косвенным признакам: он похож на Слак и прочие поделки, которые не могут быть отрисованы частично, а только целиком. Возможно, скрипты ломятся в сеть, но блокируются из-за санкций или бог знает чего. Ожидание в 10 секунд похоже на таймаут, заданный при отправке HTTP-запроса. Спасибо, что хотя бы выставили его: по умолчанию он равен 30 секунд.

    Странно, что последние файлы отображаются внутри браузера, хотя никак не связаны с ним. Это банальная глупость, деградация разработки. Надо сказать, я не удивлен. В Адобе много что делают на Node.js, например дашборд, из которого ставятся приложения. Я как-то шарился по папкам и нашел ворох скриптов. Плюс часто выскакивает диалог с текстом “приложение node хочет доступ к такому-то сертификату.”

    В сотый раз повторю тезис: сапожник без сапог. Фирма, которая тридцать лет пишет настольные программы под Винду и Мак, не может нормально показать последние файлы. Для загрузки приложений делается поделка па Хроме и Js, глючная и тормозная. Деградация софта в угоду менеджменту: сделать тяп-ляп, но зато быстро и получить повышение.

    Хочется верить, что индустрия печати пересядет с иглы Адоба на что-то другое, но пока что просвета не видно.

  • Avoid code you cannot debug

    This is a small tip I’d like to share with Clojure programmers.

    In a project, avoid code you cannot debug. It’s simple: if you can put a tag like #debug or similar somewhere in the middle, run a test and hang in a debugging session, you’re good. But if you cannot, you’ll be in trouble one day.

    Thus, any kind of DSL or yet another “smart” solution is a source of potential problems. Take Meander, for example. Imagine I have a map like this:

    {:name "Ivan"
     :address {:city "Chita"}}
    

    and I want it to become this:

    {:name "Ivan"
     :city "Chita"}
    

    With Meander, I would write:

    (m/match
      {:name "Ivan" :address {:city "Chita"}}
      {:name ?name :address {:city ?city}}
      {:name ?name :city ?city})
    

    and it works fine. But one day, my datasource suddenly returns a user without an address:

    {:name "Ivan" :address nil}
    ;; or just {:name "Ivan"}
    

    which is completely fine because a user might have no address associated with them. By passing that map into m/match, I expect it to return {:name "Ivan" :city nil} but no: there will be an exception:

    (m/match
       {:name "Ivan" :address nil}
       {:name ?name :address {:city ?city}}
       {:name ?name :city ?city})
    
    Unhandled clojure.lang.ExceptionInfo
       non exhaustive pattern match
       {}
    

    The line “non exhaustive pattern match” tells nothing to me nor the ex-data does. The message is fuzzy, there is no context, the ex-data has nothing useful (it’s an empty map). Having such an entry in logs or Sentry would not help you in a bit.

    Moreover, you cannot debug it. The m/match macro expands into a huge block of code. Debugging it somewhere in the middle would be quite challenging.

    Now compare it with a plain function that splits the data step by step:

    (defn remap-user [entry]
    
      (let [{username :name
             :keys [address]}
            entry
    
            {:keys [city]}
            address]
    
        {:name username
         :city city}))
    

    First, it works with both maps:

    (remap-user {:name "Ivan"})
    => {:name "Ivan", :city nil}
    
    (remap-user {:name "Ivan" :address {:city "Chita"}})
    => {:name "Ivan", :city "Chita"}
    

    Second, I can always put a debugging tag into that function and observe the local variables, the state and even run some expressions. With Meander, it’s just impossible or only possible with certain effort.

    Third, if a city is required, I’d put something like this:

    (assert city "The city is missing")
    

    and get a clear exception I want.

    Vast Meander patterns are completely unmaintainable. Pass something weird and you’ll get a “non exhaustive pattern match” message with no idea about what went wrong.

    Finally, debugging is crucial. If you cannot hang in the middle of execution and observe the state, that’s bad. Most Clojure programmers believe it’s a special language liberating you from debugging errors, but it’s not true. Debugging has not gone anywhere even with such a great language as Clojure.

  • Пауза в Ютубе

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

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

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

    Спрашивается, почему бы не вынести кнопки в отдельную полосу? Да, они займут место, ну и что? Почему проблему интерфейса рашают за счет контента? Почему интерфейс налазит на видео, вместо того чтобы быть снизу?

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

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

    Кстати, один из способов решить эту проблему — смотреть Ютуб в VLC, о чем я писал раньше. Слегка экстремально, но проблемы субтитров нет.

  • Корректура в PDF

    Если кто не знает, откуда столько ненависти к PDF, сейчас объясню.

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

    Один раз я даже писал про возможности Preview по работе с PDF, но все это уловки для бедных, когда нет исходника.

    Тезис о том, что с PDF нельзя работать как с документом, подтверждает следующий опыт: середина 2023 года, тридцать лет с момента появления PDF — и не найти программы, которая бы работала с ним без ошибок.

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

    Теперь самое интересное. Внос правок сводится к шагам: перешел к очередному комментарию, поправил исходник, удалил коммент. Что же пошло не так? А вот что.

    Preview на Mac M1 не может удалить некоторые комментарии. Те, что с типом Highlight — да, а Note — нет. Специально проверил, старый Preview на Интеле может, но поведение неочевидно. В целом работа с аннотациями в Preview глючная: коммент может висеть еще долго после удаления. Иногда фокус смещается произвольно и удаляется не тот коммент.

    Не все это можно передать в картинках, но например: слева у комментария есть опция удаления, а справа у Note — нет.

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

    Вы скажете — браузер. Не вопрос, открыл в Хроме, а там такое:

    Плюс комменты нельзя удалять, read-only.

    Может, Акробат наше все? Ну, уже сам факт, что установка требует sudo, внушает опасения. Ладно, поставил. Документ не открывается перетаскиванием в программу — только File -> Open, только хардкор. Удаление комментов работает, но если скопировать текст из PDF, получим такое:

    Âòîðàÿ ãëàâà ïîñâÿùåíà ðåëÿöèîííûì áàçàì äàííûõ,
    

    Словом, кто вносил корректуру, тот в цирке не смеется.

    Повторю тезис из начала заметки: любая работа с PDF — это боль по определению. Он специально сделан так, чтобы правки были максимально затруднены. Бинарный формат, девять редакций, адское легаси. Любая программа, которая предлагает редактирование PDF — это н…балово. Оно работает только в примитивных случаях, а как что-то серьезней — сплошная беда.

    Поэтому, кстати, я считаю, что корректор, который не работает с бумагой — это слабый корректор. Хороший как минимум не должен ее избегать.

    UPD

    Продолжение заметки. Добрые люди подсказали два варианта: PDF Expert и Master PDF Editor. Первая не обслуживает пользователей из России, но ставится из brew. Оказалось, она не работает без облачной учетной записи. Попап закрывает интерфейс, хоть усрись, но создай учетку. Скриншот не сохранил, прогу удалил. Поставил Master PDF Editor, на первый взгляд все отлично. Посидел два часа, вносил корректуру. Сохранил файл и перекинул на другой комп. Открываю, а там:

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

    Эту работу я как-нибудь доделаю, но она стоила много нервов. Очень, очень много нервов.

Страница 11 из 74