JavaRush /Курси /Claude code /План реалізації: ризики та перевірки

План реалізації: ризики та перевірки

Claude code
Рівень 17 , Лекція 3
Відкрита

1. Карта — ще не маршрут

Після дослідження кодової бази легко зловити оманливе відчуття, що задача вже майже вирішена: лишилося набрати кілька рядків і прийняти оплески. На практиці саме в цей момент найчастіше починається локальний хаос: ви зрозуміли, де змінювати, але не що саме і не в якому порядку.

Investigation Note відповідає на запитання «Де живе проблема?». Але це ще не план — це карта місцевості, а не маршрут. Карта показує міст і річку, але не каже, їхати через міст чи об’їжджати, тому що він у ремонті. З кодом так само: баг пов’язаний із OrderController, OrderService, GlobalExceptionHandler і тестами checkout — але де ставити захист, як повернути 400 і чим довести, що валідний checkout не зламано, ще незрозуміло.

Зручно тримати в голові дуже простий ланцюжок:

Issue Intake Note → Investigation Note → Approved plan → лише потім зміни

Якщо перескочити через затверджений план, Claude перетворюється на дуже старанного помічника, який відремонтує півквартири, поки ви просили підтягнути дверну ручку. Він не злий, він допомагає занадто широко. Ваше завдання — дати йому не лише напрям, а й межі.

2. Слово approved вирішує все

Тепер давайте заземлимо термін. Implementation Plan — не документ «для порядку» і не любов до таблиць, а узгоджений людиною чернетковий варіант майбутньої реалізації. Живе поруч із Issue Intake Note або окремим блоком у TASK_SPEC.md. Сенс один: до старту кодових змін ви фіксуєте маршрут і перевіряєте, що він адекватний.

Слово approved тут особливо важливе. Чернетку Claude збере хорошу, але затверджує людина: вона приймає ризик, погоджується на межі й відповідає, що план вирішує потрібну проблему, а не просто виглядає переконливо. А «виглядає переконливо» — небезпечна категорія.

Ось що саме ви затверджуєте, коли дивитеся на план:

Що в плані На яке запитання ви відповідаєте
Мета Ми справді лікуємо потрібну проблему, а не сусідній симптом?
Scope Зміни залишаються в розумних межах?
Non-goals Зрозуміло, чого ми не робимо «заодно»?
Ризики Ми розуміємо, що можемо зламати?
Перевірки У нас є реальний спосіб довести результат?
Stop conditions Зрозуміло, коли треба зупинитися, а не «дотискати»?

Чернетку плану зручно замовляти у Claude у дуже прямій формі — без магії, без «зроби красиво», без надії, що він сам здогадається, який формат вам потрібен.

Підготуй чернетку плану за задачею про empty cart у checkout.
Не змінюй код.
Поверни: goal, scope, non-goals, affected files, steps, risks,
verification strategy, stop conditions.
Якщо доказів бракує, познач unknown, а не вгадуй.

Бачите, тут немає жодного романтичного слова. І це добре: плани не зобов’язані надихати — вони зобов’язані економити вам помилки.

3. Кожна секція — на своє запитання

Коли ви вперше бачите хороший Implementation Plan, виникає дивне відчуття: він одночасно дуже простий і дуже дисциплінуючий. Зайвої філософії в ньому немає, зате кожна секція відповідає на окреме практичне запитання. А якщо якоїсь секції немає — це майже завжди не дрібниця, а дірка, через яку пізніше вилізе scope creep або неперевірений ризик.

Для нашого Commerce OS давайте візьмемо реалістичний тикет: при POST /api/orders з порожнім списком товарів backend повертає 500, а має 400 з зрозумілою validation error. Нижче — не величезний документ, а зручна карта секцій, які в плані мають бути.

Секція Що означає по-людськи Приклад для Commerce OS
Goal
Що саме має стати краще Порожня корзина більше не валить checkout у 500, а API повертає зрозумілу validation error
Scope
Де працюємо Валідація empty cart у checkout, пов’язаний error mapping і релевантні тести
Non-goals
Що не робимо заодно Не редизайнимо корзину, не змінюємо UX непорожнього checkout, не чіпаємо unrelated pricing logic
Affected files
Які файли найімовірніше зачепимо OrderService, GlobalExceptionHandler, OrderControllerWebTest і, за потреби, точка входу в OrderController
Ordered steps
У якому порядку рухаємося Спочатку зафіксувати empty cart test, потім закрити доменну перевірку, потім привести HTTP-відповідь до узгодженого формату
Risks
Що може піти не так Можна випадково змінити валідний checkout або зламати загальний формат помилок
Verification strategy
Як доведемо результат Автотести + відтворюваний запит POST /api/orders з порожнім items[]
Stop conditions
У яких випадках не продовжуємо Якщо потрібна загальна переробка error schema, якщо змінюється shared pricing behavior, якщо diff лізе в сусідні checkout-модулі
Rollback note
Як відкочуємося, якщо все пішло не так Зміна має вміщуватися в один логічний відкат без схемних правок

Корисно побачити план і у вигляді маленького фрагмента. Зверніть увагу: він не довгий, не бюрократичний і не намагається пояснити історію Всесвіту.

## Мета
Не давати POST /api/orders з порожнім items[] падати в 500;
повернути зрозумілу validation error.

## Область змін
Перевірка empty cart у checkout, error mapping і пов’язані тести.

## Не-цілі
Не змінюємо UI корзини, happy-path checkout і unrelated pricing code.

## Затронутые файлы
OrderService, GlobalExceptionHandler, OrderControllerWebTest
і за потреби точка входу в OrderController.

Важливо ще одне правило: не копіюйте в план весь Issue Intake Note і весь Investigation Note. План — робочий документ для реалізації, а не архів знайденого. Якщо 90% тексту повторюють уже знайдені факти, перед вами не маршрут, а переказ попередніх кроків самому собі.

4. Task risk list: ризики краще назвати до коду

Список ризиків здається нудним рівно до першого разу, коли ви його не написали, — тоді ризики перестають бути рядками в документі й перетворюються на сюрпризи у гілці, тестах і чаті команди. Тому хороший task risk list — не драматизація задачі, а нормальна інженерна чесність: зміна зачіпає не лише той шматок, який ви лагодите.

Для початківця корисно мислити про ризики не як про щось страшне, а як про сусідні поверхні, які зачіпає задача. Навколо empty-cart кейса в Commerce OS зазвичай спливають п’ять типів ризиків.

Ризик Severity Чому це важливо Що робимо
Зміниться поведінка валідного checkout Medium Можна випадково зачепити happy-path з непорожніми items[] Обмежуємо нову перевірку сценарієм empty cart і окремо перевіряємо happy-path
Зламається очікування фронтенду щодо формату помилки Medium UI може бути прив’язаний до поточної shape response Не змінюємо контракт помилки ширше, ніж потрібно, без окремого узгодження
calculateTotal()
використовується ще десь
Medium Нова доменна захисна перевірка може зачепити інший сценарій Перевіряємо всі використання до правки й мовчки не змінюємо загальну семантику методу
Потрібна загальна переробка error mapping High Це вже більше ніж одна локальна bugfix-задача Ставимо stop condition і не продовжуємо «заодно»
Diff полізе в unrelated checkout/pricing файли Low/Medium Задача втрачає читабельність і форму, зручну для відкату Звужуємо scope і переглядаємо steps

Зверніть увагу на дві речі. По-перше, ризик без реакції майже марний. Якщо ви написали «може зламатися формат помилки», але не додали, як це помітити і що робити, це просто тривожна думка в гарній обгортці. По-друге, список ризиків не має бути нескінченним. Для звичайної задачі вам зазвичай вистачає трьох-шести реальних ризиків. Якщо їх двадцять, або задача занадто широка, або ви записуєте все підряд, включно з поганим настроєм checkout-flow по четвергах.

У практичній роботі добре працює просте правило: якщо ризик настільки серйозний, що при його настанні ви зобов’язані зупинитися, він має потрапити не лише до risk list, а й до stop conditions. Це вже не «на замітку», а жорстка межа.

5. Verification strategy: як довести результат

Ось тут план перестає бути просто «списком кроків» і стає інженерним документом. Бо будь-яку задачу можна красиво описати, але без verification strategy у вас лишається лише надія. А надія, як відомо, прекрасне людське почуття і дуже слабкий технічний інструмент.

У цьому курсі ви вже бачили базовий план перевірки. Тут ми використовуємо ту саму ідею, тільки застосовуємо її до конкретної великої задачі. Не лякайтеся слова strategy: мова не про багатосторінкову QA-методологію. На цьому рівні це дуже приземлена відповідь на запитання: що саме ми запускаємо, перевіряємо і вважаємо достатнім доказом.

Для нашого прикладу з empty cart секція може виглядати так:

## Стратегія перевірки
1. Запустити targeted web/API test на POST /api/orders з порожнім items[].
2. Додати сценарій: empty cart повертає 400, а не 500.
3. Перевірити ручним запитом, що response body лишається в узгодженому validation format.
4. Переконатися, що валідний checkout з непорожнім items[] поводиться як раніше.
5. Якщо з’ясується, що потрібен загальний redesign error schema, зупинитися.

Зверніть увагу: хороша verification strategy завжди конкретна. Фраза «поганяти тести» — погана. Вона не каже, які саме тести, на якому рівні й що вважатиметься успіхом. А от формулювання «додати сценарій, де empty cart повертає 400, а не 500» уже підходить: воно вимірюване, зрозуміле й прив’язане до задачі.

Дуже важливо не переплутати verification strategy з повним дизайном тестів. Тут ми ще не проєктуємо всю test strategy і не обговорюємо весь локальний harness. Ми просто фіксуємо нижній контракт перевірки для цієї задачі. Іншими словами: що ви маєте побачити, щоб чесно сказати «так, ця зміна працює і не рознесла сусідню поведінку».

Для початківця корисно запам’ятати ще один нюанс. Ручна перевірка тут не заборонена. Якщо ви не можете покрити все автоматикою негайно, ручний крок допустимий — але він має бути вузьким і відтворюваним. «Потикати руками, наче ок» — погана перевірка. «Надіслати POST /api/orders з порожнім items[] і переконатися, що приходить узгоджена validation error» — нормальна. Різниця маленька за словами і величезна за користю.

Якщо задача підходить для роботи за метою — цей режим ми вводили на рівні 6, а на TDD розбираємо далі в курсі, — то verification strategy має явно містити машинно-перевірювану умову фінішу: список команд і очікуваних результатів, за якими автоматичний цикл розуміє, що задача завершена. Тоді план перестає бути «списком кроків для людини» і стає специфікацією для циклу «за метою» — через slash-команду на кшталт /goal або скриптований цикл claude -p (точна назва й доступність можуть змінюватися від версії до версії). Якщо хоча б один пункт готовності суб’єктивний, умова фінішу розділяється на машинну частину для автоматичного циклу й людську — для схвалення.

6. Stop conditions і rollback notes

Ця частина багатьом здається надмірною, доки вони не спробують один раз «дотиснути» задачу без стоп-границь. Тоді з’ясовується, що stop conditions — це зовсім не песимізм, а спосіб не зіпсувати хороший план у той момент, коли реальність перестає збігатися з очікуваннями. Простіше кажучи, це заздалегідь написаний дозвіл самому собі не героїчно імпровізувати.

Хороший stop condition — це не «якщо стане складно, засмутитися». Це дуже конкретний сигнал: задача вийшла за поточні межі й потребує нової домовленості. Для empty-cart кейса такими стоп-сигналами можуть бути ось такі речі:

Якщо сталося це Що це означає Правильна дія
Потрібно змінювати загальний формат помилок для checkout або кількох контролерів Задача стала ширшою, ніж початковий scope Зупинитися й винести це в окреме рішення
З’ясовується, що empty cart допустимий в іншому flow, наприклад у draft-order сценарії Доменне правило неоднозначне Не продовжувати без узгодження поведінки
Зміни полізли в shared pricing logic або unrelated checkout-модулі План був занадто оптимістичним або хибним Переглянути scope і affected files
Тести падають за межами empty-cart сценарію Зміна зачепила сусідню поведінку Не «лагодити по ланцюжку», а повернутися до plan

Rollback note при цьому потрібен не для драматичного postmortem, а для звичайної інженерної гігієни: ви заздалегідь відповідаєте, як повертаємося назад, якщо рішення виявиться поганим. У невеликих задачах відповідь часто скромна, і це нормально.

## Нотатка про відкат
Зміна має вміщуватися в один логічний відкат.
Схемних і data-міграцій у межах задачі не допускається.
Якщо нова обробка empty cart поводиться неправильно,
ми відкочуємо локальний fix цілком і повертаємося
до останньої стабільної поведінки гілки без каскадних змін.

Чим нудніший rollback note, тим краще. Серйозно. Якщо для відкату потрібна окрема балада про доблесть і жертви, значить, задача від самого початку була занадто широкою.

7. Три артефакти — три запитання

Коли документів навколо однієї задачі стає більше ніж один, починаються перші плутанини. Це нормально. Особливо якщо назви здаються схожими і всюди є «goal», «risks» і «files». Тому тут корисно один раз дуже чітко розкласти ролі артефактів. Після цього працювати стає помітно легше.

Кожен документ відповідає на своє запитання. І якщо ви змушуєте один артефакт відповідати за все одразу, він перетворюється на кашу з красивим заголовком.

Артефакт На яке запитання відповідає Що в ньому головне
Issue Intake Note Що це взагалі за задача? Проблема, вплив, вимоги, assumptions, open questions
Investigation Note Де ця задача живе в коді? Файли, функції, тести, точки зміни, evidence
Implementation Plan Що саме робимо і в якому порядку? Scope, non-goals, affected files, ordered steps, risks
Verification strategy Чим доведемо, що рішення спрацювало? Команди, тести, ручні перевірки, критерії зупинки

Дуже спокусливо робити так: спочатку написати хороший intake, потім хороший investigation, а потім у план просто вставити все це копіпастою й додати заголовок Plan. Не робіть так. Інакше людині, яка читатиме документ перед реалізацією, доведеться заново викопувати з довгого тексту те, що їй потрібно просто зараз. План має бути коротшим, сухішим і практичнішим. Він не пояснює всю історію задачі — він допомагає безпечно пройти її наступну фазу.

Хороший критерій простий: якщо відкрити тільки план, за ним має бути ясно, що змінювати, де змінювати, що не чіпати, чим перевіряти і коли зупинятися. Якщо для цього потрібно гортати три сторінки історичного контексту, значить, план недотиснутий.

8. Скрізний приклад Commerce OS: approved plan

Давайте зберемо все разом в одному компактному прикладі, щоб у вас лишився не абстрактний набір термінів, а цілком відчутний образ готового документа. Візьмемо наш Commerce OS і задачу про порожню корзину в checkout. Intake уже зроблено, investigation уже знайшло потрібні сервіси, тести й unknowns. Тепер із цього народжується затверджений людиною план.

Спочатку корисно попросити Claude зібрати чернетку, а не фінальне рішення:

На основі intake та investigation підготуй чернетку плану.
Не змінюй код.
Потрібно повернути лише:
goal, scope, non-goals, affected files, ordered steps,
task risk list, verification strategy, stop conditions.
Не вигадуй того, чого немає в evidence.

Після цього ви правите чернетку очима інженера, а не людини, якій уже дуже хочеться натиснути Enter і побачити diff. У результаті план може набути приблизно такого вигляду:

## Мета
Не давати POST /api/orders з порожнім items[] падати в 500;
повернути узгоджену validation error на HTTP-рівні.

## Область змін
Валідація empty cart у checkout, error mapping і пов’язані API tests.

## Не-цілі
Не змінюємо UI корзини, happy-path checkout і unrelated pricing logic.

## Затронутые файлы
OrderService.java, OrderController.java,
GlobalExceptionHandler.java, OrderControllerWebTest.java.

## Упорядковані кроки
1. Додати reproducing check для POST /api/orders з порожнім items[].
2. Закрити empty-cart validation поруч із calculateTotal(), не змінюючи unrelated pricing behavior.
3. Повторно використати поточний error mapping або мінімально розширити його,
   щоб повернути 400 замість 500.
4. Прогнати targeted tests і відтворюваний запит;
   підтвердити, що валідний checkout unchanged.

Потім до нього додаються список ризиків і стратегія перевірки — і ось тут план стає по-справжньому approved, а не просто «звучить розумно».

## Список ризиків задачі
- medium: можна зачепити shared callers calculateTotal()
- medium: фронтенд може залежати від поточного error format
- high: якщо для фікса потрібен загальний redesign error schema,
  задача виходить за scope

## Стратегія перевірки
- targeted web/API test на empty cart
- ручний POST /api/orders з порожнім items[]
- підтвердження, що валідний checkout з непорожніми товарами
  не змінив поведінку

## Умови зупинки
- потрібен загальний redesign error schema
- неясні shared callers calculateTotal()
- diff іде в unrelated checkout/pricing модулі

Якщо хочете додати ще один запобіжник, можна прогнати цей план через reviewer-agent із вашого Workflow Kit — не для того, щоб він «дозволив» зміни, а щоб він знайшов діри в доказовій базі або занадто широкі кроки.

Перевір чернетку плану як reviewer.
Дивись лише на повноту і межі:
чи немає зайвого scope, чи не пропущено ризики,
чи прив’язані кроки до verification.
Код не змінюй.

У цей момент впевнене «здається, ми зрозуміли задачу» перетворюється на спокійне «ми знаємо, що саме робимо, чим ризикуємо і як зрозуміємо, що зробили правильно». Це документ, який можна показати іншому інженеру, обговорити, поправити, розрізати на reviewable slices і лише потім віддавати в реалізацію.

Окремий випадок — коли план приходить із хмарного планувальника, який ми згадували в попередній темі цього рівня (умовно /ultraplan). Формат результату зазвичай одразу містить усі три артефакти — план реалізації, список ризиків, стратегію перевірки — і часто нотатки самоперевірки. Читати й затверджувати такий план потрібно за тією ж схемою, що й план, зібраний локально: перевірити межі задачі, non-goals, затронуті файли, послідовність кроків, ризики й команди для перевірки. Хмарний планувальник не замінює ваше схвалення — він прискорює чорнове опрацювання й розширює контекст дослідження.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ