learn-se · Урок 6 · ~18 минут · приоритет №1 миссии

Нарезка задач: вертикальные срезы вместо горизонтальных слоёв

Твоя миссия №1 — ставить задачи точно. Половина точности — не в формулировке одной задачи, а в том, как ты режешь фичу на задачи. Правильная нарезка держит агента в узком коридоре, даёт тебе рабочий продукт после каждого шага и не даёт увязнуть. Мы уже сделали это 8 раз руками — теперь назовём правило.

Одна идея урока

Режь фичу на тонкие вертикальные срезы, каждый из которых идёт сквозь все слои (данные → логика → UI) и работает сам по себе. Не на горизонтальные слои («сначала вся база, потом весь API, потом весь UI»).

1 · Вертикально, а не горизонтально

Есть два способа разбить фичу на куски. Разница решает, увидишь ли ты работающий продукт на первый день — или на тридцатый.

Горизонтальный слой. «Задача 1: вся схема БД. Задача 2: все API-роуты. Задача 3: весь UI.» Каждый кусок — целый слой вширь. Проблема: ничего не работает, пока не готов последний слой. Три недели ты не можешь ничего проверить вживую.
Вертикальный срез. «Задача 1: клиент сохраняет ОДНО поле и видит его — таблица + роут + карточка.» Тонкая нитка сквозь все слои. Проблема решена: после первого же среза есть что запустить и принять.
Как отличить в диффе. Вертикальный срез виден по форме (урок 5): миграция + хук + компонент = 3 слоя. Если дифф — только миграции и ни одного компонента, тебе принесли горизонтальный слой, а не срез. Спроси: «а где я это увижу вживую?»
Живой пример — Срез 1 чек-инов Первый срез не был «вся фича чек-инов». Он был предельно узкой ниткой: клиент отправляет вес за неделю и видит его. Один сценарий, сквозь все слои — check_ins + правило доступа, один роут, одна CheckInCard. Тренер, фото, расписание, офлайн, пуши — всё это отдельные срезы позже. После Среза 1 уже было что задеплоить и потрогать.

2 · Первый срез — walking skeleton

Самый первый срез фичи имеет имя: walking skeleton — «шагающий скелет». Это тончайшая сквозная нитка, которая уже работает end-to-end, но почти ничего не умеет. Скелет ходит — то есть данные реально долетают от UI до базы и обратно, — но мяса на нём нет.

Когда применять. Почти всегда для новой фичи. Скелет снимает главный риск рано: «а вообще эта нитка проходит сквозь auth, RLS, паттерн проекта?» Именно скелет чек-инов поймал баг с незалогиненным клиентом (урок 5) — на первом же срезе, а не на тридцатом.
Когда вредно / перебор. Скелет — это не «пустой каркас без единого рабочего сценария». Если ты нарезал так тонко, что срез ничего не делает вживую (например «просто создать таблицу»), это уже горизонтальный слой, а не скелет. Скелет обязан ходить.
Цена. У скелета есть накладная стоимость: каждый срез — это отдельная интеграция, отдельная приёмка, отдельный коммит. Слишком мелкая нарезка = много церемоний на грамм пользы. Баланс: срез должен быть тонким, но целым сценарием.
Правило толщины среза

Хороший срез проходит тест: «его можно продемонстрировать одним предложением в настоящем времени».
✅ «Клиент сохраняет вес и видит его» — целый сценарий.
✅ «Тренер видит чек-ины клиента» — целый сценарий.
❌ «Создана таблица check_ins» — не сценарий, это кусок слоя.
❌ «Готова вся фича чек-инов с фото, расписанием и пушами» — не тонко, это месяц работы одним куском.

3 · Как секвенировать срезы и как отдавать их агенту

Скелет прошёл — дальше ты расширяешь его срез за срезом. Порядок не случаен. Сначала — сделать сквозным, потом — расширить аудиторию/данные, потом — закалить инварианты, потом — богатство. Реальная последовательность чек-инов:

#Срез (одно предложение)Что добавил
1Клиент сохраняет вес и видит егоwalking skeleton — сквозная нитка
2Тренер видит чек-ины клиентарасширил аудиторию (+ граница доступа)
3aПовторная отправка не создаёт дубльзакалил инвариант (idempotent)
3bКлиент прикладывает фотобогатство данных
4Тренер задаёт день чек-инабогатство + LWW
3cЧек-ин уходит из офлайнанадёжность — почти даром благодаря 3a
5Тренеру приходит пуш о чек-инеуведомления

Заметь 3a раньше 3c. Это не случайность — это компаундинг из урока 5: idempotent-инвариант, вложенный рано, сделал офлайн-срез почти бесплатным. Порядок срезов — это рычаг. Правильные свойства вперёд удешевляют то, что идёт следом.

Как ставить срез агенту — анатомия

Один срез = одно ТЗ с четырьмя частями. Ровно так ты ставил мне цели БЖУ:

Контекст     — где в продукте, зачем пользователю
Поведение    — Given/When/Then (один-два сценария)
Не входит    — явный список «пока НЕ делаем»
Критерии     — как проверим приёмку вживую

Секция «Не входит» — самая недооценённая. Она и есть граница среза. Без неё агент «на всякий случай» дорисует пуши, редактирование тренером, экспорт — и твой тонкий срез распухнет в горизонтальный слой.

И обратная ошибка — перерезать, сделать инфраструктуру, которая срезу не нужна:

Соблазн перерезать. Для целей БЖУ агент мог завести целую таблицу профиля. Но профиль setlog живёт в user_metadata — на walking skeleton хватило 0 миграций. Отдельная таблица «на будущее» = работа, которую срез не заказывал.
Тонко ≠ халтурно. Ты сам это назвал: «делаем walking skeleton, таблица тут избыточна». Правильный срез берёт самый дешёвый носитель, который закрывает сценарий — не самый «архитектурно полный».
Но замеряй компаунд. Ты же и предсказал: дневной учёт потребует настоящую таблицу — и на следующем срезе прогноз сбылся (nutrition_log). Дешёвый носитель для скелета + честное «здесь потом будет таблица» — это не противоречие, это две разные толщины.

Проверь себя

1. Агент предлагает план: «Неделя 1 — вся схема БД. Неделя 2 — все API. Неделя 3 — весь UI». Что не так?

Классическая горизонтальная нарезка. До конца недели 3 нет ни одного сценария, который можно запустить и принять. Проси вертикальный срез: «одна тонкая нитка сквозь все три слоя к концу недели 1».

2. Какой из кусков — настоящий walking skeleton для новой фичи «заметки к тренировке»?

Скелет обязан ХОДИТЬ — один целый сценарий сквозь все слои. Первый и четвёртый — куски слоёв (не работают сами). Второй — не тонко, это месяц. Только третий: тонкая сквозная нитка, которую можно запустить и принять.

3. Зачем секцию «Не входит» писать явно в ТЗ среза?

«Не входит» — это и есть граница среза. Без неё агент «на всякий случай» добавит пуши/экспорт/права, и вертикальный срез размажется в горизонтальный. Явная граница держит коридор узким.

4. Почему idempotent-срез (3a) поставили РАНЬШЕ офлайн-среза (3c), а не наоборот?

Компаундинг из урока 5. Офлайн-очередь повторяет отправку — обычно нужен дедуп. Но unique+upsert из 3a сделал повтор безопасным by construction. Правильное свойство вперёд удешевляет поздний срез. Секвенирование — это стратегия, а не порядок «как удобнее».

Упражнение — нарежь фичу сам

Возьми фичу, которую мы ещё не делали: «личный рекорд (PR) по упражнению» — пользователь видит свой максимум по каждому упражнению, а тренер видит рекорды клиента. Не пиши ТЗ целиком. Сделай только нарезку:

  1. Скелет. Сформулируй walking skeleton одним предложением в настоящем времени. Проверь себя: он ходит? (есть рабочий сценарий сквозь слои?)
  2. Срезы. Выпиши 3–4 следующих среза, тоже по одному предложению. Каждый — целый сценарий, не кусок слоя.
  3. Порядок. Объясни, почему именно такой порядок — что из раннего среза удешевит поздний.

Бонус — поймай плохую нарезку. Ниже план от агента. Найди, что здесь нарезано неправильно, до того как раскроешь.

План агента (фрагмент)

— Срез 1: создать таблицу personal_records со всеми полями и RLS.
— Срез 2: написать все API-роуты (свои рекорды + рекорды клиента для тренера).
— Срез 3: сделать весь UI — карточка PR, экран тренера, графики.

Показать разбор
Разбор

Это горизонтальные слои, переодетые в «срезы»: слой данных, слой API, слой UI. Ни один нельзя запустить и принять сам по себе — рабочий продукт появится только после Среза 3. Ни один из них не проходит тест «продемонстрируй одним предложением в настоящем времени»: «создана таблица» и «написаны роуты» — это не сценарии.

Как надо: Срез 1 (скелет) — «пользователь видит свой PR по одному упражнению» (таблица + роут + карточка, узко). Срез 2 — «тренер видит PR клиента» (+ граница доступа). Срез 3 — «PR обновляется автоматически после тренировки». Срез 4 — «графики динамики PR». Каждый ходит, каждый деплоится, каждый принимается вживую.

Что уносишь

Точная постановка — это не только «как сформулировать одну задачу», но и «как порезать фичу на задачи». Режь вертикально: тонкая нитка сквозь все слои, которая работает. Начинай с walking skeleton: скелет должен ходить, а не просто стоять каркасом. Секвенируй как стратег: правильные инварианты вперёд удешевляют поздние срезы. И держи границу секцией «Не входит» — без неё тонкий срез распухнет в слой.

Источники: J.B. Rainsberger — vertical slicing · Cockburn — Walking Skeleton · Bogard — Vertical Slice · живой кейс: чек-ины setlog