Открытый канал ID 76261311863397

Организованное программирование | Кирилл Мокевнин

Каналов в рубрике
1 733
Место этого канала
№ 999
Открыть рубрику →

Публикации за период

По реакциям

Поиск и вся лента — после бесплатной регистрации. Свои даты — по подписке; владелец канала видит их бесплатно. Сортировка по реакциям — по подписке. Зарегистрироваться

Загрузка…

Коварная память кодинговых агентов

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

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

Я в какой-то момент, когда увидел очередное "я понял, сохраню в память", психанул и запретил ему это делать. Он этот запрет тоже положил в память :) Поэтому пришлось закатать рукава и проработать схему запрета в AGENTS.md. Можно сказать, а почему бы не выключить ее совсем? Есть таки таки вещи, где она нужна и где я не хочу сильно думать. Возможно там есть настройка которая позволяет память менять по проектно (щас пост опубликую и проверю) и тогда вопрос может быть решен кардинально.

Какой у вас опыт с памятью?
Просмотры: 4
Перейти в пост Открыть в MAX Сообщить о неточности
Выпуск про переход от инженера к предпринимателю, созданию компании express42 и последующему поглощению Флантом уже в сети. Мы встретились с моим старым другом Сашей Титовым, где поговорили про его путь, про девопс и будущее инфраструктуры https://www.youtube.com/watch?v=LUytWE_NShk
Просмотры: 10
Перейти в пост Открыть в MAX Сообщить о неточности
Улучшаем харнес

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

Понятно что со временем появляется все больше и больше правил, которые описываются в AGENTS.md
(или что лучше в CODING_STANDARDS.md
). Но хотелось бы чтобы они чекались автоматом. Клод нам сам постоянно предлагал и в какой-то момент начал писать скрипты допом к линтингу, которые, в основном, регулярками, проверяли что-то. Кушать не просит и ладно, я не сопротивлялся, но видел что это решение на тоненького, хотя и лучше чем ничего.

Когда эти скрипты начали копиться, я подумал, хм, а ведь мне ничего не стоит попросить его переписать правила как плагины к линтерам на конкретных языках. Кое что мы так действительно переписали, но в какой-то момент сам клод говорит, а давай заюзаем ast-grep. Я посмотрел и понял что проспал очень логичную штуку. Еще в 22 году, когда полетел treesitter, кто-то замутил инструмент, который грепает не исходники, а AST. Причем что важно, независимо от языка, оно все языки превращает AST и грепает по его нодам.

Это резко повышает точность рабатываний, потому что вместо регулярок, которые ловят ненадежно, плюс херово работают с вложенностью, мы имеем по сути универсальный способ представить весь код (и все форматы) в виде единого AST пространства, по которому идет поиск. Ну и естессно переписали все проверки, потому что у этой штуки еще есть sdk для ноды. А все подобные скрипты у нас агент фигачит на TypeScript. Пара примеров:

1. no-unknown-in-generated-types: в сгенерированных фронт-типах (app/javascript/types/serializers/) не должно быть unknown. Typelizer пишет unknown, когда не смог вывести тип поля. Это бывает у атрибута поверх T::Struct или у вычисляемого атрибута без typelize. Тип нужно объявить явно в ресурсе.

2. no-untyped-resource-dsl: в сгенерированных RBI-сигнатурах DSL ресурсов не должно быть T.untyped. Чинить надо в ресурсе или в компиляторе typelizer.rb, а не в RBI.

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

p.s. Какие еще фишки вы знаете?
Просмотры: 9
Перейти в пост Открыть в MAX Сообщить о неточности
Статистика по задачам. Как повлиял ии?

Заметил интересный эффект. По мере внедрения агентов, мы стали очень сильно ускорятся в скорости закрытия тасок, в какой-то момент мне почудилось что еще чуть-чуть то текучка пропадет и мы займемся, новыми большими фичами почти без отвлечения. Но как я был не прав :)

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

А между тем 5 агентов (только у меня) херачат сутками. У меня кстати накопилось уже материала по изменениям, буду про это писать скоро. И переписывания на го и снижение цены лида и улучшение аналитики. Ух сколько всего.

Ци
фры

Посчитал все тикеты разработки, фидбека и контента в Трекере с октября 2025 по сентябрь 2026. За год создано 1340 тикетов, закрыто 1032. Точка отсчёта — 14 мая: в этот день в репозитории появился первый коммит, написанный вместе с Claude.

Сколько создаём и закрываем в месяц

• Октябрь–апрель: создавали около 70, закрывали около 50.
• Июнь–август: создаём около 105, закрываем около 105.
• Сентябрь: создали 422, закрыли 222.

Как быстро закрываем

• До мая тикет жил до закрытия в среднем от 3 недель до 2 месяцев. Начиная с мая — 5–6 дней.
• Доля тикетов, закрытых за неделю, выросла примерно с 20% до 35–48%. Исключения — июнь и сентябрь.

Коммиты

• До мая было около 400 в месяц, в сентябре — 713. У 87% сентябрьских коммитов соавтор — Claude.

Выводы
1. Тикеты закрываются примерно в 6–10 раз быстрее, чем до мая.
2. Летом мы впервые закрывали не меньше, чем создавали. До этого очередь только росла.

Аппетиты растут во время еды :)
Просмотры: 13
Перейти в пост Открыть в MAX Сообщить о неточности
Плановое обслуживание кода

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

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

Эффективность агента

/do
ctor (Claude Code) — раз в месяц проверяю здоровье агентского окружения: конфигурацию, неиспользуемые скилы и MCP, медленные хуки, проблемы с permissions и другие накопившиеся проблемы. Заодно помогает освобождать память от устаревшего и лишнего.

/fewer-permission-pr
ompts (Claude Code) — анализирует историю работы и предлагает, какие часто используемые безопасные команды стоит добавить в allowlist, чтобы агент меньше отвлекал подтверждениями.

/run-skill-gen
erator (Claude Code) — периодически пересобирает знания агента о том, как поднять и проверить проект, чтобы /run и /verify не опирались на давно устаревшие команды.

/retro (Matt Pocock Skills) — формально не плановая задача. Запускаю после сессии, где агент заметно буксовал, делал лишние шаги или его приходилось несколько раз исправлять. Скил анализирует, что можно поменять в инструкциях, автоматических проверках и окружении, чтобы эта проблема больше не повторялась.

Качество кода

/simplify (Claude Code) — прохожусь по активно меняющимся частям проекта. Ищет дублирование, лишние абстракции, возможность переиспользовать уже существующий код и просто слишком сложные решения. Удобно запускать раз в неделю по нескольким наиболее активно меняющимся каталогам.

/c
ode-review (Claude Code; у Matt Pocock также есть одноимённый skill) — отдельный проход по изменениям за неделю на корректность, качество кода и возможные упрощения. Обычный review конкретного изменения такую накопительную деградацию часто не замечает.

/improve-codebase-a
rchitecture (Matt Pocock Skills) — ищет места, где архитектура постепенно поплыла: слишком мелкие модули, неудачные границы, сложные интерфейсы, размазанное по нескольким местам поведение. Можно натравливать прямо на конкретные слои, типа посмотри сервисы

Чтобы не потерять это добро, я включил в его книгу паттернов агентной разработки https://mokevnin.github.io/agentic-coding-design-patterns/ru/scheduled-maintenance.html

Кстати есть неочевидный нюанс. По идее все это надо стартовать автономно, но автономный запуск где-нибудь на github actions подразумевает работу не от подписки конкретного пользователя, а по апи. А хорошие модели чертовски дороги в таком варианте использования, поэтому пока по старине, стартуем все это ручками.

p.s. Поделитесь своими фишками, что запускаете вы?
Просмотры: 10
Перейти в пост Открыть в MAX Сообщить о неточности
Ассемблер неправильная абстракция

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

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

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

Cobol был одной из первых попыток подняться от описания вычислений к описанию бизнес-намерений. Предполагалось, что программы на похожем на английский языке смогут читать и, возможно, писать сами специалисты бизнеса. Но понятный синтаксис не устранил сложность программирования. Для точного описания поведения все равно понадобились переменные, условия, циклы, структуры данных и процедуры. В результате cobol стал успешным языком для бизнес-систем, но не стал языком самого бизнеса, так как писали на нем по-прежнему программисты.

Успешные примеры появились там, где намерение удалось ограничить конкретной и хорошо формализованной областью. Хорошие примеры это регулярки, sql, html/css или terraform. Это конечно еще не бизнес уровень, но уже что-то.

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

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

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

Я был бы рад ошибиться, но пока не вижу предпосылок. А как вы думаете?
Просмотры: 15
Перейти в пост Открыть в MAX Сообщить о неточности
Адаптация проекта под LLM

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

Чем дольше живет проект, тем больше в нем косяков в именовании (чего угодно), кастомных решений и самопальных либ, разных подходов в реализации одного и того же (накопленных за годы). А еще просто банально устаревшие штуки, которые уже давно никем не используются. Раньше мы со всем этим жили, потому что времени на исправления нет, но где-то год назад начали массовые рефакторинги, которые сейчас почти закончены.

Правда мне регулярно возражают, что вот у нас так а llm хочет сильно по другому или llm делает фигню. Это правда, llm может делать фигню, но далеко не всегда потому что она училась только на говнокоде. И модель и харнес и много чего влияет, но, глобально, модель учится на типовом коде и ее решения достаточно типовые, поэтому в большинстве случаев можно пренебречь какими-то своими ноухау и быть как все. Что не отменяет элементов, которые приходится делать по другому.

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

Ключевые вещи которые мы сделал:

Там где получилось, привели имена в домене к общепринятым (мы мучали llm отдельно от проекта на тему того какой понятийный аппарат используется в образователей сфере. Может показаться что это фигня, но нет, есть немало слов, про которые мы не то чтобы сильно знали, потому что все это было заложено лет 12 назад, а с тех пор многое утекло. Иногда наше именование не совпадало с общепринятыми (международными) понятиями, а иногда просто все так поменялось, что потерялось изначальное значение. Раньше мы даже взяться за это не могли, а тут без проблем, даже учитывая что один такой пулреквест может тянуть изменения в сотнях, а то и тысячах файлах (спасибо типам и тестам за контроль).

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

Иишка смогла найти готовые решения, благодаря которым мы выкинули немало самопала. Это может выглядеть контритуитивно, но несмотря на то что ии позволяет нахерачить все самим, лучше брать готовые промышленные решения (популярные и стандартные). Это касается как фронтовой части (полностью ушли на Mantine), где теперь мы получаем почти 100 процентный уровень генерации в one shot режиме, так и решения для бекендовых задач, например подписок, которое требует определенной модели данных и предоставляет готовые общепринятые сущности.

Плюс постепенное обрастание спеками, проработанными тикетами, глоссарием, adr, коммитамии с хорошими сообщениями, все это вместе дало возможность ии гораздо быстрее и точнее понимать что происходит.

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

Одна из моих любимых тем, про которую не устаю говорить. В модели данных часто бывает ситуация, когда состояние выражено не прямым образом, а косвенно. Буквально вчера я реализовывал кастомные тарифы под конкретных пользователей. Отличие такого тарифа от обычного сводится к тому, заполнено ли поле user_id в тарифе или нет. Если не заполнено, то значит это общий тариф, если заполнено, значит под конкретного пользователя и другие его не могут видеть.

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

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

В общем не полагайтесь на то как заполнены поля, вводите нужные статусы, которые явно будут говорить о том что происходит. Заодно это дает более удобную аналитику и выборки
Просмотры: 76
Перейти в пост Открыть в MAX Сообщить о неточности
Новый выпуск подкаста про Agile, Scrum и ИИ трансформацию уже доступен https://vk.ru/orgprog?z=video-224967259_456239343 В этот раз с Асхатом Уразбаевым мы вспоминаем как это было и куда пришло. Взлеты и падения, культы карго и трансформации в компаниях. А что в конце? Дейли не нужен, вот такие пироги
Просмотры: 73
Перейти в пост Открыть в MAX Сообщить о неточности
Иммутабельная денормализация

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

В реальных проектах выясняется, что нормализованные данные сложно соединять и выбирать. При глубоком уровне зависимостей, чтобы добраться до внешней сущности, нужно либо соединять 5 таблиц, либо делать 5 запросов. Пример из Хекслета. У нас есть программа обучения, которая состоит из модулей, в которые входят темы которые состоят из уроков, которые состоят из юнитов (теория, практика, тесты). На это все накручено много логики по прогрессу и отображению. В такой структуре, вопросы типа "какой урок следующий по порядку?" заставляют поломать голову.

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

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

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

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

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

Но есть места где без синхронизации данных не обойтись никак. В основном это касается статусов, они могут меняться и за ними нужно следить.
Просмотры: 74
Перейти в пост Открыть в MAX Сообщить о неточности
Вся лента — после бесплатной регистрации
ВКонтакте Телеграм Одноклассники
Избранное в datool.ru

Следите за каналом в личном кабинете

Зарегистрируйтесь в datool.ru, чтобы добавить канал «Организованное программирование | Кирилл Мокевнин» в избранное и отслеживать его показатели.

Зарегистрироваться
Для владельцев каналов

Подтвердите свой канал

Войдите или зарегистрируйтесь в datool.ru, затем добавьте нашего бота в канал по инструкции в личном кабинете. После проверки владения замок исчезнет и вам станет доступно управление каналом.

Войти или зарегистрироваться

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти