Читать в телеге. Когда-то там были посты не только от меня.
Тестирование заголовков писем
Уважаем собеседника
При рабочем общении важно уважать время собеседника, но, увы, не все умеют это делать. Проявляется это по-разному, но из простых и при этом распространенных проблем можно было выделить привет без контекста. Коллег можно было направить на путь истинный ссылкой на NoHello.
Сейчас, когда стало очень легко делегировать мышление, часто встречается ситуация, когда кто-то тупо постит вывод нейронки без какой-то обработки. Что весьма грубо: скопипастить сообщение в/из чат-бота кто угодно может, и лишняя прослойка тут ни к чему. Если нечего толкового сказать — лучше промолчать. Чтобы с этим бороться, можно в качестве ссылки указывать no slop grenade или stop sloppypasta. Но если это не очень работает, а коллектив толерантен к токсичности, можно ввести в оборот и более агрессивные методы.
Роутинг на фронте
Когда фронтенд собирается из нескольких модулей, то роутинг становится проблемой: хороший UX часто требует на странице из одного модуля ссылаться на путь в другом модуле. Такие связи довольно произвольные, и чтобы избежать связи всех со всеми и циклических зависимостей, надо что-то делать.
Тупейшее решение — просто ссылаться на нужный путь строкой, но это очень хрупко и при любом изменении путей есть шанс, что что-то поломается. В идеале нужно, чтобы была проверка на уровне компиляции, что все ссылки рабочие. Можно обмазаться проверками при сборке, но это так себе вариант.
Окей, может тогда сделаем модуль или файлик под пути с константами и все будут зависеть от него? Это получается почти God-object, со всеми вытекающими. При этом тяжело следить, как модули связаны между собой. И может остаться путь, на который уже никто не ссылается. Есть еще вариации вроде генерации общего файла (например, из путей в модулях) или роутинг на основе расположения исходников (например, “/user/$id” лежит в папке “/user”), но проблемы там похожие. Можно поиграться с динамической регистрацией путей, но это уже рантайм.
Ладно, можно сделать объявление путей локальным для модуля, и сделать по модулю чисто с путями. Т.е. для users будет routes-users с белым списком путей, которые торчат наружу. В этом подходе плохо, что число модулей удваивается.
Наконец, еще есть подход с интерфейсами. Похоже на центральное объявление, однако интерфейсы живут внизу иерархии (там же, где commons и инфраструктура, например), а реализация — наверху (там, где собственно приложение из модулей собирается). Соответственно, пути внутри модулей изолированы и проверяются компилятором, в интерфейсах объявлено только то, что нужно для общения между модулями (и это легко контролировать на ревью), а реализация тривиальна, потому что зависимости от всех модулей уже и так есть. В рабочем проекте использовал именно этот подход, с двумя интерфейсами: для общего меню и для вызовов между модулями (там было пяток путей всего).
Синтаксис C++
На днях я узнал, что это
[&]<[:_:]>([[=({})]][:(_,_):])[[=^^::,=_]]{}
— валидная лямбда в C++26. Дело Perl живет:)
Решалка головоломки "Аквариумы"
Недавно я стал довольно много играть во всякие головоломки с этого и связанных сайтов. Головоломки можно разбить на 3 условных категории. В первой я достаточно быстро нашел набор локальных паттернов, и после этого решение ищется легко, практически машинально. Вторая группа уже посложнее: паттерны не очень локальные, и надо смотреть на взаимосвязи нескольких строк или столбцов. Иногда там еще и очень мало корректных следующих шагов, а найти их тяжело. Наконец, третья категория: в ней приходится опускаться до поиска с возвратом (aka backtracking), потому что не ясно, есть ли способ получше.
В какой-то момент для головоломки из последней категории я решил попросить у ChatGPT подсказку. В ответ он мне выдал лабуду, которая противоречит правилам и самой себе. Я парой запросов пытался добиться чего-то более адекватного, но это было бесполезно. Позже я попробовал Claude. Он пыхтел 20 минут, но все-таки выдал подсказку, которую можно было использовать.
И я навайбкодил (прости господи) приложение для решения головоломки (скриншот → подсказка). Опус 4.8 выдал первый результат через час (1 промпт + пара отвеченных вопросов). Я специально выбрал стек технологий, с которым не знаком (предлагался Kotlin/JS, Elm и Rust, но на них у меня есть (руками!) написанные приложения). Разумеется, первые результаты выглядели по-уродски и не работали. Были проблемы с обработкой скриншотов и цветовыми схемами. На их исправления понадобился еще час примерно.
Получившаяся решалка… выдавала тоже лабуду, на уровне ответов ChatGPT. Что странно, с учетом того, что клод в режиме чата справлялся. Позже я понял, что проблема все еще в обработке изображений. Мне даже пришлось самому печатать тестовые данные! Но даже этого было недостаточно. Все еще оставались проблемы с цветовыми схемами. Я временно на это забил и сфокусировался на логике.
Вскоре я нашел пример, который не решался набором правил. К сожалению, пришлось разрешить использовать поиск с возвратом. Потратил весьма приличное время на тестирование и улучшение подсказок, но в итоге все заработало. К сожалению, агент довольно быстро дошел до состояния, когда он думает, что проблема исправлена, но она еще есть. Я увлекся и не сразу осознал, что надо было его заставить на все писать тесты. Другой проблемой был Firefox и его функции безопасности с canvas, но после нескольких отладочных сборок и это починилось. А попутно и проблемы с обработкой скриншотов сошли на нет.
Как и ожидалось, отладка заняла существенно больше времени, чем первый MVP. Несмотря на то, что клод делал основную работу и все заняло больше итераций, чем я ожидал, мне все равно нравится результат. И я ощущаю, что что-то разработал, несмотря на опасения об обратном. Наконец, я стал решать эти головоломки лучше (абсолютно бесполезный навык).
MVP был на грани размера контекста — 99.9% от миллиона токенов (но потом сжал его, конечно). Некоторый код я посмотрел наискосок и совсем не впечатлился, ReScript меня никак не зацепил.
Если интересно, попробовать можно на http://localhost:5050 тут.
Безопасность спутниковой связи
Занятное исследование про защищенность сетей спутниковой связи.
Если вкратце — все очень плохо™. 50% соединений не используют шифрование. При этом можно найти кучу конфиденциальных данных — ключи шифрования, звонки, видеопотоки, управление промышленностью, энергетикой, ретейлом, банковские операции и даже данные военных. И все это можно получить с одной точки без дорогого оборудования.
Что знают про вас нейронки?
Полтора года назад было занятно попросить ChatGPT сгенерировать картинку, как он вас видит. Но это легко сделать — персонального контекста полно. И сделать это можете только вы. А как вас видят другие люди?
Раньше можно было посмотреть, что знает о вас интернет, загуглив свое имя или ник. Но пользоваться поиском уже не модно, нейронки же! Теперь можно посмотреть, что они знают о вас на уровне весов:
Как и в случае с генерацией изображений, результаты немного странные, но может через пару лет параметров станет больше и результаты будут лучше (картинки про вас сейчас ChatGPT тоже поинтереснее делает).
Код ревью в эпоху ИИ
Годная статья про то, как массовое использование агентов меняет разработку в целом и код-ревью в частности, с опорой на цифры из различных исследований. И базу про цели код-ревью повторяет.
Поскольку код стало производить легче, давление в процессе сместилось и нагрузка на ревьюеров кратно возросла. А с процессом ревью в индустрии и до ИИ были проблемы.
Код-ревью — это по сути диалог, одна из основных целей которого — достичь общего понимания проблемы и обменяться знаниями. Однако с ИИ понимание деградировало в угоду скорости, и если тупеньких ошибок стало меньше из-за локальной оптимизации, то архитектура, правильные абстракции и общее видение страдают, а ловить ошибки в них обычно сложнее. Кроме того, если в “человеческом” коде обычно видны намерения, то в сгенерированном ИИ коде их нет, и тяжело понять причину, почему тот или иной участок кода написан именно так (если эта причина вообще есть). Есть даже гипотеза, что основная цель программирования — построение рабочей теории, ментальной модели того, что должен делать продукт и как; и если это делегировать ИИ, то и результаты будут соответствующими.
Один из подходов — “вроде норм, мержим как есть, потом поправим если че”, но он плохо масштабируется и в долгой перспективе делает продукт очень хрупким. При поверхностных ревью система становится черным ящиком.
Что с этой проблемой делать? Можно попробовать ИИ-ревью, обложиться проверками и чек-листами, заставить людей предоставлять описание изменений, использовать grill-me, ограничить размер PR, заставить объяснять изменения на синхронном созвоне… Но все это либо не масштабируется, либо легко проигнорировать или обойти с помощью ИИ. Сам автор пока склоняется к маленьким PR с приложенным планом/промтом. Ну и экспериментировать с обязательным достижением понимания.
Более прагматичный подход изложен в другой статье. Там отмечается, что ревью вообще-то не очень благодарная работа, и его глубина — сугубо культурный аспект, который очень редко вознаграждается. Пока вы ревьюите один PR, вам навалят еще три. Еще себе в перформанс-ревью напишут сколько фичей доставлено, было бы еще больше, если бы не ревьюер… а вот за само ревью повышения не дадут. Если ревью особо не ценятся в команде, и поощряется количество фич, то лучше потратить время на что-то более видимое. Особенно, если на том конце — тонкая мясная прослойка перед ИИ. Можно сделать ревью опциональными и сместить фокус на проектирование (хотя это и не заменит полноценного ревью).
Постепенная автоматизация
Хорошая статья, дополняющая и раскрывающая идею частичной автоматизации.
Ключевая идея заключается в том, что любое (повторяющееся) ручное действие надо документировать, а после каждого использования — улучшать ее, частично автоматизировать и хоть чуть-чуть двигаться от состояния полностью ручной работы в сторону полной автоматизации. Таким образом итеративно собираются требования и ограничения, а также “коллективное бессознательное”, если речь идет про команду. Если чуть дольше выполнять работу — никто не заметит, а вот выделять ресурсы на автоматизацию фигни никто не будет.
Объяснения алгоритмов для игр
Хороший сайт с набором объяснений алгоритмов, полезных для разработки игры: поиск пути, генерация карт, работа с сетками, определение видимости, расчет урона, диаграммы Вороного и т.п.