Читать в телеге. Когда-то там были посты не только от меня.
ИИ-перевод
Попробовал перевести статью про техдолг клодом, в основном ради любопытства, насколько хорошо это делают нейронки. Сохранится ли стиль? Будут ли добавлены load-bearing словечки и прочие LLM-измы? Сможет ли нейронка использовать оригинальные термины (потому что я их перевел с английского изначально)?
Я запустил 2 сессии параллельно: в первой промпт был буквально “Translate this for an international audience”, во второй это был уже абзац с несколькими подсказками, на что стоит обратить внимание. Обе сессии были с Opus 5 High.
Первый перевод был в целом норм с точки зрения сохранения смысла, но выбор слов был местами довольно странный (например, “logical” вместо “makes sense” или “take seriously” вместо “take into consideration”), и порядок слов иногда тоже был непривычным. Разумеется, картинки остались без перевода, и было предоставлено ровно ноль контекста для локальных мемов. Цинизм и мат были смягчены. Больше всего досталось определению техдолга — оно стало более многословным и менее точным. Стиль оригинала местами сохранился, но в основном был потерян, а перевод воспринимался как машинный. Короче, мне не понравилось.
Однако я доволен этим отрицательным результатом, потому что большинство этих проблем “предсказал” во втором варианте промпта. На удивление, разница между вариантами перевода была не очень большой, в основном отличия в синонимах, числе и временах — не очень даже понятно, повлиял ли как-то на это промпт или это “естественная” случайность модели (или вообще фингерпринтинг). К сожалению, второй вариант перевода оказался не сильно лучше первого: да, там были переводы картинок и сноски про мемы, потому что я это попросил, и они в целом были средненькие, но сам перевод был местами лучше, местами хуже, и клод не смог передать стиль (“вайб”?).
Далее, я сбросил сессиям варианты друг друга и спросил что они думают (“меняемся листочками”). Первый чат ответил прямо: бери второй, с минорными правками. А второй похвалил первый за “better English rhythm”, посетовал на отсутствие перевода картинок и сносок и нашел нестыковки. Наконец, я попросил “лУчШуЮ” модель Fable 5.1 Max выдать лучший результат, даже немного помог ей, и все равно на выходе получилось не то, как будто ИИ-рулетку в третий раз покрутил.
В общем, для передачи смысла сойдет, а так средне. Сейчас модно говорить, что “ИИ заменит Х-чиков” — штош, если вы хотите качественный перевод, то ИИ еще не способен заменить переводчиков.
UPD: попробовал по совету экспертов — чистый контекст, второй промпт + нэтив спикер + косяки которые нашлись в переводах:
- Определение техдолга — все еще говно, и совпадает с определением из “грязного” контекста буква в букву.
- Опять рулетка с выбором слов/синонимов/порядка/временами/числами и т.п. Но, справедливости ради, реже спотыкаешься об такое.
- Перевод картинок хуже: например, “Можно, а зачем” в этом варианте переведен как “You could. But why?”, а Opus из второго варианта перевел как “Sure, but why?”, и в “грязном” контексте то же самое.
- У Opus “костыль” остался костылем с контекстом про слэнг, а у чистого Fable — тупо “hack”.
- Да в и целом опус интереснее/лучше объяснил мемы (чемодан, “если бы мы знали”, ТЗ и т.п.)
Короче, я не увидел качественного улучшения по сравнению с Opus — все равно надо доделывать.
Хорошая спецификация — долго, дорого и не всегда возможно
Занятная статья про 2 основные аспекта формальной верификации: дороговизну и сложность формализации. И если первый аспект можно закидать деньгами, вычислительными ресурсами и теперь еще ИИ (который уже может нагенерить, например, формальное доказательство для теоремы Ферма), то понять, а как, собственно, система должна себя вести, все еще очень тяжело (за редкими исключениями). Спецификацию сейчас не для каждого языка программирования можно найти, а для чего-то более приближенного к бизнесу если что-то и будет задокументировано, то информация о поведении будет размазана по документации, тикетам, коду, презентациями, тестам и т.п. Но даже если собрать это все в одном месте и начать формализовывать, то появляется куча вопросов про сценарии. А бизнес на большинство и не знает ответа, или ему вообще пофиг, что будет в этом случае.
Еще одна проблема заключается в строго следовать спецификации тупо невыгодно. Это разобрано на примере PDF читалок: лучше как-то криво отобразить сломанный документ, чем сказать “ой, не по спецификации” и ничего не делать (закон Постела).
В общем, хотя формальная верификация и стала более доступной, она все еще слабо применима на практике.
Игры OverTheWire
Когда учился в универе, CTF был не очень популярен и прошел мимо меня. Игры OverTheWire как раз в таком формате: чтобы пройти на следующий уровень надо найти спрятанный флаг (пароль), выполняя задания.
Минимальную базу по Linux можно получить, пройдя Bandit. Даже с учетом того, что я все там знаю, все равно было занятно.
Азы по web-безопасности покроет Natas, а по шифрованию — Krypton. Остальные — про реверс-инженеринг.
Культуры зависимостей
Неплохой доклад с тезисом, что различные подходы к управлениям зависимостями в индустрии — это культурный вопрос, а не технический. Начинается, разумеется, с веба, а другим примером служат игры. Жирные зависимости — плохо (потому что большая часть вам не нужна), мелкие — тоже (left-pad). Не забыт и вопрос обновления — и часто плохо, и редко плохо (но это решаемо). Короче, перед добавлением зависимости надо думать, шансы прикидывать.
Сравнение Proguard и R8
ProGuard — это обфускатор и минификатор для java, а R8 — тоже минификатор для java и де-факто стандарт для Android. У последнего сложилась репутация как более мощной замены для ProGuard, некоторые не-Android проекты даже рассматривают замену ProGuard на R8 (например, Kotlin), благо формат настроек у них почти совпадает. У меня раньше в голове был образ, что R8 — это то же самое, что и ProGuard, только новее и лучше. Реальность полна разочарований, как говорится:)
Я буду рассматривать только вопрос минификации (обфусцировать java — очень странная идея), и стоит обговориться, что область ее применения очень ограничена — на серверах места полно, а на пользовательские системы java сейчас редко доставляют (Gradle тут скорее исключение).
Вот что я обнаружил, я когда попробовал заменить кастомную минификацию в Gradle сначала на R8, а потом на ProGuard:
- Вывод R8 зависит от версии JVM, а ProGuard для работы нужна JVM с jmods, которые могут быть не включены в JDK.
- R8 не позволяет ничего настроить относительно ресурсов и, как следствие, мультирелизных jar, манифестов, неактуальных контрольных сумм и т.п.
- R8 нельзя заставить удалить класс или метод, если на него есть ссылки (даже если знаете, что это логически мертвый код).
- R8 переписывает метаданные Kotlin и ломается, если ваш Kotlin новее.
- R8 переписывает методы, и, с одной стороны, код получается меньше, но может из-за этого сломаться на новейших JVM/Kotlin с чем-то вроде
java.lang.VerifyError: Bad invokespecial instruction: interface method reference is in an indirect superinterface.
При этом R8:
- Cжимает лучше, потому что работает на уровне методов, а ProGuard — на уровне классов. Т.е. ProGuard может оставить класс с 1 живым методом и сотней неиспользуемых.
- Требует меньше настроек “корневых” классов.
- Не такой строгий — если не видны какие-нибудь родительские классы, то предполагает, что они есть.
- Поддерживает Kotlin.
- Не имеет зависимостей — это один jar.
Мой сценарий довольно особенный и ProGuard оказался лучше, но для Android описанные минусы R8 слабо релеватны, так что для него он будет лучше.
ИИ-переписывание Bun
Многие наверняка слышали историю про то, что bun переписали с Zig на Rust с помощью тучи ИИ-агентов: впечатляющие графики, “новый уровень ИИ-инженеринга”, blazing fast™, убедительные результаты и т.п. Спонсирует все это Антропик, который купил bun в декабре. Эксперимент успешный, переписанный bun уже внутри Claude Code, аж с июня. А еще автор Bun на досуге запромптил Claude, чтобы сделать прорыв по гипотезе Римана. Короче, гений, миллионер, еще и плейбой наверняка.
Мало кто видел ответ создателя Zig на эту статью: “вы не разобрались”, проблема не в Zig и не в языках, потому что вопросики к автору bun были и до этой эпопеи.
А тем временем с момента статьи прошло больше месяца. Автор в режиме “ща, ща” все никак не зарелизит лучшую версию 1.4.0. На гитхабе при этом почти 5 тысяч открытых PR, большинство от агентов.
Выводы делайте сами, как говорится.
UPD: таки зарелизили.
Zero-defects code
Капсула времени: служебка Microsoft аж из 1989 года про нулевую терпимость к багам. Кажется, она не очень помогла, но вещи написаны хорошие, которые по большей части актуальны до сих пор.
Даже если идеал кода без багов недостижим, все равно надо к нему стремиться. Если думать, что баги неизбежны, то не будут стараться их предотвратить; будет фокус на количестве фич и скорость — будет соответствующее качество; надо править корень проблемы, а не симптомы и бороться со сложностью и т.п.. Увы, пока никто не придумал, как убедить руководителей в пользе долговременного планирования после того как прошел этап MVP, и как бороться с тем, что награждают не за качество работы.
Семантический diff
Из-за того, что в последнее время стало кратно больше код-ревью (потому что нейронку надо худо-бедно контролировать), многие начали присматриваться к “семантическим” инструментам для отображения изменений в коде, хотя они давно известны: Difftastic, sem, diffsitter, SemanticDiff и т.п.
Не могу сказать, что какой-то из инструментов произвел на меня вау-эффект: да, вроде получше, но не настолько, чтобы пересилить неудобства. Я честно пытался, но пользоваться ими на постоянной основе у меня не получилось: это все консольные инструменты, а мне окошки подавай с графической IDE. Да, вроде есть какая-то интеграция с VS Code у некоторых, но на спектре IDE-шности у меня он все еще ближе к текстовому редактору лежит.
В IntelliJ можно настроить внешний инструмент для разницы, но это по сути ярлык для вызова терминала (да и то без приседаний не обойтись). А еще у них есть тикет, чтобы сделать “нормально”, которому аж 21 год (sic!).
В итоге я, прости господи, навайбкодил плагин для IntelliJ, чтобы интегрировать консольные инструменты в окошко сравнения. Получилось не очень: сами модели в IntelliJ довольно ограничены и с помощью них все выразить не получается. Но все-таки, чуть-чуть лучше встроенного diff в некоторых сценариях.
50 оттенков Brainfuck
Brainfuck, хоть и весьма минималистичный (8 односимвольных команд), изначально задумывался как язык, для которого можно сделать минимальный компилятор (уже вторая версия была 240 байт, а на современном железе можно уложиться в 100).
Если же минимизировать количество команд — то легко уложиться в 2 простые команды (можете поиграться тут), или в одну посложнее.
А если минимизировать количество различных символов? Если отбросить эзотерику, одним из первых тут стал JSFuck, который выразил весь JS через 6 символов: +!()[]. А потом код-гольфисты продолжили:
- JS дожали до 5 символов —
[]+=`. Как и в JSFuck — приколы типизации. - Ожидаемо нашлись варианты для Python (
exc="%\n) и Perl (<>^es), но там скучныйexec/eval. - Внезапно для Haskell надо всего 4 символа —
()=;, разумеется, не обошлось без λ-исчисления, точнее, SKI. - Для Си есть решение за 5 символов —
+1;=$, в котором напрямую прописываются машинные коды. - В java унылые
02367?\abcdeitu, по сути просто обычный исходник, написанный через юникод-последовательности\u0a23, с гимнастикой для снижения количества нужных цифр. - В bash — аналогичный подход с
01456\$ ', zsh чуть интереснее с$#< (){}. - В PHP — 5 символов,
(^.9), подходы похожи с JS: делаем числа, из них буквы, потом имена функций и т.д..
Если вернуться к эзотерике, то стоит упомянуть Whitespace, где нужны только \t \n. Но победителем будет бесспорно Unary с прикольной идеей: берем код на Brainfuck, преобразуем его (биективно) в число, пишем соответствующее количество нулей (или любых других символов), и программа готова.
Наглядный пример, почему важны хорошие генераторы случайных чисел и QA
Неплохой разбор вскрывшейся недавно уязвимости биткоин-кошелька Coldcard. Вкратце: из-за кривой сборки (в этой статье чуть подробнее расписано) вместо нормального генератора случайных чисел с физическим источником энтропии использовался программный, с гораздо меньшей энтропией. Как следствие, стало легко подобрать приватный ключ. В итоге украдено более 1500 BTC ($100 млн.+) с 7300+ адресов.