Большая задача — это задача, которую нельзя честно оценить, нельзя распараллелить и нельзя сдать по частям. Декомпозиция чинит всё три: мелкий кусок оценивается точнее, куски берут разные люди, а первая ценность доходит до пользователя раньше. Главный приём — вертикальная нарезка: каждый кусок — тонкий, но сквозной срез через все слои (интерфейс, логика, данные), который сам по себе приносит пользу. Антипаттерн — горизонтальная нарезка по слоям («сначала вся база, потом весь бэкенд, потом весь фронт»): по отдельности куски бесполезны, ценность приходит только в самом конце. Хороший кусок проверяют по INVEST: независимый, обсуждаемый, ценный, оцениваемый, маленький, тестируемый.
Мне однажды прилетела задача «личный кабинет» одним тикетом. Оценили в полтора месяца. Через полтора месяца было готово «почти всё», но показать пользователю было нечего: профиль ждал историю заказов, история ждала фильтры, фильтры ждали бэкенд, который делали «заодно со всем». Ценность не доходила, пока не доехало всё. Развалилось ровно потому, что задачу не разрезали — её просто взяли целиком и понадеялись.
Декомпозиция — это не «нарезать помельче, чтобы было много тикетов». Это умение отрезать кусок так, чтобы он сам по себе что-то значил. Этому навыку учатся дольше, чем написанию требований, и именно он отличает аналитика, который двигает поставку, от того, кто плодит карточки.
Зачем вообще дробить
Большой монолитный кусок работы плох сразу по нескольким причинам, и каждая стоит денег и нервов.
- Оценка. «Личный кабинет» оценить невозможно — слишком много неизвестного внутри. А «вывести имя и email на странице профиля» оценивается в часах и почти не врёт. Чем мельче кусок, тем точнее оценка.
- Параллельность. Один большой кусок берёт один человек, и команда упирается в него. Пять кусков берут несколько человек одновременно — работа идёт параллельно.
- Ранняя ценность. Маленький сквозной кусок можно выкатить и показать пользователю уже на этой неделе, не дожидаясь, пока будет готово всё. Обратная связь приходит раньше, и если идея плоха — вы узнаёте это до того, как вложили полтора месяца.
- Меньше риск. Если что-то пойдёт не так, вы потеряете один маленький кусок, а не полтора месяца работы. Ошибка в мелком обходится дёшево.
Сведём в одну мысль: дробление превращает «всё или ничего через полтора месяца» в «понемногу и предсказуемо каждую неделю».
Вертикальная и горизонтальная нарезка
Это главная развилка декомпозиции, и большинство ошибок именно здесь. Любую фичу можно разрезать двумя способами, и они дают противоположный результат.
Горизонтальная нарезка режет по техническим слоям. Сначала «сделать всю базу данных», потом «весь бэкенд», потом «весь фронтенд». Звучит логично для разработчика — каждый делает свой слой. Но для поставки ценности это антипаттерн: ни один кусок по отдельности не работает. Готовая база без интерфейса не показывает пользователю ничего. Ценность появляется только когда сойдутся все слои — то есть в самом конце, как в моей истории с личным кабинетом.
Вертикальная нарезка режет поперёк слоёв. Каждый кусок — тонкий, но сквозной срез: немного интерфейса, немного логики, немного данных — ровно столько, чтобы заработал один маленький сценарий целиком. Кусок узкий, но доходит до пользователя и приносит пользу сам по себе.
flowchart TB
subgraph H["Горизонтально (антипаттерн)"]
direction TB
H1["Вся база данных"] --> H2["Весь бэкенд"] --> H3["Весь фронтенд"]
H3 --> HV["ценность только в конце"]
end
subgraph V["Вертикально (как надо)"]
direction LR
V1["Кусок 1: UI+логика+данные"] --> VV1["польза сразу"]
V2["Кусок 2: UI+логика+данные"] --> VV2["польза сразу"]
V3["Кусок 3: UI+логика+данные"] --> VV3["польза сразу"]
end
Схема выше противопоставляет два подхода. Сверху горизонтальный: три слоя идут друг за другом — сначала база, потом бэкенд, потом фронт, — и пользователь не получает ничего, пока не готов последний слой, ценность капает одним разом в самом конце. Снизу вертикальный: три независимых куска, и каждый — это тонкий срез сразу через все слои (немного интерфейса, немного логики, немного данных), поэтому каждый кусок приносит пользу сразу после готовности. Главное отличие: горизонтальные куски бесполезны поодиночке, вертикальные — каждый ценен сам по себе. Поэтому режьте поперёк слоёв, а не вдоль.
Признак, что вы режете горизонтально
Если в названиях ваших кусков есть слова «база», «бэкенд», «фронтенд», «API», «интеграция» — почти наверняка вы режете по слоям. Имя хорошего вертикального куска описывает пользовательский результат: «пользователь видит имя и email в профиле», а не «эндпоинт GET /profile». Кусок должен называться тем, что станет правдой для пользователя, когда кусок готов.
Каким должен быть хороший кусок: INVEST
Чтобы не спорить «достаточно ли мелко» на ощущениях, есть чек-лист — аббревиатура INVEST. Шесть свойств хорошего куска (обычно — user story; что это такое, разбирается в записи про user story и use case).
| Буква | Свойство | Что значит на практике |
|---|---|---|
| I | Independent (независимый) | Кусок можно сделать и выкатить отдельно, не дожидаясь трёх других |
| N | Negotiable (обсуждаемый) | Это не жёсткий контракт, а повод договориться о деталях с командой |
| V | Valuable (ценный) | Приносит пользу пользователю или бизнесу сам по себе |
| E | Estimable (оцениваемый) | Команда понимает, что внутри, и может прикинуть срок |
| S | Small (маленький) | Влезает в один спринт, лучше — в несколько дней |
| T | Testable (тестируемый) | Есть критерии приёмки, по которым видно, что кусок готов |
Не нужно молиться на каждую букву. INVEST — это лупа, через которую смотришь на кусок и видишь, что с ним не так. Не можете оценить (E)? — внутри слишком много неизвестного, копайте. Не ценен сам по себе (V)? — вы, скорее всего, отрезали горизонтальный слой. Не тестируемый (T)? — нет критериев приёмки, кусок не готов идти в работу.
Приёмы: как именно резать
«Режь вертикально» — хороший принцип, но руки всё равно спрашивают «а по какой линии?». Вот рабочие приёмы — обычно достаточно приложить один-два к фиче, чтобы куски сами проявились.
- По сценариям и шагам. Фича «оформление заказа» = выбор товара → адрес доставки → оплата → подтверждение. Каждый шаг — отдельный кусок.
- По данным. Сначала вывести в профиле только имя и email, потом — телефон, потом — историю заказов. Каждое поле или группа полей — кусок.
- По правилам. Сначала оформление без скидок, потом отдельным куском — скидки, потом — промокоды. Каждое бизнес-правило накручивается поверх работающего минимума.
- Happy path сначала. Первый кусок — только успешный сценарий (карта валидна, всё хорошо). Обработка ошибок, повторов, граничных случаев — следующими кусками. Так вы быстро получаете работающий скелет, а потом наращиваете надёжность.
Happy path — самый недооценённый приём
Соблазн — сразу описать все ветки и ошибки в одном куске. Но «оформить заказ, когда всё хорошо» и «обработать десять способов, которыми оплата может упасть» — это очень разный объём работы и риска. Отрежьте happy path первым: он маленький, ценный (демо уже можно показать) и тестируемый. Ветки ошибок добавляйте отдельными кусками — каждый со своими критериями приёмки.
Пример: режем «фильтр каталога»
Прилетела задача: «сделать фильтрацию товаров в каталоге». Звучит как один тикет. Разрежем вертикально.
Сначала горизонтальный соблазн, которого мы не делаем: «сделать API фильтров», «сделать панель фильтров на фронте», «сделать индексы в базе». Каждый кусок бесполезен поодиночке — показать пользователю нечего, пока не сойдётся всё.
Теперь по правилу — каждый кусок сквозной и ценный сам по себе:
Кусок 1 (happy path, по данным):
фильтр по одной категории — выпадающий список + запрос + выдача.
Пользователь уже может сузить каталог. Можно выкатывать.
Кусок 2 (по данным):
добавить фильтр по цене (от/до) поверх работающего куска 1.
Кусок 3 (по правилам):
показывать рядом счётчик «найдено N товаров».
Кусок 4 (ветка):
пустая выдача — экран «ничего не найдено, сбросить фильтры».
После куска 1 у пользователя уже есть работающая фильтрация по категории — узкая, но настоящая, её можно выкатить и собрать обратную связь. Каждый следующий кусок накручивает ценность поверх работающего, а не достраивает половину системы в надежде, что в конце всё сойдётся. Если после куска 2 приоритеты сменятся — вы остановитесь с работающей фичей, а не с грудой недоделанных слоёв. И заметьте: критерии приёмки к каждому куску пишутся отдельно — это часть того, чтобы кусок вообще был готов идти в работу, про что подробнее в записи как написать ТЗ.
Откуда это взялось
Критерии INVEST сформулировал Билл Уэйк в 2003 году — он же придумал саму аббревиатуру как удобную проверку качества user story в Extreme Programming. Сама практика «нарезки историй» (story splitting) выросла в agile-сообществе в 2000-х вместе с короткими итерациями: раз спринт всего две недели, большую фичу физически нельзя взять целиком — приходится резать. Идея вертикального среза («walking skeleton», тонкий работающий скелет через все слои) старше и шире agile, но именно итеративная разработка сделала её повседневным навыком аналитика, а не теорией.
Частые вопросы
Как декомпозировать большую задачу?
Режьте её вертикально — тонкими сквозными срезами через все слои (интерфейс, логика, данные), где каждый кусок приносит пользу сам по себе и его можно выкатить отдельно. Не режьте горизонтально по слоям («вся база», «весь бэкенд») — такие куски бесполезны поодиночке. Рабочие приёмы: резать по шагам сценария, по данным (поле за полем), по бизнес-правилам и отрезать happy path первым. Каждый кусок проверяйте по INVEST: независимый, ценный, оцениваемый, маленький, тестируемый.
Что такое INVEST?
INVEST — это чек-лист из шести свойств хорошего куска работы (обычно user story): Independent (независимый, делается отдельно), Negotiable (обсуждаемый, не жёсткий контракт), Valuable (ценный сам по себе), Estimable (оцениваемый), Small (маленький, влезает в спринт), Testable (тестируемый, есть критерии приёмки). Это не закон, а лупа: если кусок не проходит по какой-то букве, она подсказывает, что с ним не так.
Чем вертикальная нарезка отличается от горизонтальной?
Горизонтальная режет задачу по техническим слоям: сначала вся база, потом весь бэкенд, потом весь фронт — и ценность доходит до пользователя только в самом конце, когда слои сойдутся. Вертикальная режет поперёк слоёв: каждый кусок — тонкий сквозной срез сразу через интерфейс, логику и данные, который работает и приносит пользу сам по себе. Для поставки ценности горизонтальная нарезка — антипаттерн, режьте вертикально.