Здарова, работяги!
У меня сложилось впечатление, что в сообществе есть определённая путаница на тему мемори-банков, рулсов, MCP и скиллов. Поэтому сегодня хочу поговорить с вами именно на эту тему.
Начнем с определений.
Memory bank — это внешняя память агента о проекте или пользователе.
Туда обычно кладут долгоживущий контекст: архитектурные решения, договорённости, особенности проекта, вкусы команды, важные факты, которые агент должен помнить между сессиями.
По сути, это способ не объяснять одно и то же заново в каждом чате.
Memory bank как “папка с простынями контекста, которую агент должен перечитывать перед работой” — почти устаревший паттерн.
Rules / рулсы — это инструкции для агента, которые задают рамки его поведения.
Например: “используй только pnpm”, “не трогай файлы миграций”, “компоненты называем через PascalCase”, “перед изменением API сначала предложи план”.
MCP — это протокол, через который агент подключается к внешним инструментам и данным.
Например, к GitHub, Jira, Figma, базе данных, Sentry, файловой системе, внутренним сервисам компании.
MCP превращает агента из “чата, который умеет писать текст” в участника рабочего процесса, который может ходить в нужные системы и получать оттуда контекст.
Skills / скиллы — это переиспользуемые сценарии работы агента под конкретные задачи.
Например: “как делать code review”, “как заводить новый пакет в монорепе”, “как писать тесты в этом проекте”, “как оформлять PR”.
Если совсем коротко:
Memory bank хранит контекст.
Rules задают правила поведения.
MCP даёт доступ к инструментам.
Skills описывают рабочие сценарии.
Использовать агента без них сейчас нет совершенно никакого смысла, качество его работы драматически падает без них. Но нужны ли прям все эти инструменты?
Сейчас всё больше фокус смещается в сторону связки rules и skills.
Rules играет роль закона: они всегда в силе и задают рамки, которые агент не должен нарушать. Агент держит их в контексте всегда.
Skills работают как инструменты: агент знает, что они есть и когда их применять, но не держит их целиком в контексте постоянно.
Нужен code review — достал skill для review.
Нужно завести новый пакет — достал skill для этого сценария.
Окей, с теорией разобрались. Давайте попробуем теперь написать алгоритм выбора инстурмента.
Я бы шёл в таком порядке.
1. Сначала линтеры, форматтеры, тесты, типы и скрипты
Если правило можно проверить автоматически, лучше проверять его автоматически. Не надо забивать микроскопом гвозди.
Линтер не забудет, не потратит токены и не начнёт “творчески интерпретировать” инструкцию.
2. Потом skills
Если речь не про жёсткую проверку, а про сценарий действий, лучше оформить это как skill.
Например: как делать code review, как заводить новый модуль, как расследовать падение CI, как готовить релиз.
Skill хорош тем, что не висит в контексте всегда. Агент знает, когда его доставать, и подтягивает подробную инструкцию только под конкретную задачу.
3. И только потом rules
Rules стоит использовать для того, что должно ограничивать агента всегда и не может быть надёжно выражено через автоматику или skill.
Они самые дорогие, потому что постоянно занимают место в контексте и влияют на каждую задачу, даже если конкретно сейчас это правило не нужно.
Резюмируя
• Если можно зашить в автоматику — зашиваем в автоматику.
• Если это сценарий — пишем skill.
• Если это постоянный инвариант, который агент обязан помнить всегда — пишем rule.
Итого
Не надо пытаться засунуть весь контекст проекта в одно место. Чем точнее вы раскладываете знания по слоям, тем стабильнее и дешевле работает агент.
Интересно ли вам было бы почитать про то, как я пишу скиллы для своих проектов, какие там есть фишки и особенности?
У меня сложилось впечатление, что в сообществе есть определённая путаница на тему мемори-банков, рулсов, MCP и скиллов. Поэтому сегодня хочу поговорить с вами именно на эту тему.
Начнем с определений.
Memory bank — это внешняя память агента о проекте или пользователе.
Туда обычно кладут долгоживущий контекст: архитектурные решения, договорённости, особенности проекта, вкусы команды, важные факты, которые агент должен помнить между сессиями.
По сути, это способ не объяснять одно и то же заново в каждом чате.
Memory bank как “папка с простынями контекста, которую агент должен перечитывать перед работой” — почти устаревший паттерн.
Rules / рулсы — это инструкции для агента, которые задают рамки его поведения.
Например: “используй только pnpm”, “не трогай файлы миграций”, “компоненты называем через PascalCase”, “перед изменением API сначала предложи план”.
MCP — это протокол, через который агент подключается к внешним инструментам и данным.
Например, к GitHub, Jira, Figma, базе данных, Sentry, файловой системе, внутренним сервисам компании.
MCP превращает агента из “чата, который умеет писать текст” в участника рабочего процесса, который может ходить в нужные системы и получать оттуда контекст.
Skills / скиллы — это переиспользуемые сценарии работы агента под конкретные задачи.
Например: “как делать code review”, “как заводить новый пакет в монорепе”, “как писать тесты в этом проекте”, “как оформлять PR”.
Если совсем коротко:
Memory bank хранит контекст.
Rules задают правила поведения.
MCP даёт доступ к инструментам.
Skills описывают рабочие сценарии.
Использовать агента без них сейчас нет совершенно никакого смысла, качество его работы драматически падает без них. Но нужны ли прям все эти инструменты?
Сейчас всё больше фокус смещается в сторону связки rules и skills.
Rules играет роль закона: они всегда в силе и задают рамки, которые агент не должен нарушать. Агент держит их в контексте всегда.
Skills работают как инструменты: агент знает, что они есть и когда их применять, но не держит их целиком в контексте постоянно.
Нужен code review — достал skill для review.
Нужно завести новый пакет — достал skill для этого сценария.
Окей, с теорией разобрались. Давайте попробуем теперь написать алгоритм выбора инстурмента.
Я бы шёл в таком порядке.
1. Сначала линтеры, форматтеры, тесты, типы и скрипты
Если правило можно проверить автоматически, лучше проверять его автоматически. Не надо забивать микроскопом гвозди.
Линтер не забудет, не потратит токены и не начнёт “творчески интерпретировать” инструкцию.
2. Потом skills
Если речь не про жёсткую проверку, а про сценарий действий, лучше оформить это как skill.
Например: как делать code review, как заводить новый модуль, как расследовать падение CI, как готовить релиз.
Skill хорош тем, что не висит в контексте всегда. Агент знает, когда его доставать, и подтягивает подробную инструкцию только под конкретную задачу.
3. И только потом rules
Rules стоит использовать для того, что должно ограничивать агента всегда и не может быть надёжно выражено через автоматику или skill.
Они самые дорогие, потому что постоянно занимают место в контексте и влияют на каждую задачу, даже если конкретно сейчас это правило не нужно.
Резюмируя
• Если можно зашить в автоматику — зашиваем в автоматику.
• Если это сценарий — пишем skill.
• Если это постоянный инвариант, который агент обязан помнить всегда — пишем rule.
Итого
Не надо пытаться засунуть весь контекст проекта в одно место. Чем точнее вы раскладываете знания по слоям, тем стабильнее и дешевле работает агент.
Интересно ли вам было бы почитать про то, как я пишу скиллы для своих проектов, какие там есть фишки и особенности?
1❤33👍15🔥12😎3🥱1
Воскресенье, 3 мая — последний день подачи тестовых в Летние школы
Здарова, работяги!
Многие из вас знают, что я уже несколько лет преподаю в ШРИ(школа разработки интерфейсов Яндекса) React, кто-то возможно даже был на этих лекциях(ссылки на некоторые есть в закрепе). В этом году я решил отойти от привычной темы и сконцентрироваться на новом для меня формате - с деталями и материалами вернусь чуть позже, но буду очень рад видеть вас в числе очных слушателей)
Главное о школах:
Важная инфа: до 3 мая ждём и заявки, и выполненное тестовое — оно приходит на почту сразу после регистрации.
@Young_and_Yandex
Здарова, работяги!
Многие из вас знают, что я уже несколько лет преподаю в ШРИ(школа разработки интерфейсов Яндекса) React, кто-то возможно даже был на этих лекциях(ссылки на некоторые есть в закрепе). В этом году я решил отойти от привычной темы и сконцентрироваться на новом для меня формате - с деталями и материалами вернусь чуть позже, но буду очень рад видеть вас в числе очных слушателей)
Главное о школах:
1️⃣ Направления: бэк (C++ и Java), мобилка (iOS и Android), фронтенд и фулстек, аналитика2️⃣ Занятия очно в июле и августе в московском офисе. Программа насыщенная, но не помешает учёбе, работе и просто отдыху3️⃣ Ограничений по возрасту, вузу, ступени обучения — нет. Ждём всех, кто справится с отбором и готов поучиться летом, а осенью выйти на стажировку4️⃣ Планируем Школы на 400 человек — тебя ждёт широкий нетворк и плотная работа с ментором5️⃣ В программе собрали всё самое прикладное: актуальные технологии и подходы, практические домашки, командную работу над проектами, хакатоны, публичные выступления и вечеринки!
Важная инфа: до 3 мая ждём и заявки, и выполненное тестовое — оно приходит на почту сразу после регистрации.
@Young_and_Yandex
Please open Telegram to view this post
VIEW IN TELEGRAM
Летние школы Яндекса
Ежегодная образовательная программа Яндекса, больше половины выпускников которой становятся стажёрами и сотрудниками компании
👍4🔥2
Здарова, работяги!
В прошлый раз разобрались, чем отличаются memory bank, rules, MCP и skills, и сошлись на том, что основной фокус сейчас — связка rules + skills. Сегодня — как я пишу скилы: что стоит оформлять, что нет, и на что обращать внимание.
Коротко напомню разницу
Rules — правила, которые агент держит в контексте всегда и применяет на каждой задаче.
Skills — переиспользуемые сценарии. Агент знает, что они есть и когда их доставать, но не держит целиком в контексте.
Две главные мысли
Первая: если проблему можно решить не скилами и не рулами — решаем не скилами и не рулами.
Линтеры, форматтеры, тайпчек, скрипты, кодгены — надёжнее и дешевле любого guidance. Не забывают, не жгут токены, не интерпретируют инструкцию творчески. Скилы и рулы — это то, к чему приходим, когда автоматикой уже не получается.
Вторая: скилы не пишем впрок.
Отношусь к ним как к коду — пишу по мере необходимости. Со временем набирается своя база, и появляется чувство:
• какие скилы я всегда тащу в новый проект, потому что они проверены опытом;
• какие подключаю ситуативно — например, для React-проекта имеет смысл взять скилы Vercel про React(но не все);
• какие пишу с нуля под конкретные грабли, которые увидел в работе агента.
Скилл «на будущее» обычно не попадает в реальные сценарии и просто висит балластом. А если их много, агент хуже выбирает нужный и описания начинают конфликтовать. Поэтому: увидел поведение, которое не устраивает → если ответ «скилл», только тогда написал.
Алгоритм: что делать, когда хочется добавить guidance
1. Это уже покрыто? Существующий skill, rules, системный промпт, линтер. Если да — обновляю существующее, а не плодю новое.
2. Можно ли решить тулзами? Линтер, тайпчек, скрипт, кодген. Если правило детерминированное — заводим автоматику. Скилл тогда максимум объясняет, что делать поверх тулзы.
3. Это всегда или ситуативно? Всегда и на каждой задаче — rule. Под конкретный тип задач (ревью, новый пакет и тд) — skill.
Как писать сам скилл
Description — самое важное. Агент видит только description в списке доступных скилов и по нему решает, доставать его или нет. Должно быть два блока:
• WHAT: что скилл делает.
• WHEN: триггеры — слова, контексты, типы задач.
Плохо: «помогает с тестами».
Хорошо: «как писать тесты в проекте. Используй при написании, добавлении или рефакторинге test-файлов. Триггеры: ‘написать тест’, ‘покрыть тестами’, ‘тесты падают’».
SKILL.md держу коротким. Ориентир — до 100 строк. Что не влезает — выношу в отдельные файлы и линкую из основного. Глубже одного уровня ссылок не делаю — агент может просто не дочитать.
Прогрессивное раскрытие. В SKILL.md — то, что нужно в 80% случаев. Детали и редкие сценарии — в отдельные файлы.
Один путь, а не пять вариантов. Если в скиле «можно вот так, или вот так» — агент каждый раз выбирает заново и каждый раз по-разному. Даю дефолт и явный запасной вариант для редких случаев.
Конкретные примеры. «Вот вход, вот выход» работает в разы лучше, чем абзац объяснений.
Скрипты вместо генерации. Детерминированную операцию лучше положить готовым скриптом и вызвать, чем описывать «сгенерируй такой-то код». Скрипт надёжнее и не жрёт токены на генерацию.
Резюме
• Сначала пробуем тулзы, потом скилы, в последнюю очередь — rules.
• Скилы не пишем впрок, только по факту.
• В самом скиле: подробное description с WHAT и WHEN, короткий SKILL.md, один путь, конкретные примеры, скрипты для детерминированных операций.
Скилы — это не документация на все случаи жизни. Это набор маленьких заточенных инструментов под сценарии, которые ты уже видел в работе.
В следующий раз могу показать свою личную подборку скилов — глобальные и те, что чаще всего беру в новые проекты. Интересно?
В прошлый раз разобрались, чем отличаются memory bank, rules, MCP и skills, и сошлись на том, что основной фокус сейчас — связка rules + skills. Сегодня — как я пишу скилы: что стоит оформлять, что нет, и на что обращать внимание.
Коротко напомню разницу
Rules — правила, которые агент держит в контексте всегда и применяет на каждой задаче.
Skills — переиспользуемые сценарии. Агент знает, что они есть и когда их доставать, но не держит целиком в контексте.
Две главные мысли
Первая: если проблему можно решить не скилами и не рулами — решаем не скилами и не рулами.
Линтеры, форматтеры, тайпчек, скрипты, кодгены — надёжнее и дешевле любого guidance. Не забывают, не жгут токены, не интерпретируют инструкцию творчески. Скилы и рулы — это то, к чему приходим, когда автоматикой уже не получается.
Вторая: скилы не пишем впрок.
Отношусь к ним как к коду — пишу по мере необходимости. Со временем набирается своя база, и появляется чувство:
• какие скилы я всегда тащу в новый проект, потому что они проверены опытом;
• какие подключаю ситуативно — например, для React-проекта имеет смысл взять скилы Vercel про React(но не все);
• какие пишу с нуля под конкретные грабли, которые увидел в работе агента.
Скилл «на будущее» обычно не попадает в реальные сценарии и просто висит балластом. А если их много, агент хуже выбирает нужный и описания начинают конфликтовать. Поэтому: увидел поведение, которое не устраивает → если ответ «скилл», только тогда написал.
Алгоритм: что делать, когда хочется добавить guidance
1. Это уже покрыто? Существующий skill, rules, системный промпт, линтер. Если да — обновляю существующее, а не плодю новое.
2. Можно ли решить тулзами? Линтер, тайпчек, скрипт, кодген. Если правило детерминированное — заводим автоматику. Скилл тогда максимум объясняет, что делать поверх тулзы.
3. Это всегда или ситуативно? Всегда и на каждой задаче — rule. Под конкретный тип задач (ревью, новый пакет и тд) — skill.
Как писать сам скилл
Description — самое важное. Агент видит только description в списке доступных скилов и по нему решает, доставать его или нет. Должно быть два блока:
• WHAT: что скилл делает.
• WHEN: триггеры — слова, контексты, типы задач.
Плохо: «помогает с тестами».
Хорошо: «как писать тесты в проекте. Используй при написании, добавлении или рефакторинге test-файлов. Триггеры: ‘написать тест’, ‘покрыть тестами’, ‘тесты падают’».
SKILL.md держу коротким. Ориентир — до 100 строк. Что не влезает — выношу в отдельные файлы и линкую из основного. Глубже одного уровня ссылок не делаю — агент может просто не дочитать.
Прогрессивное раскрытие. В SKILL.md — то, что нужно в 80% случаев. Детали и редкие сценарии — в отдельные файлы.
Один путь, а не пять вариантов. Если в скиле «можно вот так, или вот так» — агент каждый раз выбирает заново и каждый раз по-разному. Даю дефолт и явный запасной вариант для редких случаев.
Конкретные примеры. «Вот вход, вот выход» работает в разы лучше, чем абзац объяснений.
Скрипты вместо генерации. Детерминированную операцию лучше положить готовым скриптом и вызвать, чем описывать «сгенерируй такой-то код». Скрипт надёжнее и не жрёт токены на генерацию.
Резюме
• Сначала пробуем тулзы, потом скилы, в последнюю очередь — rules.
• Скилы не пишем впрок, только по факту.
• В самом скиле: подробное description с WHAT и WHEN, короткий SKILL.md, один путь, конкретные примеры, скрипты для детерминированных операций.
Скилы — это не документация на все случаи жизни. Это набор маленьких заточенных инструментов под сценарии, которые ты уже видел в работе.
В следующий раз могу показать свою личную подборку скилов — глобальные и те, что чаще всего беру в новые проекты. Интересно?
1🔥38❤1👍1
Пост фана и чутка рекламы 🚶
Я сам не из Москвы: приехал сюда учиться примерно 10 лет назад. Скажу как есть: изначально город мне не зашёл. Он был совсем не похож на уютную Рязань, где я вырос. Особенно усугубляли ситуацию осень(начало учебного года) и идущая за ней зима — с темнотой, серостью и вот этим всем.
В какой-то момент я смирился: ну, видимо, город такой. Сконцентрировался на учёбе, потом на работе.
Но со временем отношение менялось. Я люблю ходить пешком: иногда выхожу на пару станций раньше и иду остаток пути ногами, а иногда вообще обхожусь без транспорта — в разумных пределах, конечно. Так постепенно проникался городом и находил новые места.
Сейчас я уже совсем не могу надолго уехать: быстро начинаю скучать. Обожаю осень, весну и лето в Москве. Зиму, правда, так и не полюбил 😄
В моей истории большую роль сыграли пешие прогулки. Но ещё очень крутой формат — разные забеги по городу, квесты и похожие активности. Они позволяют иначе взглянуть на любимый город.
Яндекс решил организовать один из таких форматов — «Рекурсия по городу»: командное офлайн-приключение в формате CTF. Будет 35+ заданий по маршруту через точки, связанные с историей российской IT-индустрии: в том числе через территорию МГУ, центр фундаментальных исследований РАН и другие места.
Старт — в одной из моих любимых локаций: штаб-квартире Яндекса в «Красной Розе».
Если вам тоже интересны такие активности, переходите по ссылке и регайте команду
Я сам не из Москвы: приехал сюда учиться примерно 10 лет назад. Скажу как есть: изначально город мне не зашёл. Он был совсем не похож на уютную Рязань, где я вырос. Особенно усугубляли ситуацию осень(начало учебного года) и идущая за ней зима — с темнотой, серостью и вот этим всем.
В какой-то момент я смирился: ну, видимо, город такой. Сконцентрировался на учёбе, потом на работе.
Но со временем отношение менялось. Я люблю ходить пешком: иногда выхожу на пару станций раньше и иду остаток пути ногами, а иногда вообще обхожусь без транспорта — в разумных пределах, конечно. Так постепенно проникался городом и находил новые места.
Сейчас я уже совсем не могу надолго уехать: быстро начинаю скучать. Обожаю осень, весну и лето в Москве. Зиму, правда, так и не полюбил 😄
В моей истории большую роль сыграли пешие прогулки. Но ещё очень крутой формат — разные забеги по городу, квесты и похожие активности. Они позволяют иначе взглянуть на любимый город.
Яндекс решил организовать один из таких форматов — «Рекурсия по городу»: командное офлайн-приключение в формате CTF. Будет 35+ заданий по маршруту через точки, связанные с историей российской IT-индустрии: в том числе через территорию МГУ, центр фундаментальных исследований РАН и другие места.
Старт — в одной из моих любимых локаций: штаб-квартире Яндекса в «Красной Розе».
Если вам тоже интересны такие активности, переходите по ссылке и регайте команду
Рекурсия по городу — командная офлайн-игра, 23 мая
CTF-приключение, где вы вместе с командой разгадаете загадку архивного FTP-сервера и почувствуете инженерную культуру Москвы. Вам предстоит перемещаться по городу, находить «флаги» и постепенно чинить систему, которая зациклила реальность.
❤10🔥6🥰3👍2
Здарова, работяги!
В прошлый раз говорили про скилы. Сегодня — про линтеры и форматтеры: как я выбирал стек на новом проекте, почему сначала взял Biome и почему переехал на oxlint + oxfmt.
Почему про линтеры
Как уже писал, прежде чем тащить guidance в скилы и рулы, стоит посмотреть, нельзя ли закрыть это автоматикой. Линтер — бесплатный детерминированный гейт: не забывает, не интерпретирует, не жжёт токены. Особенно ценно при работе с агентом — каждое правило в линтере = минус один пункт в guidance и минус один способ облажаться.
Что было на столе
— ESLint + Prettier — максимум правил и плагинов, но два тула, медленно, конфигурить долго.
— Biome — один тул на всё (lint + format + import sort), быстрый, конфиг простой.
— oxlint + oxfmt — Rust-стек от oxc: быстрый линтер с большим покрытием ESLint-правил и отдельный форматтер.
Сравнение коротко
— Скорость: oxlint > Biome >> ESLint+Prettier.
— Количество тулов: Biome — один. oxlint + oxfmt и ESLint + Prettier — два, но oxlint + oxfmt живут в одной экосистеме и конфигурятся проще.
— Покрытие правилами: ESLint — максимум. oxlint — большая часть популярных ESLint-правил, пул растёт. Biome — свой набор, заметно уже.
— Конфигурируемость: ESLint — максимум. oxlint — гибко, overrides, плагины. Biome — намеренно ограничено.
— Экосистема: ESLint — всё. oxlint — догоняет, ключевые плагины (react, typescript, import) уже есть. Biome — самодостаточно, плагинов нет.
Почему сначала взял Biome
Просто, быстро, один тул. На старте проекта это закрывает 90% потребностей с нулевой настройкой.
Почему слез
Пожил пару недель и понял, что правил банально не хватает.
— Нет аналога consistent-type-assertions. Запрет as SomeType — критичное правило, потому что агенты обожают кастить типы вместо того, чтобы написать type guard или поправить сигнатуру. Без линтера это ловится только на ревью, и то не всегда.
— Слабый no-restricted-imports. Хотелось паттернами фиксировать границы модулей в монорепе — в Biome либо никак, либо очень куцо.
— Нет react/no-multi-comp и подобных мелочей, которые модель регулярно норовит нарушить.
— overrides по glob сильно ограничены, не получается тонко настроить правила под разные части репы.
В итоге половину инвариантов пришлось бы тащить в AGENTS.md как текстовое правило — а это ровно то, чего стараюсь избегать.
Переход на oxlint + oxfmt
— Все важные ESLint-правила, которых не хватало, есть из коробки.
— overrides по glob позволяют жёстко зафиксировать границы между приложениями и пакетами в монорепе.
— Скорость на уровне Biome, на больших прогонах даже лучше.
— AGENTS.md похудел: куча пунктов уехала в линтер.
Форматтер (oxfmt) пока проще биомовского, но мне его хватает.
Резюме
— При работе с агентами линтер обязателен.
— Biome — отличный выбор для небольших проектов, пока хватает встроенных правил.
— ESLint + Prettier сейчас не вижу смысла брать: медленнее, конфигурить дольше, а у oxlint уже хорошее покрытие правил.
— oxlint + oxfmt — мой текущий дефолт.
В прошлый раз говорили про скилы. Сегодня — про линтеры и форматтеры: как я выбирал стек на новом проекте, почему сначала взял Biome и почему переехал на oxlint + oxfmt.
Почему про линтеры
Как уже писал, прежде чем тащить guidance в скилы и рулы, стоит посмотреть, нельзя ли закрыть это автоматикой. Линтер — бесплатный детерминированный гейт: не забывает, не интерпретирует, не жжёт токены. Особенно ценно при работе с агентом — каждое правило в линтере = минус один пункт в guidance и минус один способ облажаться.
Что было на столе
— ESLint + Prettier — максимум правил и плагинов, но два тула, медленно, конфигурить долго.
— Biome — один тул на всё (lint + format + import sort), быстрый, конфиг простой.
— oxlint + oxfmt — Rust-стек от oxc: быстрый линтер с большим покрытием ESLint-правил и отдельный форматтер.
Сравнение коротко
— Скорость: oxlint > Biome >> ESLint+Prettier.
— Количество тулов: Biome — один. oxlint + oxfmt и ESLint + Prettier — два, но oxlint + oxfmt живут в одной экосистеме и конфигурятся проще.
— Покрытие правилами: ESLint — максимум. oxlint — большая часть популярных ESLint-правил, пул растёт. Biome — свой набор, заметно уже.
— Конфигурируемость: ESLint — максимум. oxlint — гибко, overrides, плагины. Biome — намеренно ограничено.
— Экосистема: ESLint — всё. oxlint — догоняет, ключевые плагины (react, typescript, import) уже есть. Biome — самодостаточно, плагинов нет.
Почему сначала взял Biome
Просто, быстро, один тул. На старте проекта это закрывает 90% потребностей с нулевой настройкой.
Почему слез
Пожил пару недель и понял, что правил банально не хватает.
— Нет аналога consistent-type-assertions. Запрет as SomeType — критичное правило, потому что агенты обожают кастить типы вместо того, чтобы написать type guard или поправить сигнатуру. Без линтера это ловится только на ревью, и то не всегда.
— Слабый no-restricted-imports. Хотелось паттернами фиксировать границы модулей в монорепе — в Biome либо никак, либо очень куцо.
— Нет react/no-multi-comp и подобных мелочей, которые модель регулярно норовит нарушить.
— overrides по glob сильно ограничены, не получается тонко настроить правила под разные части репы.
В итоге половину инвариантов пришлось бы тащить в AGENTS.md как текстовое правило — а это ровно то, чего стараюсь избегать.
Переход на oxlint + oxfmt
— Все важные ESLint-правила, которых не хватало, есть из коробки.
— overrides по glob позволяют жёстко зафиксировать границы между приложениями и пакетами в монорепе.
— Скорость на уровне Biome, на больших прогонах даже лучше.
— AGENTS.md похудел: куча пунктов уехала в линтер.
Форматтер (oxfmt) пока проще биомовского, но мне его хватает.
Резюме
— При работе с агентами линтер обязателен.
— Biome — отличный выбор для небольших проектов, пока хватает встроенных правил.
— ESLint + Prettier сейчас не вижу смысла брать: медленнее, конфигурить дольше, а у oxlint уже хорошее покрытие правил.
— oxlint + oxfmt — мой текущий дефолт.
1✍27🔥7❤4👍4
Интересен ли вам еще формат видео(утуб, вквидео и тд) или лучше сконцентрироваться на тг?
Anonymous Poll
83%
Да 🤓
17%
Нет, лучше больше постов в тг 🤬
🍌2
ТОП - Тёма о программировани
Интересен ли вам еще формат видео(утуб, вквидео и тд) или лучше сконцентрироваться на тг?
Понял, принял, делаем 👨💻
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22🎉9❤3🍌1
Здарова, работяги!
Сегодня разберёмся, в чём боль code-first, что меняет schema-first и как это выглядит в Fastify.
Code-first
Правила формы данных живут в коде, рассыпанные по разным местам. Валидация — отдельная функция. Типы — отдельный интерфейс. Обе сущности — копии одной и той же правды в разных синтаксисах.
Знакомая картина — ручная валидация формы:
Два источника правды на одну сущность. Один обновил — другой забыл. Дальше прод, неприятный сюрприз, разбор полётов в Slack.
Schema-first
Подход, при котором описание формы данных живёт отдельно от бизнес-логики и является источником правды. Описываем форму декларативно — например, объектом JSON Schema. Дальше из этого объекта получаются:
— валидация входа (запрос проверяется по схеме до того, как попадёт в обработчик);
— сериализация выхода (ответ режется по схеме, лишние поля не уйдут наружу);
— TypeScript-типы (генерятся из схемы — например, через TypeBox или json-schema-to-ts).
Одна декларация — три артефакта. Обновил схему — всё остальное само догнало.
Как это в Fastify
Fastify построен вокруг schema-first из коробки. Минимальный пример:
Что мы получили бесплатно:
— request body валидируется до обработчика. Невалидный — 400 с понятным сообщением, обработчик даже не дёргается;
— response сериализуется по схеме. Если в user внезапно прилетело password_hash — он не уйдёт наружу. Это и про безопасность, и про предсказуемость контракта;
— additionalProperties: false режет лишние поля на входе. Прислали лишнее — до обработчика оно не доедет. Если хочется именно 400, это уже настраивается через Ajv.
Бонусом — скорость
Под капотом сериализация ответа идёт не через JSON.stringify, а через fast-json-stringify: на старте по response-схеме компилируется специализированная функция, и дальше она работает в разы быстрее (в бенчах самой библиотеки — до 2x на типовых ответах). JSON.stringify каждый раз обходит объект на ходу и не знает заранее, какие поля в нём окажутся. fast-json-stringify знает структуру и идёт почти прямым проходом по известным полям. Платим за это одной компиляцией на старте — копейки.
Дока Fastify.
Резюме
— schema-first даёт один источник правды — декларацию данных, из которой вытекают валидация, сериализация и типы;
— code-first проще на старте, но копии одной правды быстро расходятся, и это всегда вылазит больно;
— в Fastify это работает из коробки, плюс бонусом сериализация в разы быстрее обычного JSON.stringify.
Сегодня разберёмся, в чём боль code-first, что меняет schema-first и как это выглядит в Fastify.
Code-first
Правила формы данных живут в коде, рассыпанные по разным местам. Валидация — отдельная функция. Типы — отдельный интерфейс. Обе сущности — копии одной и той же правды в разных синтаксисах.
Знакомая картина — ручная валидация формы:
function validateUserForm(values) {
const errors = {}
if (!values.email) errors.email = 'required'
if (!values.age || Number.isNaN(+values.age)) errors.age = 'must be number'
return errors
}
// где-то рядом
type UserForm = { email: string; age: number }
Два источника правды на одну сущность. Один обновил — другой забыл. Дальше прод, неприятный сюрприз, разбор полётов в Slack.
Schema-first
Подход, при котором описание формы данных живёт отдельно от бизнес-логики и является источником правды. Описываем форму декларативно — например, объектом JSON Schema. Дальше из этого объекта получаются:
— валидация входа (запрос проверяется по схеме до того, как попадёт в обработчик);
— сериализация выхода (ответ режется по схеме, лишние поля не уйдут наружу);
— TypeScript-типы (генерятся из схемы — например, через TypeBox или json-schema-to-ts).
Одна декларация — три артефакта. Обновил схему — всё остальное само догнало.
Как это в Fastify
Fastify построен вокруг schema-first из коробки. Минимальный пример:
const schema = {
body: {
type: 'object',
required: ['email', 'age'],
properties: {
email: { type: 'string', format: 'email' },
age: { type: 'integer' }
},
additionalProperties: false
},
response: {
201: {
type: 'object',
properties: {
id: { type: 'integer' },
email: { type: 'string' }
}
}
}
}
fastify.post('/users', { schema }, async (req, reply) => {
const user = await db.users.insert(req.body)
reply.code(201).send(user)
})
Что мы получили бесплатно:
— request body валидируется до обработчика. Невалидный — 400 с понятным сообщением, обработчик даже не дёргается;
— response сериализуется по схеме. Если в user внезапно прилетело password_hash — он не уйдёт наружу. Это и про безопасность, и про предсказуемость контракта;
— additionalProperties: false режет лишние поля на входе. Прислали лишнее — до обработчика оно не доедет. Если хочется именно 400, это уже настраивается через Ajv.
Бонусом — скорость
Под капотом сериализация ответа идёт не через JSON.stringify, а через fast-json-stringify: на старте по response-схеме компилируется специализированная функция, и дальше она работает в разы быстрее (в бенчах самой библиотеки — до 2x на типовых ответах). JSON.stringify каждый раз обходит объект на ходу и не знает заранее, какие поля в нём окажутся. fast-json-stringify знает структуру и идёт почти прямым проходом по известным полям. Платим за это одной компиляцией на старте — копейки.
Дока Fastify.
Резюме
— schema-first даёт один источник правды — декларацию данных, из которой вытекают валидация, сериализация и типы;
— code-first проще на старте, но копии одной правды быстро расходятся, и это всегда вылазит больно;
— в Fastify это работает из коробки, плюс бонусом сериализация в разы быстрее обычного JSON.stringify.
Fastify
Fastify - Fast and Low Overhead Web Framework
Fastify is a fast and low overhead web framework for Node.js.
1🔥20❤3👍3🍌2
Здарова, работяги!
Около четырёх лет назад я прочитал лекцию React(продвинутый) в ШРИ. Там был большой разбор про то, как React работает под капотом.
Лекция неожиданно для меня хорошо зашла: я-то её планировал на аудиторию студентов ШРИ, а получилось 92к просмотров. До сих пор люди иногда пишут, что именно после неё у них щёлкнуло понимание React, и это меня сильно мотивирует.
Потом я надолго почти перестал писать про React.
Причина простая: я несколько лет преподавал React, не только в ШРИ, и в какой-то момент накопилась усталость скорее от преподавания, чем от самой темы.
А пока отдыхал, React взял и уехал вперёд.
Что осталось прежним
Главная база из той лекции не умерла.
React всё ещё не “просто меняет DOM”. Он строит work-in-progress дерево, сравнивает его с текущим деревом, готовит изменения и потом коммитит результат.
Ререндер всё ещё не равен “браузер перерисовал весь экран”.
Ремаунт всё ещё может внезапно стереть локальный state.
Фаза коммита всё ещё не то место, где React может спокойно сказать: “ой, браузер занят, я продолжу позже”. Если дошли до применения изменений — надо применять.
То есть если вы тогда поняли идею
Но сменился фокус
Раньше React часто объясняли через
Мол, React строит виртуальное дерево, сравнивает с прошлым, находит разницу и аккуратно обновляет настоящий DOM.
Как первая ступенька — норм. Как полная модель — уже слабовато.
Современный React всё меньше хочется объяснять через “сравнение деревьев” и всё больше через планирование работы.
Не просто:
— что изменилось;
— какой компонент ререндерится;
— сколько DOM-нод надо обновить.
А ещё:
— срочная это работа или нет;
— можно ли её прервать;
— можно ли показать старый UI, пока новый готовится;
— можно ли часть работы сделать на сервере;
— можно ли вообще не делать ручную мемоизацию, потому что её заберёт Compiler.
Вот это, по моему ощущению, главный сдвиг последних лет.
React стал не только библиотекой для описания UI. Он всё больше становится runtime-ом, который управляет тем, когда, где и с каким приоритетом этот UI должен появиться.
В старой лекции был классический пример:
родитель хранит
Решения тогда были понятные:
— изолировать state ближе к месту использования;
— не поднимать состояние без причины;
— следить за ремаунтами;
— аккуратно использовать
— профилировать, а не гадать по ощущениям.
И это всё ещё хорошие советы.
Но теперь этого слоя знаний уже недостаточно.
React 18 принёс автоматический батчинг и конкурентный рендеринг. Появились
Не магия. Не “теперь можно не думать”. Скорее наоборот: думать надо глубже и немного о другом.
Поэтому я хочу сделать серию постов про современный React через призму той старой лекции.
Не “что нового в React 18/19” списком из ченджлогов. А нормально, по-работяжьи:
— что из старой модели всё ещё держится;
— где старые объяснения стали слишком грубыми;
— как батчинг, транзишены и отложенный рендеринг меняют разговор про ререндеры;
— почему Suspense теперь не только про
— зачем нужны Server Components и почему
— что React Compiler меняет в привычке мемоизировать всё руками.
Короче, будем снова залезать под капот React. Только уже не того React времён “хуки ещё выглядят свежей штукой”, а React, который пытается управлять всей жизнью интерфейса: от серверной работы до срочности обновлений на клиенте.
Около четырёх лет назад я прочитал лекцию React(продвинутый) в ШРИ. Там был большой разбор про то, как React работает под капотом.
Лекция неожиданно для меня хорошо зашла: я-то её планировал на аудиторию студентов ШРИ, а получилось 92к просмотров. До сих пор люди иногда пишут, что именно после неё у них щёлкнуло понимание React, и это меня сильно мотивирует.
Потом я надолго почти перестал писать про React.
Причина простая: я несколько лет преподавал React, не только в ШРИ, и в какой-то момент накопилась усталость скорее от преподавания, чем от самой темы.
А пока отдыхал, React взял и уехал вперёд.
Что осталось прежним
Главная база из той лекции не умерла.
React всё ещё не “просто меняет DOM”. Он строит work-in-progress дерево, сравнивает его с текущим деревом, готовит изменения и потом коммитит результат.
Ререндер всё ещё не равен “браузер перерисовал весь экран”.
key всё ещё влияет на то, считает ли React компонент “тем же самым” между рендерами.Ремаунт всё ещё может внезапно стереть локальный state.
Фаза коммита всё ещё не то место, где React может спокойно сказать: “ой, браузер занят, я продолжу позже”. Если дошли до применения изменений — надо применять.
То есть если вы тогда поняли идею
current tree и work-in-progress tree, это знание не превратилось в тыкву.Но сменился фокус
Раньше React часто объясняли через
Virtual DOM.Мол, React строит виртуальное дерево, сравнивает с прошлым, находит разницу и аккуратно обновляет настоящий DOM.
Как первая ступенька — норм. Как полная модель — уже слабовато.
Современный React всё меньше хочется объяснять через “сравнение деревьев” и всё больше через планирование работы.
Не просто:
— что изменилось;
— какой компонент ререндерится;
— сколько DOM-нод надо обновить.
А ещё:
— срочная это работа или нет;
— можно ли её прервать;
— можно ли показать старый UI, пока новый готовится;
— можно ли часть работы сделать на сервере;
— можно ли вообще не делать ручную мемоизацию, потому что её заберёт Compiler.
Вот это, по моему ощущению, главный сдвиг последних лет.
React стал не только библиотекой для описания UI. Он всё больше становится runtime-ом, который управляет тем, когда, где и с каким приоритетом этот UI должен появиться.
В старой лекции был классический пример:
родитель хранит
count, рядом лежит тяжёлый ChildVerySlow, нажимаем кнопку — и внезапно страдает вообще не тот компонент, который визуально поменялся.Решения тогда были понятные:
— изолировать state ближе к месту использования;
— не поднимать состояние без причины;
— следить за ремаунтами;
— аккуратно использовать
React.memo;— профилировать, а не гадать по ощущениям.
И это всё ещё хорошие советы.
Но теперь этого слоя знаний уже недостаточно.
React 18 принёс автоматический батчинг и конкурентный рендеринг. Появились
startTransition и useDeferredValue. Suspense перестал быть просто красивой обёрткой вокруг lazy. Server Components поменяли вопрос с “как быстрее отрендерить на клиенте” на “а должна ли эта работа вообще попасть на клиент”. React Compiler начал двигать нас в сторону мира, где часть ручного memo, useMemo и useCallback становится внутренней заботой React, а не обязательной ручной работой разработчика.Не магия. Не “теперь можно не думать”. Скорее наоборот: думать надо глубже и немного о другом.
Поэтому я хочу сделать серию постов про современный React через призму той старой лекции.
Не “что нового в React 18/19” списком из ченджлогов. А нормально, по-работяжьи:
— что из старой модели всё ещё держится;
— где старые объяснения стали слишком грубыми;
— как батчинг, транзишены и отложенный рендеринг меняют разговор про ререндеры;
— почему Suspense теперь не только про
React.lazy;— зачем нужны Server Components и почему
use client нельзя расставлять на автопилоте;— что React Compiler меняет в привычке мемоизировать всё руками.
Короче, будем снова залезать под капот React. Только уже не того React времён “хуки ещё выглядят свежей штукой”, а React, который пытается управлять всей жизнью интерфейса: от серверной работы до срочности обновлений на клиенте.
YouTube
React (продвинутый)
Продолжаем изучение React. Заглянем «под капот» и разберём тонкости использования библиотеки.
5🔥113👍20❤13🦄3🙏2
«Кто-то должен был это сказать!» — эта мысль не покидала нас, пока слушали новый сезон подкаста «Свободный слот» 🌟
В нём коллеги из Авито говорят на темы, которых лиды стараются избегать: от переоценки собственных сил и одиночества до тревоги по поводу AI.
А ещё у ребят есть канал — там они делятся мыслями, которые не попали в выпуски, полезными статьями и анонсами митапов. Очень советуем заглянуть!
В нём коллеги из Авито говорят на темы, которых лиды стараются избегать: от переоценки собственных сил и одиночества до тревоги по поводу AI.
А ещё у ребят есть канал — там они делятся мыслями, которые не попали в выпуски, полезными статьями и анонсами митапов. Очень советуем заглянуть!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🤮2👍1👏1👌1
Здарова, работяги!
Продолжаем про React.
Если бы я сейчас пересобирал старую лекцию про React, я бы начал не с FPS.
Тогда я заходил через плавность интерфейса: пользователь нажал кнопку, ввёл текст, открыл попап — интерфейс должен ответить без подвисаний.
Это всё ещё правда. Но сейчас я бы быстрее переходил к другому вопросу: какую работу пользователь должен увидеть сразу, а какая может подождать.
Старый заход
В той лекции я шел через 60 FPS.
Идея простая: между двумя кадрами у браузера очень мало времени. Если JS надолго занял поток, браузер не успел отрисовать следующий кадр — интерфейс дёрнулся.
Это не устарело. Просто
Fiber в этой истории был ответом на проблему: React перестал воспринимать рендер как один большой кусок работы. Новое дерево можно готовить частями, а не в режиме «начали — теперь все ждут».
Эта база держится. Если вы заблокировали главный поток тяжёлым JS, пользователю всё равно будет плохо.
Но как объяснение современного React этого уже мало.
Чего здесь не хватает
Проблема не только в том, сколько работы делает интерфейс. Проблема ещё и в том, какая это работа.
Пользователь печатает в инпуте — символ должен появиться сразу. Иначе это ощущается не как «рендер не успел», а как сломанная клавиатура.
А пересчитать результаты поиска, перестроить таблицу или подготовить следующий экран можно чуть позже. Пользователь не ждёт каждый промежуточный результат. Он ждёт, чтобы интерфейс не вставал колом.
Раньше мы почти всегда упирались в один совет: сделай работу быстрее. Профилируй, мемоизируй, выноси state ближе к месту использования.
И это всё ещё правильный совет. Просто он не закрывает весь кейс. Иногда работа нужная, но пользователь не обязан ждать её прямо сейчас.
Что изменилось в модели
Современный React всё меньше похож на прослойку для обновления DOM и всё больше — на механизм управления работой интерфейса.
Не только:
— что изменилось;
— какие компоненты надо пересчитать;
— какие DOM-изменения потом применить.
А ещё:
— что должно ответить сразу;
— что можно подготовить в фоне;
— что можно прервать и начать заново;
— что вообще лучше не тащить на клиент.
Вот почему старая рамка
Пример такой фичи
Ввод в поле — срочный. Пересчёт тяжёлого списка по этому вводу — часто нет. Поэтому одно обновление должно пройти сразу, а второе может догнать позже.
Но это не пост про
Важно отметить, что transition не делает медленный код быстрым. Синхронный фильтр на десять тысяч строк React не превратит в фоновую магию.
Так что старые инструменты никуда не делись: убирать лишнюю работу всё ещё надо. Просто теперь появился ещё один вопрос: что из оставшейся работы можно показать позже.
Как я бы объяснял сейчас
Раньше я бы больше давил на то, как React сам организует рендер: строит новое дерево, может прервать подготовку, потом одним куском коммитит результат.
Сейчас я бы добавил второй слой: разработчик тоже всё чаще участвует в разговоре о приоритетах. Что должно ответить сразу. Что можно подготовить позже. Где показать старый экран, пока новый ещё собирается.
Разница в формулировке маленькая, а в голове большая.
Потому что дальше в эту же рамку ложатся транзишены, Suspense, стриминг и Server Components. Это не просто набор новых фич, а попытка разложить интерфейс по границам: что сделать сразу, что догрузить потом, что можно прервать.
Вот это, по-моему, и есть главный сдвиг.
Резюме
— ограничение по времени на кадр всё ещё актуально, но это не вся история;
— современный React удобнее объяснять через вопрос: что делать сейчас, а что позже;
— React и раньше управлял рендером, но теперь разработчик чаще явно участвует в выборе приоритетов;
— главный вопрос теперь не только «как сделать меньше работы», но и «что пользователь должен увидеть сразу».
Продолжаем про React.
Если бы я сейчас пересобирал старую лекцию про React, я бы начал не с FPS.
Тогда я заходил через плавность интерфейса: пользователь нажал кнопку, ввёл текст, открыл попап — интерфейс должен ответить без подвисаний.
Это всё ещё правда. Но сейчас я бы быстрее переходил к другому вопросу: какую работу пользователь должен увидеть сразу, а какая может подождать.
Старый заход
В той лекции я шел через 60 FPS.
Идея простая: между двумя кадрами у браузера очень мало времени. Если JS надолго занял поток, браузер не успел отрисовать следующий кадр — интерфейс дёрнулся.
Это не устарело. Просто
60 FPS — слишком грубая рамка, если на ней остановиться.Fiber в этой истории был ответом на проблему: React перестал воспринимать рендер как один большой кусок работы. Новое дерево можно готовить частями, а не в режиме «начали — теперь все ждут».
Эта база держится. Если вы заблокировали главный поток тяжёлым JS, пользователю всё равно будет плохо.
Но как объяснение современного React этого уже мало.
Чего здесь не хватает
Проблема не только в том, сколько работы делает интерфейс. Проблема ещё и в том, какая это работа.
Пользователь печатает в инпуте — символ должен появиться сразу. Иначе это ощущается не как «рендер не успел», а как сломанная клавиатура.
А пересчитать результаты поиска, перестроить таблицу или подготовить следующий экран можно чуть позже. Пользователь не ждёт каждый промежуточный результат. Он ждёт, чтобы интерфейс не вставал колом.
Раньше мы почти всегда упирались в один совет: сделай работу быстрее. Профилируй, мемоизируй, выноси state ближе к месту использования.
И это всё ещё правильный совет. Просто он не закрывает весь кейс. Иногда работа нужная, но пользователь не обязан ждать её прямо сейчас.
Что изменилось в модели
Современный React всё меньше похож на прослойку для обновления DOM и всё больше — на механизм управления работой интерфейса.
Не только:
— что изменилось;
— какие компоненты надо пересчитать;
— какие DOM-изменения потом применить.
А ещё:
— что должно ответить сразу;
— что можно подготовить в фоне;
— что можно прервать и начать заново;
— что вообще лучше не тащить на клиент.
Вот почему старая рамка
60 FPS стала тесной.Пример такой фичи
startTransition — просто самый наглядный пример этой идеи.Ввод в поле — срочный. Пересчёт тяжёлого списка по этому вводу — часто нет. Поэтому одно обновление должно пройти сразу, а второе может догнать позже.
Но это не пост про
startTransition. Для него нужен отдельный разбор.Важно отметить, что transition не делает медленный код быстрым. Синхронный фильтр на десять тысяч строк React не превратит в фоновую магию.
Так что старые инструменты никуда не делись: убирать лишнюю работу всё ещё надо. Просто теперь появился ещё один вопрос: что из оставшейся работы можно показать позже.
Как я бы объяснял сейчас
Раньше я бы больше давил на то, как React сам организует рендер: строит новое дерево, может прервать подготовку, потом одним куском коммитит результат.
Сейчас я бы добавил второй слой: разработчик тоже всё чаще участвует в разговоре о приоритетах. Что должно ответить сразу. Что можно подготовить позже. Где показать старый экран, пока новый ещё собирается.
Разница в формулировке маленькая, а в голове большая.
Потому что дальше в эту же рамку ложатся транзишены, Suspense, стриминг и Server Components. Это не просто набор новых фич, а попытка разложить интерфейс по границам: что сделать сразу, что догрузить потом, что можно прервать.
Вот это, по-моему, и есть главный сдвиг.
Резюме
— ограничение по времени на кадр всё ещё актуально, но это не вся история;
— современный React удобнее объяснять через вопрос: что делать сейчас, а что позже;
— React и раньше управлял рендером, но теперь разработчик чаще явно участвует в выборе приоритетов;
— главный вопрос теперь не только «как сделать меньше работы», но и «что пользователь должен увидеть сразу».
Telegram
ТОП - Тёма о программировани
Здарова, работяги!
Около четырёх лет назад я прочитал лекцию React(продвинутый) в ШРИ. Там был большой разбор про то, как React работает под капотом.
Лекция неожиданно для меня хорошо зашла: я-то её планировал на аудиторию студентов ШРИ, а получилось 92к…
Около четырёх лет назад я прочитал лекцию React(продвинутый) в ШРИ. Там был большой разбор про то, как React работает под капотом.
Лекция неожиданно для меня хорошо зашла: я-то её планировал на аудиторию студентов ШРИ, а получилось 92к…
3🔥26👍11❤2