-
Видео с митапа о Postgres
Появилась запись митапа:
Примерно час я рассказываю про всякие технические кишки, потом дискуссия с Николаем (CTO Самураев) и Владимиром (разработчиком JDBC-драйвера для Postgres).
Не обещаю, что будет интересно, скорее сильно на любителя.
-
Copilot и документация
Вчера провел с коллегой эксперимент.
Коллега подключил в редакторе Copilot и говорит — смотри, как круто он генерит комментарии к функции! Скажем, для функции
generate-time-buckets(account, time-frames)
пишет что-то вроде “generate time buckets for given account and time frames”.Мда, содержательно: для
generate-time-buckets
получить “generate time buckets”… Мне такой подход кажется малоинформативным: очевидно, Copilot берет сигнатуру и аргументы, конкатит их, разбивает на лексемы и причесывает, чтобы смотрелось по-человечески.Предложил эксперимент: пишем фукнцию, которая тупо складывает два числа:
return a + b
. Называем функциюdelete-file
и просим Copilot написать докстринг. Что он пишет? Правильно, “Delete а file”. Есть и второй вариант — “Delete a file from S3”, видимо, для корпоративных клиентов в облаке.Словом, теперь у нас ИИ-комментарии, а чего мы добились и какую проблему решили — не понятно.
-
Зачем спринты?
За все время работы в айти я не понял, зачем нужны спринты.
Как правило, спринт — это период от двух недель до месяца. В него набирают задач и пытаются их сделать к концу спринта. Потом спринты оценивают: этот был лучше, чем в прошлый раз, а этот хуже. Тут собрали двадцать стори-поинтов, а тут восемнадцать. Проводят ретро, которые убивают время.
Все это кажется мне бредом. Зачем делить время на равные участки? Зачем считать стори-поинты? Какое знание дает цифра 18 стори-поинтов? Чем это хуже, чем 20 поинтов?
В чем проблема, если задача из одного спринта переносится в другой? Кто от этого пострадал? Если задача не умещается в спринт, то может просто не впихивать невпихуемое?
Нужно обсудить процесс? Так проведи серию звонков 1 на 1 с разработчиками. Не обязательно ждать ретро.
В моем понимании процесс управляется релизами. Скажем, поставили мы задачу выкатить новый релиз через два месяца. Договорились, что в релиз войдет то, се, пятое-десятое. Не успеваем? Что-то упрощаем, что-то откладываем в следующий релиз.
Зачем нам спринты? Почему все следуют карго-культу гуглов-амазонов? Нужно думать своей головой, а не как менеджер Гугла.
UPD: сюда же относятся эстимейты. Воистину, самое тупое и бесмыссленое, что есть в айти. Эстимейтить все и вся, ошибаться на порядок и потом рвать задницу, чтобы успеть.
-
Шкала ООП
Когда говорят про ООП, упоминают всякие солиды, наследование и прочее. И не говорят вот про что (а надо бы).
Если в языке присутствует ООП, то типизация объектов размывается. Только структуры и функции дают четкие типы; объекты, наоборот, разрушают их путем абстракций. Они замыливают глаз.
Скажем, у нас есть классы
Dog
иCat
, унаследованные отAnimal
. Пока мы передаем собак и котов явно, все хорошо. Но когда мы передаем их как животных (Animal
), там может быть что угодно. В итоге на одни и те же данные смотришь по-разному.Если предположить, что
Animal
наследуется еще от чего-то, то получится шкала отObject
кDog
/Cat
, и как смотреть на объект — зависит от контекста. В некоторых случаях делают даун-каст и ап-каст: передают кота в виде объекта, а потом проверяют: если это кот, то одно, если собака, то другое, иначе эксепшен.Эту шкалу (
Object
—Animal
—Mammal
—Dog
) важно держать в голове и знать, где находишься сейчас. Лично мне она доставляет много хлопот, когда я пишу на ООП-языках, например Джаве. Шкала — это не вкл/выкл, а некая доля, позиция в в дереве, следить за которой сложнее.Может быть, кто-то лучше выразил эту мысль, но либо я не слышал, либо забыл.
-
Не люблю регулярки
Признаться, я не особо люблю регулярные выражения. Я знаю их где-то на троечку, время от времени применяю, но стараюсь, чтобы их было меньше.
Дело в том, что регулярные выражения — это сверхплотный, сверхкраткий язык описания шаблонов в тексте. Из его главного преимущества — краткости — следует главный недостаток. Когда регулярка больше какого-то порога, ее понимание и поддержка резко идут вниз. В этом случае следует отказаться от регулярки, однако в проекте запросто может оказаться маньяк, который накрутит еще пару этажей регулярок.
Другой момент — с регуляркой часто оказывается, что ты не все учел. Предположим, нужно искать в тексте числа с плавающей запятой. Вы написали регулярку, которая ищет числа вроде
-12.0042
. А потом оказалось, что у чисел может не быть целой части, например-.0042
. А еще оказались числа в научной нотации:-1.2E9
. И регулярку нужно допиливать, допиливать и накидывать тесты.У регулярок есть хорошее применение: ими удобно разбивать текст. Как правило, я разбиваю текст на части и проверяю, что их количество и содержимое чему-то соответствует. Это проще отлаживать, это лучше в плане сообщения об ошибке. Если текст не натягивается на монструозную регулярку, ты не можешь объяснить, что пошло не так. А если обрабатывать текст по частям, легко сказать, в чем проблема.
В одном из проектов у нас была библиотека для генерации регулярок. Это когда декларативно указываешь: либо это слово, либо это, либо то, но не это и не то, и библиотека строит одну регулярку. В ней учитываются общие начала слов, например для
fuck
иfuckoff
получимfuck(?=off)
. Выбрал такой пример, потому что фильтровали сообщения в чате. Было много других слов, значения которых я не знал и смотрел в словаре.Этот подход интересен тем, что регуляркам отводится служебная часть. Конфигурация делается словарями и списками, все ясно и прозрачно.
Вместо регулярок мне больше нравится парсинг грамматикой. Пару лет назад я прочитал пару статей про комбинаторные парсеры и решил сделать свой. В результате я написал огрызок, который назвал Ostap (потому что великий комбинатор). В библиотеке были простые парсеры и те, что составляются из других (and, or). Можно задать грамматику словарем и получить из нее парсер.
В результате у меня получилось составить грамматику JSON, и парсер разбирал произвольный JSON-документ. Правда, это было медленней джавного Jackson раз в десять, но за скоростью я не гнался. Почему-то зачесались руки сесть и переписать его на Джаве и собрать парсеры для JSON, INI, Tolm и других форматов.
Словом, регулярки хороши, но я предпочитаю держать их на расстоянии вытянутой руки. Чем они ближе, тем строже я слежу за ними.
-
Jira
Я считаю, работать в компании, которая пилит Джиру, это примерно то же самое, что работать в военкомате или Роскомнадзоре. Нормальному человеку, даже если он туда попал, будет стыдно, и он уйдет в другое место.
Современная Джира — это просто заповедник багов и косяков. Каждый ее квадратный сантиметр несет бред. Без шуток, по мотивам Джиры можно написать небольшую книгу о том, как делать не надо.
Из сегодняшнего: заполняю тикет, прикладываю кусочек кода. Пишу:
{code:clоjure} (dеfn do-some-shit [a b] (do-this {:a b})) {code}
Сохраняюсь и вижу:
Unable to find source-code formatter for language: clоjure. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, relange, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, swift, visualbasic, xml, yaml(dеfn do-some-shit [a b] (do-this {:a b}))
Иными словами: сообщение о том, что подсветка Clоjure не поддерживается, внедрилось прямо в код! Причем даже без переноса строки: код следует сразу за
...yaml
.Сначала я проклял всеми словами фронтендеров, но посмотрел в Network и убедился: это серверный рендер. Клиент посылает фрагмент, а сервер возвращает HTML. Поскольку это не JSON, некуда положить нотис о том, что язык не поддерживается, и ребята такие — давайте просто засунем его в код.
Каким же мудаком надо быть, чтобы протащить это в прод — я просто не знаю. И куда глядела армия QA, разные бета-тестеры и вообще сами сотрудники фирмы? Фееризм космического дна.
-
Сишные строки
Одна из самых худших вещей в айти — это сишные нуль-терминированные строки. Другими словами, цепочка байтов, которая завершается нулем. Керниган и Ричи были гениями, никто не спорит, но решение с нулем на конце трудно назвать удобным.
Беда в том, что, читая эту строку, никогда не знаешь, где конец. Сколько байтов резервировать — 32 или килобайт? Немало ошибок в сишных программах связано с тем, что неверно определяется конец строки.
Интересно наблюдать сишные строки в бинарном протоколе Postgres. В оригинальной его части строки передаются как в Си — то есть неизвестной длины с нулем на конце. Скажем, сообщение StartupMessage строится по принципу
u s e r n a m e 0 d a t a b a s e 0
А в расширениях, которые появились позже, строки передаются нормально: сначала длина в int32, потом байты без нуля:
0 0 0 5 h e l l o
Пример — расширение
hstore
, в нем строки передаются с фиксированной длиной. Видимо, разработчики поняли, что жить с нулем на конце нельзя и сделали нормально.Чтение строки известной длины — это две строчки кода. Чтение неизвестной строки — это цикл, выделения буферов, конкатенация и прочий бред.
Общий тезис таков: главное должно быть первым. В строке чаще всего нас интересует длина, поэтому она должна быть в начале. Бывает, содержимое вообще неважно, нужно только переложить строку в другое место и не ошибиться на байт туда-сюда. Сишные строки делают все, что такая ошибка случилась.
С любовью вспоминаю Паскаль, где строки были правильными: сначала байт с длиной, потом содержимое. Правда, из-за этого строки не могли быть больше 256 байтов. Разные компиляторы предлагали строки, где под длину выделялось два байта или четыре.
Можно долго рассуждать, что было и по каким причинам, но к делу это отношения не имеет. Важно запомнить, что главное должно быть первым — как на экране, так и в байтиках.
-
Бусти и почта
Подписался на одного человека в Бусти — первый раз пользовался этой платформой. Заодно наблюдал котовасию с подтверждением почты.
Дело было так: захожу через Гугло-учетку, все нормально, пришло письмо “здравствуй, дорогой Ivan”. А как начал читать, появилась плашка: чел,
ivan@grishaev.me
— это твой емейл?Вы серьезно? Гугл уже подтвердил, что это моя почта, что вам еще нужно? Как вы это представляете: зашел через Гугл, а почта не моя? Тыкаю Yes, чтобы отвязался. Перехожу в соседнюю вкладку, а там вылезла та же плашка. На этот раз я промахнулся и нажал No. В результате моя почта пропала из профиля, и Бусти пишет — пока не подтвердишь почту, покоя не дам.
Хоть я и не видел кода Бусти, легко понять, почему так происходит. Когда создается учетка, у нее стоит флаг “почта не подтверждена” — нормальное поведение для регистрации по email. Но разработчики не учли, что в случае с Гуглом почта подтверждается автоматом и выносят мозг подтверждением.
На ровном месте устроили бурю в стакане: подтверди, хотя никакого подтверждения не нужно. Большой и денежный сервис, а такие косяки.
Интересный факт об авторизации, который я не знаю, куда приткнуть, поэтому пусть будет здесь. Когда пользователь входит через Фейсбук, он может отказать в передаче емейла. В результате вам прилетит джейсончик, где всякие токены-шмокены, а почты нет. Если почта критична (а это чаще всего так), приходится заворачивать пользователя со словами “не быкуй, галочку не снимай”. Требует много кода и тестов.
-
Приглашаю на митап
В следующий четверг (28 ноября) Health Samurai проводят очередной кложурный митап. Я буду рассказывать про свою библиотеку PG2 — это которая клиент к Постгресу. Начало в 19:00, нужна регистрация. Ссылка на страницу организаторов.
Из анонса может показаться, что доклад будет про библиотеку, но на самом деле я бы хотел поговорить о другом. Пока я работал над ней, то столкнулся со спецификой, о которой раньше не думал, и теперь хочу ей поделиться. Кроме самой библиотеки, расскажу о следующих вещах:
- как устроен Postgres Wire Protocol
- зачем браться за свое решение, когда есть другие, проверенные годами
- сопоставление типов Postgresql и Java/Clоjure
- заморочки с парсингом
- мысли об API и дизайне
Подойдет всем, кто как-то связан базами данных. Запись на Ютубе будет через несколько дней после митапа.
-
Можешь поправить
Есть одна обидная вещь, я называю ее “можешь поправить”. Это когда находишь ошибку, которой много лет и которую воспринимают как данность. И когда обращаешь внимание, тебе отвечают — можешь поправить.
Текст ошибки совершенно нечитаем? Можешь поправить. Сервис делает тысячу запросов вместо одного? Можешь поправить. Хрупкие билды? Можешь поправить. Не собирается под твоей операционкой? Можешь поправить. Не работает в Фаерфоксе? Можешь поправить.
Ну вы поняли: “можешь поправить” — это вежливая форма “е…сь сам”. Ощущение, что на полу лежит какашка, и все старательно ее обходят, дожидаясь, кто вступит первым. Как правило, первым вступаю я.
Повторюсь, это очень обидная вещь, и вдобавок тревожный маркер о состоянии команды. В данном случае нужно править не только технические косяки, но и отношение к ним в команде.