Куда войти?


Гео и язык канала: Россия, Русский
Категория: Технологии


Куда войти? В IT. Канал о технологиях.
Автор: Илья Ильиных, разработчик. Программирую деньги с 2018 года.
GH: https://github.com/IlyasYOY
VK: https://vk.com/kydavoiti
YouTube: https://www.youtube.com/c/Кудавойти

Связанные каналы  |  Похожие каналы

Гео и язык канала
Россия, Русский
Категория
Технологии
Статистика
Фильтр публикаций


Надо делать проверки для агентов строже.

Недавно я подключал в проект классный инструмент: [gomu](https://github.com/sivchari/gomu). Отличная утилита для запуска мутационного тестирования — у меня про это есть [видео](https://www.youtube.com/watch?v=nCPeaEdwhDI).

Она сделана с использованием намного более продвинутых инструментов, если сравнивать с популярной [go-mutesting](https://github.com/avito-tech/go-mutesting).

Я нашел gomu, когда изучал, как работает go test — для [видео](https://www.youtube.com/watch?v=BDVSbr3wGYU). Я узнал про механизм, которым пользуется gopls для подмены исходника на диске исходником, который у вас в редакторе. Называется overlay. Тесты на него можно глянуть [здесь](https://go.dev/src/cmd/go/testdata/script/build_overlay.txt).

Как только я увидел этот механизм, я сразу понял, что его можно и нужно использовать для mutation-тестирования. Я сразу пошел думать, как это сделать, искать инфу об overlay. Так я и наткнулся на gomu.

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

Это я к чему?

В gomu есть мутация if, то есть он проверяет качество тестов, которые проверяют if. Он может изменить ваш исходник, сломав if, запустить ваши тесты и сказать, упали ли они.

В теории — должны. Но только в теории.

Но! Агенты умнее. Они увидели, что там нет мутации switch, и начали заменять у меня if на switch.

Фикс уже готов: [sivchari/gomu#100](https://github.com/sivchari/gomu/issues/100).

Это я к чему?

Я думаю, что мутационное тестирование наконец-то войдет в наш арсенал, а не просто будет интересной темой для обсуждения.

Для Go это будет gomu.

Я уже использую его каждый день на unit-тестах.

537 0 12 11 11

Репост из: Куда Войти? Разное
- Можно быть бесконечно продуктивным с ИИ, но когда закончится подписка — тоска.
- Можно сколько угодно быстро кодить, но закончится батарейка или пропадет интернет — тоска.
- Можно писать в блокноте сколько угодно, но когда закончится ручка — удовлетворение.
- Можно фотографировать сколько угодно, но когда сядет батарейка — тоска.
- Можно фотографировать сколько угодно, но когда закончится пленка — удовлетворение.

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

В отношении ли дело? Когда мы снимаем на пленку — это процесс, из которого нас нежно вырывает реальность и говорит сделать паузу. Окончание батарейки совсем другое и бездушное происшествие.

Конечно, это может быть романтизация, но аналог давно меня не расстраивал, чего нельзя сказать про технологии. Они бесят меня каждый день.


Самому не верится, что скоро выйдет новый ролик. А скоро это прям сейчас! Поэтому бегом смотреть, ставить лайки, подписываться на канал, комментарии.

YouTube

Мне кажется, мне получилось его хорошо покрасить, хороший звук и тема очень актуальная. Ведь вы уже давно (я уверен) не пишете код, вы пишете промты. Про это и поговорим: как Vim адаптировался под это и как текстовые редакторы под это адаптируются.

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

А Vim, при этом, остается!

PS. А, да, кстати! Я сломал руку. Это для меня плохая новость, а для вас, скорее всего, хорошая, потому что я очень долго (для меня по крайней мере в душе) не пользовался Vim'ом и терминалом, а всё делал через десктопное приложение Codex. Об этом, наверное, и будет ролик в будущем.


Недавно я для себя сделал открытие.

Времена, когда я писал код руками прошли и вряд ли вернутся. Теперь я делегирую написание и сбор информации агенту. Я работаю не так, как работал последние годы.

Беда пришла откуда я не ждал. В моей практике всегда был набор практик, которые я НИКОГДА не нагрушал, потому что писал код сам. Например, я никогда: не использовал `any`-matcher для моков, не возвращал интерфейсы в Go, и так далее. Я думаю, что у каждого из вас есть набор правил, которые вы себе не прощаете. Вы всегда пишете код так. Точнее писали...

Возвращаясь к тому, что код сейчас за меня пишет AI. Ошибки за меня делает AI, ревьюить его надо иначе. Ранее я знал, что я могу не смотреть в своих доработках на self-review. Теперь у меня такого понимания нет. Пусть, я научил нейронки писать так как я хочу, есть куча примеров для нее, но она всегда может посадить багу, потому что она не принципиальная. Да и я мог просто сменить нейронку, а для нее нужны будут свои правила (codex, glm, opus - все пишут по-разному). Я всегда ее должен ревьюить в максимально подробном режиме. Нет таких ошибок, которые она не может не сделать.

Тут хочу поделиться приколюхой. Недавно AI сгенерил мне функцию с РУССКОЙ С ВМЕСТО C. Сказать, что я обосрался, когда мне на ревью другой агент написал об этой проблеме - ничего не сказать. Я уже вижу, как у меня мог засраться какой-то YAML/JSON конфиг.

Что с этим делать? Я не знаю. Жить.


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

Регистрируйтесь - будет весело. Друзей звать надо. Кол-во мест ограничено, как говорится.


Репост из: Куда Войти? Разное
Недавно оптимизировал свой сервис. Держит теперь бесконечный RPS.

Оформил это в skill, делюсь:

Перед оптимизацией очистите сервис от лишних аллокаций, прогрейте connection pool и не трогайте max_connections грязными руками.

В ночь растущего latency откройте pprof, положите рядом explain analyze и трижды произнесите:

> Как goroutine не блуждает без context,
как query не ходит без index,
как pool не сохнет без idle connections,
так пусть RPS мой растёт,
latency в p95 не распухает,
VACUUM приходит вовремя,
а Postgres отвечает быстро и без обиды.
Да будет throughput.


После этого запустите нагрузочный тест, но не смотрите только на средний latency — это бесовское число. Смотрите p95, p99, lock waits, slow queries и saturation.

Последствия сильной оптимизации:

Сервис может начать держать больше RPS, но будьте осторожны. Если делать ритуал без индексов, backpressure и нормального timeout budget, можно не ускорить систему, а просто быстрее положить базу.

Главное правило: настоящий performance tuning — это не магия. Это когда ты наконец-то открыл метрики.


Flaky Tests! Испугались? Больше не надо их бояться, их время прошло.

Наткнулся на статью, как автор поборол старые flaky-тесты с помощью нейронки.

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

Когда появился AI, пропала причина терпеть flaky-тесты, надо просто
заплатить вашему LLM-провайдеру, чтобы он вам нашел причину и исправил.

Что нам остается, кроме как платить? 😨


У меня есть канал, где я пишу всякое. Можете подписываться, если интересно всякое.

- интерактивно проверить все ошибки написания в Vim,
- разные фоточки,
- шутки про gown,
- поиски самого-самого браузера.

И это только вершина айзберга...

https://t.me/kydavoiti_live


Да! Обычно, в таком стиле и о таких штуках не пишу в этом канале, но сейчас я не могу молчать.

Inspired by:

Я ненавижу:
.

Это шаг в сторону, где Go нечего ловить. Есть куча языков, который позволяют писать код с method-receivers, позволяют делать это удобнее...И мы все знаем куда это приходит:


var result = users.stream()
.filter(u -> u != null && u.isActive() && u.getEmail() != null)
.flatMap(u -> u.getOrders().stream()
.filter(o -> o.getStatus() == PAID)
.flatMap(o -> o.getItems().stream()
.filter(i -> i.getProduct().getCategory() != INTERNAL)
.map(i -> entry(domain(u), priceWithDiscount(o, i)))))
.collect(groupingBy(Entry::getKey, summingDouble(Entry::getValue)))
.entrySet().stream().filter(e -> e.getValue() > 1000)
.sorted(comparingByValue().reversed()).limit(10).toList();

Вот такая бздень у нас получится на Go. Хотя нет, на Go будет даже хуже, потому что на Go нет синтаксиса, чтобы сделать lambda-функции без явного указания всех типов. То есть код выше будет таким:


result := From(users).
Filter(func(u *User) bool {
return u != nil &&
u.Active &&
u.Email != ""
}).
FlatMap[Entry[string, float64]](func(u *User) Stream[Entry[string, float64]] {
return From(u.Orders).
Filter(func(o *Order) bool {
return o.Status == Paid
}).
FlatMap[Entry[string, float64]](func(o *Order) Stream[Entry[string, float64]] {
return From(o.Items).
Filter(func(i *Item) bool {
return i.Product.Category != Internal
}).
Map[Entry[string, float64]](func(i *Item) Entry[string, float64] {
return Entry[string, float64]{
Key: domain(u),
Value: priceWithDiscount(o, i),
}
})
})
}).
GroupBy[string, float64](
func(e Entry[string, float64]) string {
return e.Key
},
func(e Entry[string, float64]) float64 {
return e.Value
},
).
Entries().
Filter(func(e Entry[string, float64]) bool {
return e.Value > 1000
}).
Sort(func(a, b Entry[string, float64]) int {
return cmp.Compare(b.Value, a.Value)
}).
Take(10).
ToSlice()

Даже раньше, когда Go-феры использовали
lo, для меня это было культурных шоком:

1. мусор: каждая операция делала мусор, с которым (слабому, если сравнить с Java) GC надо было бороться;
2. елочка: вызов оператора надо вставлять как операнд для другого оператора;
3. шум: везде указывать явные типы для lambda.

И что теперь? Да, добавление нового подхода решит проблему 1, потому сделают ленивые коллекции (сделают же? не будут же они eager? и использовать все их будут?)

Я знаю точно, что изменится. На собесах (и без того бесполезных), появится еще один вопрос: сколько allocations сделает код и как его оптимизировать. Правильным ответом будет переписывание с неправильной либы на правильную. И попутный рассказ почему одна из них плохая, а вторая нет.

PS. Хорошо, что код сейчас писать почти не нужно. Пора становится кодерам gown'a


Особенности работы bubbletea

Обещал поделиться техническими особенностями, которые вызвали у меня проблемы. Делюсь.

много событий, случайный порядок

Порядок завершения асинхронных операций может быть случайным, поэтому важно синхронизировать доступ к storage`/`state. Я встречался с этой проблемой в тестах toggle-значения завершенности задачи (и не только, это один из примеров).

В bubbletea Update обрабатывает сообщения последовательно, но tea.Cmd запускаются асинхронно. Несколько команд могут завершиться не в том порядке, в котором их создали, поэтому обработчики их сообщений должны переживать переупорядочивания.

Должен быть мем, но я просто опишу его.

• Drake hates: установить значение counter = n.
- Так у нас победит последнее примененное сообщение, а не обязательно последнее действие пользователя.
• Drake likes: изменить значение counter + k.
- Так у нас может измениться порядок применения, но результат останется тем же.

Но! И тут тоже надо очень осторожно подходить, потому что возможно конкурентное чтение текущего состояния для diff и применение обновления.

Короче, многопоточка (tm).

Что мы делали?

- сначала перестали мутировать состояние до *DoneMsg.
- ранее мы сначала изменяли state, потом ходили в store, а потом уже отправляли сообщение, на которое мог кто-то реагировать;
- теперь мы сначала ходим в store, а потом отправляем *DoneMsg, в обработчике которого обновляется state.
- а затем добавили nonce к сообщениям thinglist. nonce здесь - это идентификатор конкретного времени жизни: сообщения от старого экземпляра модели пропускаются.

Коммиты:

• 2efd2c0
• 79eb212.

Вывод простой: сообщения и его обработчики должны быть безопасны к переупорядочиванию или явно защищены от устаревших результатов, иначе многопоточка (tm).

тест закончился, фоновые операции нет

Здесь проблема была уже не в порядке применения, а в жизненном цикле приложения. В bubbletea тест мог уже дойти до tm.Quit(), но это еще не значило, что все ранее запущенные tea.Cmd действительно закончили работу, no-no-no. Было бы слишком просто.

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

В cosas это в итоге починилось коммитом 6f46daf: в storage добавили Close(), который запрещает новые операции (будет отдаваться ошибочка) и ждет завершения уже идущих записей.

Все просто...Или нет?


Alt-screen в TUI

Пользуетесь вы своим любимым Claude Code или другие Agent Harness. Все начинает прыгать, моргать, страшно, очень страшно.

У нас может быть такая ситуация, что текст приложения не помещается в экран. И часто это не проблема:

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

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

Что за alt-screen?

Это не субкультура, это чисто технический термин. Приложения с TUI могут работать в нескольких режимах: обычный и alt-screen.

Пример приложения:
- что работает в alt-screen: neovim, opencode.
- что работает в обычном режиме: codex (по крайней мере в tmux), cat, git status.

Вы сразу увидите, если приложение работает в режиме alt-screen. Оно займет все пространство вашего терминала.


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

Он следит, какой у нас размер экрана, какой размер содержимого и как его лучше отобразить.

Вы можете писать его сами, но часто он уже реализован библиотекой, которую вы используете. Например, он есть в bubbles.




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

В своем канале @kydavoiti_live я писал про видео. Оно мне напомнило, что есть такая вещь: первая помощь; о которой я почти ничего не знаю и точно ничего не умею. Хотя все мы ее проходили на работе/школе, так или иначе (чаще мимо)? Подписывали документы? Почти сразу после просмотра, я поставил себе задачу пойти на курсы первой помощи.

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

Вот, на этих выходных я прошел курс из 16 часов, где мы изучали теорию и практиковались: в алгоритме оказания первой помощи, вызове скорой помощи, проверке дыхания у человека без сознания, как (и когда) перевести пострадавшего в безопасное положение, опросе пострадавшего, помощи в организации, сердечно-легочной реанимации (детей, школьников, взрослых), перевязке кровотечений, транспортировке пострадавших множеством способов, прием Геймлиха - это (не полный) список того, что мы делали на практике друг с другом или экипировкой. Все это оттачивалось в сценках-инсценировках, даже с искусственной кровью. И конечно, была теория, в том числе и юридические права и обязанности.

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

Подробнее про эти курсы вы можете прочитать на сайте РКК: https://www.redcross.ru/. Еще делюсь каналом нашего инструктора Ивана, который на основной работе инженер, а по выходным: @first_aid_and_common_sense.

В оказании первой помощи ИИ нас не заменит. Будь то в качестве субъекта и/или объекта (как бы грустно и смешно это ни было)


Те, кто давно меня читают, знают: я люблю Vim за архитектуру. И особенно — за фичи, которые не висят в воздухе. Сегодня — как раз такой пример: cursor-text-objects.nvim.

В Vim есть textobject — способ оперировать логическими блоками текста: iw, ap, if и т.д. Это работает отлично… пока не упираешься в ограничение: объект можно взять только целиком. А хочется выделить только часть функции ниже курсора!! Очень! Именно это и решается плагином.

Добавляются всего два префикса:

• [ — от начала объекта до курсора
• ] — от курсора до конца объекта

Дальше — всё как всегда, operator + textobject:

• d]ap — удалить от курсора до конца абзаца
• d[if — удалить от начала функции до курсора
• c]iw — изменить слово от курсора до конца

Плагин внешний, но ощущается так, как будто это всегда было частью Vim.


Месяц тишины. Развею его небольшими находками.

Всё, что сейчас происходит, заставило меня отказаться от других задачников. Пришлось перейти на Singularity (пусть он и неплохой). Ко всему этому я перешёл на Codex с Copilot. Хочу попробовать, каков он. Думаю, что должно быть получше, в конце концов, ИИ — их основной продукт.

Так о чём это я! Работать с Singularity можно через вашего ИИ-агента. У них есть MCP. С доступом на чтение к Singularity и календарю у меня получился хороший ассистент по декомпозиции задач и анализу выполненного.

Проблема только одна. Из коробки MCP поставляется в формате MCPB, который поддерживается только в Claude Desktop. Но! Я парень простой, заставил его работать и в Codex. Для этого надо просто:
• распаковать MCPB — это zip-архив;
• запустить его как node.js-приложение.

Особенно хорошо это сочетается с заметками в Obsidian, которые — просто файлы на диске.

А как вы подружили ИИ и task-tracking/knowledge-management?


Сегодня поговорим про цветовые схемы для всего. Лучше времени для этого не будет, лучше уже некуда.

• покажу код,
• дам полезные ссылочки,
• мотивация,
• опыт,
• побалуемся с LLM,
• немного весеннего карьера + уточки (самое важное)

YouTube




Поговорили про нейронки и хватит.

Сегодня скину вам материал о детерминированной системе, которую любят обсуждать на собеседованиях (до сих пор, для меня это культурный шок).

У Саши вышел отличный подкаст, где он с гостем поясняет про GC в GO & Java. Для меня сейчас это Go-To материал, если кому-то надо отправить большой материал по погружению в GC. Обсудили разные алгоритмы, особенности их применения - годнота, вкуснота.

PS. Раньше я всем кидал выпуск другого подкаста с Иваном Углянским, либо один из его докладов. Сможете легко найти это все по имени автора + GC в Google.
PPS. Ладно, остался последний shorts про The Prompt.


Еще не смотрели подкаст, тогда у меня для вас замануха: Shorts

Саша поделился классной историей, как он с Claude Code & OpenClaw поймал Prompt Injection. А почему это веселая история, а не страшная? Все есть в подкасте.

Важно настроить правила доступа агента к вашим ресурсам и, чтобы все работало по принципу least privilege. Минимум секретов, все должно быть ротируемо. Хотя, что я тут рассказываю, все есть в подкасте интереснее и живее.

ЗЫ. Один из самых веселых моментов. Подписывайтесь на Сашу: @tfeat


🚨 В Jira можно больше на заходить!

Все можно делать через агента, надо просто...

Посмотреть шортс! Этот - киллер-фича ассистентов.

Показано 20 последних публикаций.