JavaRush /Курси /Claude code /Legacy risk map: карта рішень

Legacy risk map: карта рішень

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

1. Призначення risk map як карти рішень

Коли ви вперше заходите в legacy-сервіс на кшталт CashFlow Dashboard, спокуса дуже зрозуміла: виписати довгий список усього неприємного і відчути, що робота виконана. Тут deprecated, тут мало тестів, тут конфіг ніби писала людина в ліфті між поверхами. Команді такий список майже марний: він не підказує, куди йти, а куди краще навіть не сунути викрутку.

RISK_MAP.md потрібен саме для цього: він перетворює хаос знань на керовану карту «що небезпечно змінювати, наскільки це важливо для бізнесу і яку дію розумно зробити наступною». Legacy страждає не від того, що код місцями сумний. Legacy страждає від того, що хтось каже «та я тут один рядок поправлю», — і до вечора у фінменеджера MRR з’їжджає на вісім відсотків.

Корисно тримати в голові три артефакти поруч, тому що вони відповідають на різні питання:

Артефакт На яке питання відповідає
CODEBASE_INVENTORY.md
Що взагалі є в проєкті?
ARCHITECTURE_CURRENT.md
/ current-state notes
Як система реально працює зараз?
RISK_MAP.md
Де зміна найбільш небезпечна і що з цим робити?

Якщо говорити зовсім просто, inventory — це карта вулиць, current-state документ — опис дорожнього руху, а risk map — позначки «тут міст ремонтують, сюди краще не сунутися без плану». І саме ця третя частина найчастіше виявляється найпрактичнішою: вона рятує команду від героїчного, але дуже дорогого хаосу.

Тому RISK_MAP.md — не Markdown-версія тривожного щоденника, а спосіб перестати ставитися до всіх зон однаково: mrr-engine, прапорці в конфігу і старий клас із legacy/ не рівні за ризиком, навіть якщо так і просяться «терміново почистити».

2. Дві осі: criticality і change risk

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

Business criticality, важливість для бізнесу, вимірюється не красою коду, а наслідками. Зламалася логіка MRR — це бачать Commerce OS, фінансові звіти, бухгалтерія, і за кілька годин це вже грошова проблема. Зламався формат підпису в некритичному звіті — світ не падає.

Change risk, ризик зміни, дивиться зовсім в інший бік: тут цікаво не те, наскільки область важлива, а те, наскільки вона крихка. Низьке покриття, розбіжність документації і коду, високий churn в історії Git, неясний власник, конфіг між yaml і змінними середовища — усе це робить зону небезпечною, навіть якщо вона не є головним бізнес-флоу.

Добре працює така спрощена матриця:

Важливість для бізнесу \ Ризик зміни Низький ризик зміни Високий ризик зміни
Низька важливість Можна досліджувати і змінювати досить вільно Не варто лагодити «заодно»; спочатку зрозуміти, чому зона така крихка
Висока важливість Змінювати можна лише вузько і з явною перевіркою Червона зона: спочатку потрібні додаткові докази, власник і обмеження

Саме тому mrr-engine у CashFlow Dashboard майже автоматично падає у правий верхній кут: бізнес-критичний і ризикований у зміні. А старий utility-клас із legacy/, навіть потворний, скоріше потрапить у «високий change risk, але не перший пріоритет за бізнесом».

Дуже важливо не склеювати ці осі в одну оцінку «небезпечно / не небезпечно». Інакше команда або панічно уникає всіх змін, або безтурботно чіпає критичні флоу. Legacy такі ілюзії любить. Потім виставляє рахунок.

3. Unknowns як повноцінний сигнал ризику

На legacy-проєктах слово «unknowns» звучить менш урочисто, ніж мало б, — а на практиці саме невідомість часто і є головним підсилювачем ризику. Найнебезпечніше тут — вдавати, ніби картина ясна. Claude Code теж не проти зробити розумний вигляд і продовжити — не піддавайтеся.

Невідомість у risk map — не сміттєвий залишок після аналізу, а повноцінний сигнал. Не знаємо, як система поводиться на межі місяця під час зміни таймзони, — це не «поки без оцінки», а підвищений ризик. У PaymentRetryService логіка начебто відновлює підписку після retry, але тесту немає — і невідомість сама піднімає change risk.

На CashFlow Dashboard хороший приклад — тема паузи підписки. Документ каже, що paused subscription не входить в активний MRR, а код у MrrFormulas.java рахує її активною. Чесне формулювання не «логіка, мабуть, виключає paused», а «документація і код розходяться; потрібна ручна перевірка».

Корисне правило тут жорстке: якщо Claude не показав evidence anchor, значить, він не знає, а припускає. Тоді в артефакті з’являється позначка assumption або manual verification needed, а не впевнений висновок. Проєкт і так страждає від накопичених напівправд — не додавайте ще одну, тепер зі штучним інтелектом.

І так, іноді найпрофесійніша дія на цьому етапі — чесно написати: «власник області неочевидний», «реальна поведінка в проді не підтверджена», «конфіг зібраний із кількох джерел і потребує ручної звірки». Це не слабкість аналітика, а інженерна гігієна.

4. Зміст одного запису в RISK_MAP.md

Коли risk map зроблено добре, він читається швидко і допомагає так само швидко ухвалювати рішення, тому структура запису проста і повторювана, без літературних відступів на пів сторінки. Сам файл — артефакт проєкту: Workflow Kit дасть шаблон, skill або read-only агента, але RISK_MAP.md живе поруч із CashFlow Dashboard.

На практиці один запис відповідає на сім питань, зводячи спостереження із signal log і current-state не в дубль, а в рішення.

Поле Що воно має прояснити
Area
Про яку область проєкту йдеться
Business criticality
Наскільки боляче бізнесу, якщо там щось зламається
Change risk
Наскільки небезпечно вносити туди зміни
Risk categories
Якого типу це ризик: дані, конфіг, невідома поведінка, слабкі тести і так далі
Evidence
На чому ґрунтується висновок: файли, рядки, логи, звіти, git log, coverage
Missing checks
Чого нам бракує для впевненого внесення змін
Recommended action
Що розумно зробити зараз, а не колись у світлому майбутньому

Запис не має перетворюватися на мініроман. Ось компактний робочий фрагмент:

## Область
mrr-engine / pause-resume MRR

**Критичність для бізнесу:** висока  
**Ризик зміни:** високий  
**Категорії ризику:** business-critical, no-test, unknown behavior  
**Докази:** `MrrFormulas.java:88`, `SubscriptionService.java:154`, JaCoCo ~25%  
**Бракує перевірок:** немає сценарію pause-resume  
**Рекомендована дія:** не змінювати формули до фіксації поточної поведінки та review власником

Зверніть увагу на дві пастки. Missing checks — не Evidence: одне говорить, що ми знаємо, інше — чого бракує. А Recommended action — не «покращити код», а виконувана дія: заморозити зміну, уточнити власника, зафіксувати поведінку, обмежити scope, не чіпати зону.

Якщо в запису немає останнього рядка, він майже завжди марний: risk map існує заради вибору наступного ходу, а не опису страху.

5. Використання Claude Code

На цьому етапі Claude Code дуже корисний, але строго в режимі «прискорюємо збір evidence», а не «нехай сам поставить діагноз». Тримайте сесію в read-only: агент читає, шукає по коду, дивиться git log, відкриває звіти, але не редагує. Нам не потрібен ентузіаст з редактором — потрібен швидкий акуратний дослідник.

Добрий запит до Claude в цій задачі виглядає структуровано і нудно — і це комплімент:

Проаналізуй область `mrr-engine` як елемент risk map.
Поверни:
1. business criticality,
2. change risk,
3. categories,
4. evidence,
5. missing checks,
6. recommended action.
Код не змінюй.

Формат повертає дані у формі, з якої реально зібрати RISK_MAP.md, і не дає Claude зіскочити в звичне «ось ще три ідеї рефакторингу, які я придумав вам безкоштовно». Безкоштовне в legacy потім оплачується дорого.

Якщо команда вже зібрала Workflow Kit, там може жити read-only агент risk-mapper — з навмисно нудною і обмеженою конфігурацією:

---
name: risk-mapper
description: Збирає RISK_MAP.md тільки за evidence, без правок коду
tools: Read, Grep, Glob, Bash(git log:*)
---

Тут важливе саме обмеження. Дайте агенту Edit — він рано чи пізно почне «допомагати», а потрібна дисципліна: прочитай, порівняй, зібери anchor, познач невідоме, зупинися.

Ще одна корисна звичка — вимагати опори під кожним висновком. «Зона високого ризику через складність» — красиво і марно; нехай покаже файл, coverage, git log, документ, що розходиться з кодом. Не може — отже, це гіпотеза, позначена чесно.

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

6. CashFlow Dashboard: mrr-engine, retry і конфіги

Тепер давайте приземлимо все це на проєкт. У CashFlow Dashboard є щонайменше три дуже показові зони — вони хороші тим, що показують: високий ризик народжується з комбінації бізнес-критичності і слабкої перевірюваності. Спочатку подивімося на компактну картину:

Область Business criticality Change risk Чому це небезпечно Розумна дія
mrr-engine / pause-resume
Висока Високий Впливає на MRR, coverage низький, код і документи розходяться Не змінювати формули без фіксації поточної поведінки
payments / retry recovery
Висока Високий Зачеплені гроші, зовнішня інтеграція, неочевидні гілки retry Спочатку уточнити реальний потік і власника області
config / timezone + feature flags
Середня/висока Високий Конфіг розмазаний по yaml і env, таймзона поводиться нерівномірно Спочатку зібрати current-state конфігурації, не чіпати «заодно»

mrr-engine — майже навчальний приклад червоної зони. Є реальний бізнес-біль: Commerce OS уже скаржиться на розбіжність MRR, а під капотом низьке покриття і формули в кількох файлах. Навіть простий сигнал із Git це підсвічує:

git log --since="1 year ago" --name-only --pretty=format: \
  | grep 'mrr-engine/MrrFormulas.java' | wc -l
# 11

Одинадцять змін самі по собі ще нічого не доводять. Але складіть їх із coverage близько 25% і розбіжністю документа з кодом — і вийде вже не відчуття, а цілком пристойний пакет доказів. Запис для mrr-engine:

## Область
mrr-engine / pause-resume MRR

**Критичність для бізнесу:** висока  
**Ризик зміни:** високий  
**Категорії ризику:** business-critical, no-test, unknown behavior  
**Докази:** `MrrFormulas.java:88`, `SubscriptionService.java:154`, `git log`, JaCoCo ~25%  
**Бракує перевірок:** немає сценарію pause-resume і перевірки межі місяця  
**Рекомендована дія:** обмежити будь-які зміни, доки не підтверджено поточну поведінку

Тепер візьмімо payments / retry recovery — тут risk map менш очевидна, бо код іноді акуратніший, ніж у mrr-engine. Але навіть за кращого покриття помилка дорога — особливо коли неясно, коли підписка відновлена після retry, а коли має потрапити в churn.

Третя зона — конфіги і таймзона. Це той випадок, коли багато хто недооцінює ризик, бо «ми ж не змінюємо бізнес-логіку, лише поправимо конфіг». На legacy така фраза звучить приблизно як «я лише трохи посунув цеглину в несучій стіні». Feature flags розмазано між application.yml, середовищем і старими overrides, дати місцями йдуть через UTC, місцями через local time — change risk високий навіть без алгебраїчних формул.

І є ще один підступний приклад: legacy/OldBillingUtils.java. Важливість для бізнесу в нього може бути неочевидною, на перший погляд — просто старий utility, який дуже хочеться переписати заради внутрішнього спокою і душевного здоров’я. Але він використовується в десятках місць і без покриття — change risk високий. Risk map дає змогу сказати: «ні, це не перша ціль» — не тому, що код хороший, а тому, що ціна необережного покращення вища за очікувану користь.

7. Читання готової risk map і ухвалення рішень

Коли RISK_MAP.md починає працювати, він перестає бути документом «для галочки» і стає фільтром: кожне нове питання по legacy звучить трохи інакше — не «чи можемо ми це швидко поправити?», а «що карта каже про ціну виправлення?».

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

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

І так, risk map — живий артефакт: з’явився власник, підтягнули evidence, зникла розбіжність документа і коду — місце зони змінюється. Але починаємо не з оптимізму, а з доказів.

Коли ви дивитеся на CashFlow Dashboard і замість імпульсу «треба терміново все почистити» спокійно кажете: «ось червона зона, ось чому вона червона, і чому туди зараз не можна без додаткового evidence», — RISK_MAP.md уже не декоративний. Він працює. Так і починається доросле ставлення до legacy — навіть якщо сам legacy все ще виглядає так, ніби його писали в ніч перед релізом.

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