-
PG docs, part 3
(This is a new documentation chapter from the PG project.)
ToC
Connection Pool
- Basic usage
- With-pool & with-open
- Config
- Thread safety
- Pool Exhausting
- Exception handling
- Logs
- Component
To interact with a database effectively, you need a connection pool. A single connection is fragile on its own: you can easily lose it by an accidental lag in the network.
Another thing that is worth bearing in mind is, that opening a new connection every time you want to reach PostgreSQL is expensive. Every connection starts a new process on the server. If your code opens too many connections, say in a cycle or within threads/futures, sooner or later you’ll reach an error response saying “too many connections”.
The connection pool is an object that holds several open connections at once. It allows you to borrow a connection for some period of time. A borrowed connection can be only used in a block of code that has borrowed it but nowhere else. Once the block of code has done with its duties, the connection gets returned to the pool.
The pool is also capable of calculating the lifetime of connections and their expiration moments. Once a connection has expired, it gets terminated and the pool spawns a new connection.
The connection pool is shipped in a dedicated library
com.github.igrishaev/pg-pool
as it depends on the logging facility. -
PG docs, part 2
ToC
In this chapter, we’ll discuss how to reach Postgres using the Client library.
- Basic usage
- Queries
- Execute
- Prepared Statements
- Processing result with :fn-result
- Column names
- Column duplicates
- Reducers and bundles
- Transactions
- Configuration
- Authorization
- Cloning a connection
- Cancelling a query
- Notices
- Thread safety
- Debugging
Basic usage
Here is a brief example of using the client library:
(ns scratch (:require [pg.client :as pg])) (def config {:host "127.0.0.1" :port 5432 :user "test" :password "test" :database "test"}) (pg/with-connection [conn config] (pg/query conn "select 1 as one")) ;; [{:one 1}]
First, you import the
pg.client
namespace which brings the top-level API functions to interact with Postgres. Theconfig
map above specifies the minimal configuration; it might have more fields which we will explore in a separate section.The
with-connection
macro establishes a new connection, binds it to theconn
symbol, and executes the body. The connection is closed afterward, even if an exception pops up.Technically you can open and terminate a connection manually like this:
(let [conn (pg/connect config) data (pg/query conn "select 1 as one")] (pg/terminate conn) data) ;; [{:one 1}]
but it’s not recommended. Also, since the
Connection
object implementsjava.io.Closeable
, it’s possible to use it inwith-open
:(with-open [conn (pg/connect config)] (pg/query conn "select 1 as one")) ;; [{:one 1}]
-
PG docs, part 1
TL;DR: I’m writing a Postgres driver in pure Clojure. In general, works! Now I proceed with the most miserable part of the project: writing documentation. I decided to do it step by step and share it on my blog.
ToC
About
This project is a set of libraries related to the PostgreSQL database. The primary library called
pg-client
is a driver for Postgres written in pure Clojure. By purity I mean, neither JDBC nor any other third-party Java libraries are involved. Everything is driven by a TCP socket and implementation of the Posrgres Wire protocol. Fun!Besides the client, the project provides such various additions as a connection pool (see
pg-pool
). Thepg-types
library holds the encoding and decoding logic which determines how to write and read Clojure data from and into the database. You can use this library separately in pair with JDBC.next andCOPY
for efficient data transcoding in binary format.The question you would probably ask is, why would create a Postgres client from scratch? JDBC has been around for decades, and there are also good
clojure.java.jdbc
andjdbc.next
wrappers on top of it?The answer is: that although these two libraries are amazing, they don’t disclose all Postgres features. JDBC is an abstraction whose main goal is to satisfy all the DB engines. A general library that works with MS SQL, MySQL, and Postgres at the same time would reduce the variety of features each backend is capable of.
-
Анонс второй книги
Вышел второй том “Сlojure на производстве” — продолжение первой книги. Без той помпы, что в прошлый раз, когда я каждую неделю выкладывал апдейты, фото черновиков и прочее. На всё это не хватает времени, плюс хочется меньше пафоса.
В книге три главы, черновые версии которых я выкладывал в блоге. Это зипперы, базы данных и REPL. Всё это можно прочесть здесь на сайте, но каждую главу я многократно улучшил. Кроме банальных опечаток, изменилась структура, а примеры стали убедительней.
Книжка выполнена в том же стиле и манере повествования. Текст чередуется с кодом, каждый тезис подтверждается примером. Длинный код разбит на части с пояснением, что происходит. Код “подсвечен” с помощью градаций серого и начертания. Ссылки, коих много по тексту, вынесены в QR-коды на поля.
Твёрдая обложка, B5, 364 страницы. Форматы для мобильных устройств появятся позже. Издано в ДМК-Пресс тиражом в 100 экземпляров. Двадцать из них — мои, полученные в качестве гонорара, и я готов разослать их читателям.
Все подробности – где купить, открывок, галерея – указаны на странице книги.
-
Node.js
Удивляюсь, до чего же хрупок этот Node.js. Месяц назад я делал фронт на Vue, и настало время кое-что поправить. Обновляю пакеты, запускаю билд — сотня ошибок. Мудрил так и сяк, пока коллега не сказал — удали node_modules и все заработает.
Вот это “удали” меня поражает. Вместо того, чтобы решить корень проблемы, решают симптомы. Подумаешь не работает! Просто начни с чистого листа. Ситуация КРИЧИТ о системной проблеме, но никому нет дела. В платформу вливают огромные деньги, ей пользуются миллионы, и никто не может это починить.
Была б моя воля, я бы посадил разработчиков Node.js за компы и сказал: чини, но без удаления файлов. Найди источник проблемы и реши его. За удаление — пытка током на месте. И тогда бы все починили.
Помню, была та же беда в проекте с React Native, только хуже. Проект перестал собираться, и я по привычке удалил node_modules. Оказалось, в его недрах лежат бинарники для устройства, которые генерируется на старте. При повторной установке этот шаг пропускается, и где взять эти бинарники — неизвестно. На StackOverflow так и пишут — перед удалением скопируй такие-то файлы в папочку, иначе будешь плакать. Плакал я, конечно, уже после того, как это прочел.
Вы, наверное, подумали, что после удаления node_modules все заработало? Это было бы слишком просто. Я получил другие непонятные ошибки, и коллега предположил, что моя версия Node.js слишком высока. Проверили — да, у него 16, у меня 20. Но ведь месяц назад все работало на версии 20! Мало того, что за месяц случились такие изменения, так эти клоуны не оставили обратную совместимость! Не иначе как цирком с клоунами эту ситуацию назвать нельзя.
В целом Node.js вызывает ощущение, что убираешь какашки за годовалым ребенком. Те, у кого есть дети, знают, о чем я говорю. Когда делаешь это постоянно, ощущения притупляются, и можно спокойно чистить говно, жуя бутерброд. Разница в том, что к двум годам проблема с туалетом уходит, а с семи лет ребенок уже поддерживает чистоту сам.
Node.js, напротив, обречен срать под себя как инвалид. Если через восемь лет за ним нужно чистить какие-то папки, то, похоже, проблема не уйдет никогда. Бог с ним, пусть живет как хочет. Но непонятно, зачем с этим работать, и что в голове у людей, которые добровольно идут в разработку на Node.js.
-
Платежные системы
У платежных систем одна тонкость. Ты регистрируешься, подтверждаешь почту и телефон, прикладываешь скан паспорта и селфи, крутишь головой перед камерой, высылаешь все вплоть до анализов мочи — с тем, чтобы узнать: нужная функция недоступна в твоей стране.
Конечно, недоступна временно. Подпишись и мы пришлем уведомление. Уже вот-вот, буквально завтра.
Удалить аккаунт? Не можем: по такому-то закону данные хранятся пять лет, чтобы выдать по требованию властей.
Уже сто раз такое было, но вот опять — потратил полчаса на отрытие PayPal в другой стране, чтобы узнать, что там он ничего не умеет.
Регистрируясь в похожих системах, сперва нужно гуглить по словам “Service in Country limitations”.
-
Косплей
Почему-то люди не понимают: если нашел себе кумира, повторяй его поступки, а не внешность и поведение. Потому что иначе выходит косплей — костюмированное шоу.
Если нравится Стив Джобс, сделай Айфон. Если Павел Дуров — сделай соцсеть с той стеной, которую считаешь нужной. Если Лапенко — сними смешной ролик. Но не повторяй внешность или стиль общения в интернете. Это ужасно.
Точто так же не стоит повторять стиль жизни. Не надо вставать в пять утра, принимать контрастный душ, ходить босиком и медитировать. В мире полно людей, которые медитируют и не едят мяса, но не достигли ничего.
Между великими людьми вообще нет связи. Все они были молодыми и старыми, сатанистами и христианами, бабниками и девственниками. Связи нет никакой. Когда кто-то читает десять правил знаменитости, я не понимаю — зачем? Ведь известность из них не следует.
Доводилось видеть человека, который косплеил Дурова: челка, плащ до колен, все черное, взгляд мимо камеры. Он делал стартап, и было забавно видеть его за работой. Не знаю, чем кончилась его затея, но судя по всему — ничем.
Все это сказано цитатой о Стиве Джобсе. У Стива были две половины: одна — редкостный засранец, вторая — редкостный гений. Из-за второй половины ему прощали первую. Сегодня много людей косят под Стива, но у них получается первая половина — засранца.
Начинайте со второй половины.
-
Как в X
Совершенно ужасная вещь — писать на яыке X как в Y. Например, в Питоне как на Хаскеле, а в JavaScript — как в Кложе. Придумать какие-нибудь “элегантные объекты” и тыкать людям, что они живут неправильно.
Чемпионом в этой области является Питон. Из-за его гибкости на нем можно косплеить любой язык — хоть Хаскел, хоть Кобол. Скажем, выражение ниже можно сделать рабочим:
items = List[1, ...]
Для этого пишут особый класс
List
с метаклассом, у которого реализован метод__getitem__
. В нем проверяется, что если второй элемент — классEllipsis
, то возвращается ленивый список от 1 до бесконечности.Для Питона созданы сотни библиотек, которые косплеят другие языки — Хаскель, Скалу и другие. Я тоже отметился: написал либу с лаконичным названием f, где собраны плюшки Кложи: стрелочные операторы, мультиметоды и всякие мелочи.
Все это замечательно, если бы не одна деталь: оно никому не сдалось. До перехода в Кложу я работал с Питоном семь лет и ни разу не видел, чтобы использовались функциональные поделки. Промышленные проекты на Питоне — это скучный ООП-код без map/reduce, монад и алгебраических типов. В точности так, как это видит создатель языка.
Точно так же в Кложе никто не использует монады. Уже в седьмой раз я устраиваюсь кложуристом и не вижу их в проде (и это хорошо).
В текущем проекте на Кложе беда — его начинали люди, которые знали ее синтаксис, но не идиомы. Другими словами, они знали, что вместо
1 + 2
надо писать(+ 1 2)
, но не знали, как устроить работу с базой, компоненты, тесты и окружение.Кажется, это были рубисты. Я не держал свечку, но это сквозит в коде. Чуваки написали свою ORM, которая матчит базу с REST — кривую и глючную. Для конфигурации используют переменные среды, и это тоже треш и содомия. Компоненты и система убоги. Позже в фирму пришли люди опытом на Кложе. Они либо обходят легаси — ходят в базу напрямую, используют свои решения, — либо прибегают к нему с легким отвращением.
Идиома “писать на X как в Y” — это проигрыш по определению. В любом виде. Это билет в один конец, и он всегда одинаков. Вы пишете “как надо”, но потом уходите, и другие с трудом приводят код в нужное русло. Не всегда удается сделать это полностью — иной раз авгиевы конюшни столь полны, что переделывать слишком дорого, и с этим как-то живут.
Легковестные агенты из Эрланга в Кложе. Элегантные объекты в Джаве. Монады вместо исключений в Питоне. Да, интересно, да, ярко. Но бесполезно.
Если идеи по-настоящему сильны, их нужно выразить в новом языке. Не устраивает чистый C — появляется C++. Не устраивают древние диалекты Лиспа — появляется Кложа. Не нравится бородатый Эрланг — пишут Эликсир.
На любом языке надо писать так, как в нем принято. На Руби — как в Руби, а не в Кложе. На Кложе — как принято в Кложе, а не в Руби.
Чем раньше это поймешь, тем скорее на тебя снизойдет благодать.
-
Три часа
Хорошо, если бы режиссерам кто-нибудь объяснил: три часа для фильма — это много.
Что бы ты ни добавил, какой бы сюжет ни закрутил, какую бы графику ни навертел — получится затянуто.
Все трехчасовые фильмы, на которые я ходил, были затянуты. “Однажды в Голливуде” — затянуто, занудно. “Довод” — затянуто, занудно. Нелепые сцены, ответвления сюжета. Второй “Аватар” — затянуто, одно да потому.
На “Дюну” и что-то другое кассовое я не пошел, потому что научен опытом. Взяли любимую игру детства и поставили в трейлер 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 отлично на него ложится.
-