JavaRush /Курси /Claude code /Декомпозиція задачі на PR...

Декомпозиція задачі на PR slices

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

1. Декомпозиція плану як окремий крок

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

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

Корисно тримати в голові просту різницю:

Рівень На яке запитання відповідає
Implementation Plan Що саме ми робимо і в якому загальному порядку
PR slice Яку мінімальну порцію зміни можна незалежно перевірити й відрев’ювати

Тут PR slice — це логічна одиниця планування та контролю. Він може пізніше лягти в окремий commit, у частину одного PR або в самостійний PR — зараз нам важлива не упаковка, а те, що шматок роботи можна окремо зрозуміти, перевірити й за потреби зупинити.

Якщо в плані у вас написано «оновити сервіс і контролер», це може бути нормальною формулюванням на рівні задачі. Але для реальної роботи такий крок надто широкий. Він уже проситься в розбиття. Інакше ви отримаєте класичне: «я тут трохи дописав у сервісі, трошки підправив HTTP-шар, заодно вирівняв обробку помилок, ну і пару тестів зачепив». Слово «трохи» в таких історіях зазвичай означає «пристебніть ремені».

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

2. Ознаки хорошого PR slice

Хороший PR slice — це не просто «маленький крок». Маленьким можна зробити й хаос. Хороший slice — це така одиниця зміни, у якої є один чіткий намір, зрозуміла зона файлів, своя перевірка та окремий сенс для рев’ю. Якщо інший інженер відкриває такий slice й за хвилину розуміє, навіщо він потрібен, — ви на вірному шляху.

Порівняння зазвичай виглядає так:

Ознака Слабкий крок Хороший PR slice
Намір «Полагодити checkout» «Додати захист від empty cart у доменній логіці»
Область файлів Сервіс, контролер, тести, документація й ще кілька випадкових файлів Вузький набір файлів навколо однієї зміни
Перевірка «Потім прогоню все» Одна зрозуміла targeted check
Відкочування Під час відкотування зачіпає сусідні зміни Відкочується окремо
Рев’ю Потрібно заново зрозуміти половину модуля Видно одну ідею та її межі

Зверніть увагу на важливу річ: slice не зобов’язаний бути «шматочком коду». Це може бути окремий крок перевірки, крок контракту або крок документації. Дуже часто перший хороший slice — це не fix, а фіксація поведінки: невеликий regression check, відтворюваний запит, короткий smoke script. Його задача не «виправити», а заземлити проблему так, щоб потім ніхто не сперечався, чи був баг, чи вам просто «щось не так здалося».

З цього ж випливає важливе правило: один slice — один намір. Якщо в одному кроці у вас одночасно живуть feature, refactor і оновлення залежності, це вже не slice, а валіза, яку ви намагалися закрити ногою. Так, технічно можна. Ні, рев’юеру від цього краще не стане.

Ще один хороший тест на зрілість slice: чи можете ви описати його однією фразою без сполучника «і ще»? Якщо без «і ще» не виходить, найімовірніше, перед вами вже дві порції роботи, а не одна.

3. Прив’язка slice до критеріїв приймання та перевірки

На цьому етапі дуже корисно перестати думати про slices як просто про «список кроків». Насправді це міст між Implementation Plan і критеріями приймання. Кожен slice має або напряму рухати один acceptance criterion, або знімати один конкретний ризик. Якщо зв’язок не видно, крок поки що сирий.

Візьмімо наш Commerce OS і issue з порожньою корзиною в checkout. Припустімо, у вас уже зафіксовано приблизно такі критерії: запит із порожнім items[] більше не дає 500, API повертає 400 із зрозумілою validation error, а коректне замовлення продовжує працювати як раніше. Тепер задача декомпозиції — не просто «розбити на чотири пункти», а показати, який крок за який критерій відповідає.

Це зручно бачити в таблиці:

Acceptance criterion Який slice його рухає Чим перевіряється
Порожня корзина більше не падає в 500 Slice з фіксацією бага + slice з доменною перевіркою targeted check / regression check
API відповідає 400 і зрозумілою validation error Slice з HTTP mapping ручний запит або контрактна перевірка
Валідний checkout не зламаний Перевірка на кожному вузькому кроці існуючі релевантні перевірки

Тут важливо не скотитися в передчасний курс із тестування. Зараз ми не проєктуємо повну test strategy. Ми лише вимагаємо, щоб у кожного slice був власний спосіб довести, що він не зник у тумані. Якщо slice не можна перевірити хоча б однією осмисленою дією, він ще не готовий до роботи.

Окремо варто пам’ятати про stop conditions. Вони потрібні не тільки для всього плану, а й на рівні slice. Наприклад, ви робите slice з HTTP-mapping і раптом розумієте, що заради нього треба змінювати загальну схему error response для кількох модулів. Це вже не «маленький останній штрих». Це сигнал зупинитися і повернутися до плану. І це добра новина, а не погана: декомпозиція якраз і потрібна для того, щоб ловити такі сюрпризи рано, а не після трьох годин бадьорого редагування.

4. Розбираємо issue #482 по slices

Тепер давайте приземлимо все на реальний приклад, щоб це не залишалося красивою теорією. У нас є issue #482 у Commerce OS: POST /api/orders повертає 500, якщо в checkout надходить порожній список товарів. У нас уже є intake, investigation і загальний plan. Тепер перетворюємо цей plan на послідовність slices, яку інший інженер зможе відкрити й спокійно зрозуміти.

Загальна доріжка тут може виглядати так:

issue #482
→ зафіксувати поточну поведінку
→ додати доменний захист поруч із calculateTotal()
→ відобразити поведінку на HTTP-рівні
→ за потреби оновити контракт / документацію

А в Implementation Plan це зручно записати так:

## PR slices

1. Regression check for empty cart
   Files: OrderControllerWebTest.java
   Verification: targeted check відтворює поточний failure path

2. Domain validation near calculateTotal
   Files: OrderService.java
   Verification: empty items відсікаються до path з items.get(0)

3. HTTP validation response
   Files: GlobalExceptionHandler.java, OrderControllerWebTest.java
   Verification: POST /api/orders with empty items[] returns 400 + agreed validation error body

4. Contract/docs update if this response is documented separately
   Files: api/orders.md or equivalent contract note
   Verification: documented example matches actual behavior

Зверніть увагу, чому порядок саме такий. Перший slice нічого не «виправляє». Він фіксує проблему. Це важливо, тому що без такого кроку наступний slice легко перетворюється на магію: баг начебто був, потім начебто зник, але як саме — уже не дуже зрозуміло. Перший slice дає точку опори. І саме тому slice не дорівнює автоматично окремому PR: спочатку це одиниця мислення та контролю, а не обов’язкова форма упаковки.

Другий slice живе на рівні доменної логіки. Він не лізе одразу в HTTP-контракт, не переписує половину контролера й не починає «заодно покращувати архітектуру». Його єдина задача — зробити так, щоб порожня корзина коректно розпізнавалася як невалідний сценарій саме там, де живе бізнес-правило.

Третій slice вже займається тим, що побачить клієнт API. І це окремий сенс. Дуже часто розробники люблять змішати другий і третій кроки, бо «ну це ж один баг». На рівні задачі — так, один. На рівні рев’ю — ні. Один slice змінює доменну поведінку, інший — HTTP-представлення цієї поведінки. Їх корисно читати окремо. Якщо наявний GlobalExceptionHandler уже вміє мапити потрібну валідацію, цей slice може майже схлопнутися до короткої перевірки — і це теж нормально.

Четвертий slice з’являється не завжди, але в нашому випадку він виправданий лише якщо в проєкті справді ведеться окрема документація API-контракту. Це маленький, але чесний окремий крок. І він набагато приємніше читається окремо, ніж у хвості великого шматка логіки.

Тепер подивімося на контрприклад. Погана декомпозиція для тієї самої задачі виглядала б так:

1. Виправити помилку порожньої корзини
2. Рефакторити calculateTotal у PricingService
3. Прибрати обробку помилок у модулі orders
4. Оновити patch-версію Spring Boot

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

І так, не в кожній команді перший slice обов’язково буде саме failing test. Іноді це може бути короткий відтворюваний запит, службовий сценарій перевірки або мінімальний smoke script. Сенс першого slice не в тому, щоб «за заповітами тестування страждати від червоного». Сенс у тому, щоб перестати сперечатися з реальністю й отримати відтворюваний сигнал: ось баг, ось як він проявляється.

5. Зберігання декомпозиції та читабельність

Коли люди тільки починають працювати з артефактами, у них з’являється спокуса на кожен чих заводити новий Markdown-файл. Це дуже по-людськи. Здається, чим більше файлів, тим серйозніша інженерія. На практиці інколи виходить музей: plan-final.md, plan-final-2.md, really-final-plan.md. Гарно, але жити в цьому важкувато.

Для поточного рівня найчастіше не потрібно вигадувати новий артефакт. Декомпозиція чудово живе як розділ PR slices усередині вже наявного Implementation Plan. Так контекст залишається в одному місці: ви бачите ціль, scope, ризики, перевірки і тут же — послідовність маленьких кроків.

Хороший робочий формат виглядає так:

Slice Намір Файли Перевірка Сигнал стоп
1 Зафіксувати баг OrderControllerWebTest.java targeted check відтворює збій check не відтворюється
2 Увести доменне правило OrderService.java empty items відсікаються до calculateTotal() зачіпаються shared callers calculateTotal()
3 Відобразити помилку в HTTP GlobalExceptionHandler.java, OrderControllerWebTest.java запит дає 400 і узгоджену validation error потрібен загальний redesign error schema
4 Оновити контракт, якщо його документовано окремо api/orders.md або equivalent note приклад збігається з response з’ясовується, що контракт ширший

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

Тут же корисно підключати ваш Workflow Kit, але без зайвого фанатизму. Ви вже зробили issue-analysis skill і reviewer-агента. Цього достатньо, щоб не вигадувати велосипед. Наприклад, issue-analysis може згенерувати первинний розділ PR slices, а reviewer у read-only режимі — перевірити, чи немає надто широких кроків, змішаних намірів або слабких перевірок. Це хороший приклад того, як метапроєкт курсу допомагає реальному Commerce OS, а не існує сам по собі десь у вакуумі.

6. Просимо Claude різати задачу акуратно

Claude дуже старається бути корисним. Інколи навіть занадто. Якщо ви напишете «розбий задачу на кроки», він легко поверне щось на кшталт «оновити сервіс, контролер, тести та документацію». Формально кроки є. Практичної користі — приблизно як від поради «працюйте краще». Тому запит на декомпозицію має мати свій формат результату.

Гарний запит звучить приблизно так:

Розділи затверджений implementation plan на PR slices.
Для кожного slice вкажи:
- один намір,
- конкретні файли,
- одну перевірку,
- що в slice не входить,
- сигнал зупинки.
Не об’єднуй feature, refactor і dependency changes.
Якщо slice не можна відкочувати окремо, розділи його ще.

Сенс тут у тому, що ви задаєте Claude не просто тему, а формат мислення. Ви не просите «зроби красиво». Ви вимагаєте незалежні одиниці роботи. Це сильно змінює результат.

Після першої відповіді корисно робити другий прохід. Не з позиції «ну начебто нормально», а з позиції інженера, який уже одного разу бачив монструозний diff і не хоче повторення. Хороші уточнювальні запитання тут такі: «який із цих slices найбільш широкий?», «який крок зачіпає найбільше підсистем?», «який slice не можна відкочувати ізольовано?», «де ти змішав bug fix і cleanup?». Claude на такі запитання зазвичай відповідає доволі чесно, якщо його попросити прямо.

Якщо хочете використати reviewer-агента з Workflow Kit, дайте йому дуже конкретне завдання: не оцінювати код, якого ще немає, а оцінити якість декомпозиції. Наприклад, перевірити, чи в кожного slice одна ідея, чи є явна перевірка, чи немає прихованого scope creep. Це особливо корисно, коли ви самі вже трохи замилили око і вам починає здаватися, що крок «підправити обробку помилок у orders» звучить досить конкретно. Не звучить. Але після третьої чашки кави мозок інколи стає дуже дипломатичним.

7. Готовий reviewable implementation path

Найчастіша проблема в декомпозиції — не лише надто великі кроки, а й невміння вчасно зупинитися. Можна різати безкінечно й у підсумку отримати список із дванадцяти мікрорухів, кожен із яких уже незручний сам по собі. Тому важливо розуміти не лише як ділити, а й коли вже достатньо добре.

Перевірити себе можна через кілька простих запитань:

Запитання Здорова відповідь
Чи можна описати slice однією фразою? Так, без «і ще»
Чи є у slice одна зрозуміла check? Так, хай навіть маленька
Чи можна його відкочувати окремо? Так, без каскадного ремонту
Чи зрозуміє інший інженер, навіщо існує цей крок? Так, без усного переказу на 15 хвилин
Чи видно зв’язок із критерієм приймання або ризиком? Так, явно

Якщо на ці запитання ви переважно відповідаєте «так», у вас уже не просто список дій. У вас є reviewable implementation path — послідовність, якою можна рухатися спокійно й без інженерного екстриму. І це дуже помітно за відчуттями. Замість туманного «треба полагодити checkout» у вас лежить зрозумілий ланцюжок: спочатку зафіксувати баг, потім закрити доменне правило, потім вивести це назовні на рівні API, а далі, якщо потрібно, оновити контракт.

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

1
Опитування
Issue-to-PR workflow у Claude Code, рівень 17, лекція 4
Недоступний
Issue-to-PR workflow у Claude Code
Issue-to-PR workflow у Claude Code
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ