1. Без загального розуміння проєкту мало — потрібна карта
Відкрийте Commerce OS — враження оманливо просте: замовлення, платежі, підтримка, звіти. Вистачає до першого запитання: «де ламається повернення?», «який маршрут викликає платіжний сервіс?» У цей момент «нібито зрозуміло» перетворюється на блукання по папках.
CODEBASE_INVENTORY.md відповідає на запитання «що в проєкті є». API_MAP.md — на запитання «куди йде запит»: через який маршрут він входить, де переходить у сервіси, коли впирається в базу даних, коли викликає платіжного провайдера. Один сценарій тягне за собою HTTP-маршрут, бізнес-логіку, клієнт зовнішнього сервісу, чергу подій, конфіг і тести. Без карти кожне розслідування починається з нуля.
Це робочий документ: куди входить запит, куди йде далі, чим підтверджується.
2. Інтеграція — це будь-який важливий стикувальний вузол, не лише зовнішній
«Інтеграція» звучить так, ніби йдеться про платіжний шлюз, CRM і вебхуки. У навчальному сенсі це будь-який важливий стикувальний вузол між частинами системи, що впливає на поведінку: і зовнішні сервіси, і внутрішні точки з’єднання. Дивіться на них через таблицю:
| Що ми бачимо в проєкті | Приклад у Commerce OS | Чому це потрапляє до карти |
|---|---|---|
| HTTP-ендпоінт | |
Це вхідна точка користувацького сценарію |
| Обробник або контролер | |
Тут починається серверний маршрут |
| Внутрішній клієнт | |
Він пов’язує проєкт із зовнішнім сервісом |
| База даних | таблиці замовлень і повернень | Без неї багато маршрутів просто не мають сенсу |
| Черга або подія | |
Це асинхронне продовження сценарію |
| Межа авторизації | сесія клієнта, роль оператора | Показує, хто взагалі має право викликати маршрут |
| Конфігурація середовища | , |
Маршрут залежить не лише від коду, а й від налаштувань |
| Тести | |
Вони підтверджують контракт і очікувану поведінку |
Пастка: не плутайте карту інтеграцій проєкту з підключенням Claude Code до зовнішніх інструментів. Тут ми описуємо те, що вже живе всередині кодової бази, а не налаштовуємо нові підключення для самого Claude.
Межа авторизації — це відповідь на запитання хто може дійти до цього маршруту: анотація на методі, фільтр, правила в конфігу безпеки, тест.
3. Докази беремо з коду, а не з припущень
Часта помилка звучить мило і небезпечно одночасно: «Ну він же правдоподібно пояснив». Правдоподібно — не означає перевірювано. Джерело істини одне: код, конфіги, тести, за потреби команди збирання.
Ось зручна опора: звідки що зазвичай підтверджується.
| Джерело в проєкті | Що воно зазвичай доводить |
|---|---|
| Контролер, маршрут, обробник | Що ендпоінт справді існує |
| Сервіс або клієнт | Куди маршрут іде далі |
| Конфігурація | Які змінні середовища та зовнішні залежності потрібні |
| Тест | Який контракт або сценарій проєкт вважає нормальним |
| Файл збирання | Що зовнішня бібліотека взагалі підключена |
| Коментар у коді | Іноді допомагає, але сам по собі не є достатнім доказом |
Подивіться на спрощений фрагмент контролера:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/orders")
class OrderController { // фрагмент класу
@PostMapping
OrderResponse create(@RequestBody CreateOrderRequest request) {
return orderService.createOrder(request); // далі маршрут переходить у сервіс
}
}
Цей фрагмент уже підтверджує кілька речей. По-перше, маршрут POST /api/orders існує. По-друге, точка входу знаходиться в OrderController. По-третє, контролер сам майже нічого не робить, а передає виконання в OrderService. Отже, на цьому розслідування не закінчується.
Тепер подивімося на конфігурацію:
payments:
stripe:
api-key: ${STRIPE_API_KEY}
queues:
order-events-url: ${QUEUE_URL}
Конфіг не доводить, що виклик точно відбудеться, але показує важливі залежності маршруту від середовища. Якщо в карті ви пишете «створення замовлення використовує Stripe і чергу подій», а в конфігу немає навіть слідів цих налаштувань, варто насторожитися. Може бути, ви переплутали сервіс, а може бути, знайшли старий мертвий код.
Тести теж дуже корисні, тому що підтверджують не лише існування маршруту, а й очікування проєкту:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Test
void create_returns400_forEmptyCart() throws Exception {
mockMvc.perform(post("/api/orders").content("{}"))
.andExpect(status().isBadRequest()); // порожній кошик недопустимий
}
Такий тест — це вже доказ контракту API. Він не просто каже «маршрут є», а додає важливу умову поведінки: порожній кошик має давати помилку 400, а не, наприклад, мовчки створювати порожнє замовлення. Для карти це дуже корисно, тому що вона перестає бути сухим списком URL і починає фіксувати реальну поведінку системи.
4. Хороший API_MAP.md — короткий і перевірюваний
Коли студенти вперше роблять такий артефакт, вони зазвичай кидаються в одну з двох крайнощів. Або пишуть два рядки в дусі «у нас є замовлення і платежі», або намагаються зробити енциклопедію світу на сорок екранів. Обидві крайнощі не дуже корисні. Хороша карта має бути короткою, робочою і перевірюваною.
Для Commerce OS достатньо почати з простої структури:
# API_MAP.md
## Клієнтський API
## API підтримки
## API панелі керування
## Зовнішні інтеграції
## Відкриті запитання
А всередині секцій уже зручно використовувати таблицю. Наприклад, таку:
| Поле | Навіщо воно потрібне |
|---|---|
| Метод і шлях | Швидко знайти вхідну точку |
| Обробник | Зрозуміти, де починається кодовий маршрут |
| Авторизація | Побачити, хто має доступ |
| Інтеграції | Зафіксувати базу, чергу, зовнішні клієнти |
| Конфіг | Зрозуміти, від чого маршрут залежить у середовищі |
| Тести | Підтвердити контракт і поведінку |
| Відкриті запитання | Не вигадувати відсутні факти |
Зверніть увагу на останню колонку. Вона дисциплінує краще за будь-який пафосний лозунг. Якщо ви не знайшли мобільного клієнта, який використовує маршрут, не потрібно писати «використовується мобільним застосунком» лише тому, що так було б логічно. Напишіть чесно: «не перевірено».
Дуже корисно ставитися до API_MAP.md як до живого файлу в репозиторії, а не як до красивої відповіді у вікні чату. Відповідь Claude Code може допомогти зібрати чернетку, але робочим артефактом карта стає лише тоді, коли лежить поруч із проєктом, проходить через diff і оновлюється після змін.
5. Розбір маршруту на прикладі створення замовлення
Тепер зберімо один маршрут цілком, щоб ви побачили, як із коду народжується нормальний запис у API_MAP.md. Візьмімо Commerce OS і типовий сценарій створення замовлення.
Спочатку корисно побачити маршрут у вигляді схеми:
Вебклієнт
↓
POST /api/orders
↓
OrderController
↓
OrderService
├─→ StripeClient // зовнішній платіжний провайдер
├─→ OrderEventPublisher // подія в чергу
└─→ PostgreSQL // збереження замовлення
Тепер подивімося на сервісний рівень:
import org.springframework.stereotype.Service;
@Service
class OrderService { // фрагмент класу
OrderResponse createOrder(CreateOrderRequest request) {
paymentClient.charge(request.payment()); // зовнішній платіжний сервіс
orderEventPublisher.publishCreated(request); // асинхронна подія
return OrderResponse.created();
}
}
Ось тут уже з’являється справжня інтеграційна інформація. Якщо контролер довів вхід у маршрут, то сервіс доводить, що сценарій іде щонайменше в два боки: до платіжного клієнта й до видавця подій. Якщо десь поруч ще є збереження замовлення в репозиторій, отже, в карті варто згадати і базу даних.
Тепер на основі цих фрагментів можна зібрати запис у API_MAP.md:
## Клієнтський API
| Метод | Шлях | Обробник | Авторизація | Інтеграції | Конфіг | Тести | Відкриті запитання |
|---|---|---|---|---|---|---|---|
| POST | /api/orders | OrderController#create | сесія клієнта | PostgreSQL `orders`, `StripeClient`, черга `order-events` | `STRIPE_API_KEY`, `QUEUE_URL` | `OrderControllerTest#create_returns400_forEmptyCart` | чи використовує маршрут мобільний застосунок напряму? |
Зверніть увагу, як ми дійшли до цього рядка. Не «Claude гарно підсумував», а буквально зібрали його зі спостережуваних деталей: контролера, сервісу, конфігу й тесту. Якщо ви навчитеся робити так хоча б для трьох-чотирьох ключових маршрутів проєкту, далі працювати стане спокійніше. Вже не потрібно кожного разу заново згадувати, де в проєкті платежі, де події, а де лише HTTP-обгортка.
І так, це саме той момент, коли видно, чому карта API — це не просто список ендпоінтів. Якби ви зафіксували лише POST /api/orders, ви б утратили майже все цікаве.
6. Просимо у Claude Code карту, а не вигадки
Тут спокуса особливо велика. Дуже хочеться написати: «Подивись проєкт і розкажи, які тут API та інтеграції». Claude Code, як ввічливий співрозмовник, постарається допомогти. Іноді навіть надто старанно: розповість не лише те, що знайшов, а й те, що просто звучить правдоподібно. Нам таке не підходить.
Слабкий запит виглядає приблизно так:
Розкажи, які API є у проєкті.
Після такого запиту ви майже гарантовано отримаєте красивий, але пухкий текст. Нормальний запит має змусити модель працювати як акуратний помічник із дослідження, а не як гід-імпровізатор. Наприклад, так:
Побудуй чернетку файла API_MAP.md для цього репозиторію.
Для кожного запису вкажи:
- метод і шлях;
- файл обробника;
- пов’язану бізнес-логіку або клієнт;
- межу авторизації, якщо вона видна;
- конфіг або змінні середовища, від яких залежить маршрут;
- пов’язані тести;
- що не вдалося перевірити.
Не вигадуй відсутні факти.
Якщо доказів немає, позначай це як відкрите запитання.
У такого запиту є одразу кілька плюсів. По-перше, ви просите саме чернетку, а не істину в останній інстанції. По-друге, ви задаєте структуру відповіді. По-третє, ви прямо забороняєте моделі домислювати відсутні факти.
Якщо Claude пише фразу на кшталт «проєкт використовує Stripe», хороший наступний запит звучить дуже просто: покажи, чим це підтверджується. Файл клієнта, залежність у збиранні, ключ у конфігу, тест, використання в сервісі — що завгодно з цього вже перетворює припущення на перевірюване твердження. А от фраза без опори має або отримати доказ, або вирушити до колонки «відкриті запитання».
7. Карта живе в репозиторії, а не в історії чату
Дуже легко один раз зібрати інформацію, зрадіти й залишити її в чаті, де вона героїчно потоне через кілька днів у нових обговореннях. Але користі від такого підходу небагато. Артефакт починає працювати лише тоді, коли лежить поруч із кодом і змінюється разом із кодом.
Є просте практичне правило: ви не зобов’язані описати весь проєкт за один присід. Набагато корисніше почати з кількох критичних маршрутів — наприклад, замовлення, повернення, підтримка — а потім доповнювати карту в міру розслідувань. Знайшли новий webhook — додали рядок. Виявили, що маршрут залежить ще від однієї змінної середовища, — оновили запис. З’явився тест, що підтверджує контракт, — дописали його до карти. Це дешевше й надійніше, ніж намагатися написати «повну документацію світу» в перший же день.
Хороша карта зазвичай трохи неповна, але чесна. Погана карта — дуже повна, дуже красива і місцями вигадана. Для інженерної роботи майже завжди кращий перший варіант. Особливо якщо ви працюєте з Claude Code і хочете, щоб він потім використовував цей файл як надійний контекст, а не як збірку легенд про проєкт.
Тому для Commerce OS сьогодні у вас дуже зрозуміла мета: почати API_MAP.md з кількох перевірених маршрутів, фіксувати поруч обробник, авторизацію, інтеграції, конфіг і тести, а все неперевірене чесно складати до відкритих запитань. У цей момент проєкт перестає бути темним лісом із табличкою «тут десь є платежі» і починає перетворюватися на систему, якою вже можна ходити не навпомацки, а за картою.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ