1. Папки показують «що є», а не «як пов’язано»
Дерево папок orders/, payments/, support/, dashboard/ створює ілюзію порядку. Але папки — це адреси. Вони не кажуть, хто кого викликає.
Дивіться на проєкт у двох зрізах. Зовнішній: які бібліотеки і фреймворки, яких версій, що притягнулося транзитивно. Внутрішній: які модулі Commerce OS знають одне про одного, куди спрямовані стрілки, де зв’язність уже пахне спагеті.
Карта того, що шукаємо:
| Зріз | Що шукаємо | Де шукаємо | Навіщо |
|---|---|---|---|
| Зовнішні залежності | бібліотеки, фреймворки, версії | , , |
зрозуміти стек і реальні версії |
| Внутрішні залежності | зв’язки між модулями | імпорти, виклики сервісів, структура пакетів | зрозуміти вплив змін |
| Зворотні залежності | хто використовує модуль або файл | пошук за посиланнями, , |
знайти небезпечні центральні точки |
| Архітектурні порушення | цикли й порушення шарів | карта модулів, імпорти, references | завчасно побачити зони ризику |
Папки — це знання адрес. Залежності — це знання дорожнього руху. Лише друге дає змогу безпечно писати task spec, не зносячи половину магазину однією правкою.
2. Зовнішні залежності: маніфест бреше, lockfile — ні
Починайте із зовнішніх: вони відкрито лежать у конфігурації. Але маніфест показує, що проєкт хоче використовувати, а не що реально встановлено.
На фронтенді:
{
"dependencies": {
"next": "16.2.0",
"react": "19.2.0"
}
}
Це заявка, а не істина. Реальні версії живуть у lockfile. Lockfile — джерело правди про версії та дерево залежностей. Не package.json, не пам’ять Claude, не відчуття «тут ніби сучасний фронтенд».
На бекенді в Java перше джерело — build.gradle:
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
Воно дає прямі залежності. Повну картину перед оцінюванням ризику оновлень дає дерево:
./gradlew dependencies --configuration runtimeClasspath > deps-backend.txt
# зберігаємо дерево залежностей бекенду у файл
npm ls --all > deps-frontend.txt
# зберігаємо дерево залежностей фронтенду у файл
Ви розгортаєте дерево, щоб побачити не тільки прямі залежності, а й транзитивні — ті, що притягнула за собою інша бібліотека.
Просіть Claude не «які тут бібліотеки?», а так:
Покажи зовнішні залежності проєкту у двох частинах:
1) прямі залежності з конфігурації,
2) реально встановлені версії за lockfile або деревом залежностей.
Окремо познач backend і frontend.
Для кожного важливого твердження вкажи файл або команду-джерело.
Тут працює правило з минулої лекції: якщо Claude пише «проєкт використовує таку-то бібліотеку» без джерела — це гіпотеза, не знання. Перевіряйте маніфест, lockfile, вивід команди.
3. Внутрішні залежності: куди дивляться стрілки
Внутрішні залежності — не список бібліотек, а реальні зв’язки бізнес-логіки. Навчальний фрагмент карти:
orders ──► catalog
orders ──► payments
support ──► customers
support ──► ai-assist
dashboard ──► orders
dashboard ──► support
Це не повний граф, а фрагмент. Стрілка — напрям залежності. orders знає про payments. Зворотне — не завжди бажано.
У коді це виглядає буденно:
package com.commerceos.orders;
import com.commerceos.catalog.InventoryService;
import com.commerceos.payments.PaymentService;
public class OrderService {
private final InventoryService inventoryService;
private final PaymentService paymentService;
}
OrderService залежить від каталогу й платежів — це шматок карти модулів. На етапі discovery завдання — побачити зв’язок, не оцінювати.
Просіть карту прямо:
Побудуй карту внутрішніх залежностей проєкту.
Для кожного верхньорівневого модуля покажи:
- від яких внутрішніх модулів він залежить,
- які сервіси або класи це підтверджують,
- чи є підозрілі прямі зв’язки між шарами.
Не пропонуй рефакторинг. Спочатку лише карта й evidence.
Ідеальний граф всесвіту не потрібен — потрібен робочий рівень точності. Знаєте, що dashboard тягне orders і support, а support — customers і ai-assist, — цього достатньо, щоб розуміти зони ураження під час змін.
Якщо є LSP або пошук references — вони пришвидшать завдання. Але не перетворюйте це на експедицію з налаштування інструментів: для discovery достатньо читання коду, імпортів і звичайного пошуку.
4. Зворотні залежності: хто впаде, коли ви це зачепите
«Від чого залежить модуль» — лише половина картини. Друга половина — хто залежить від нього. Вона показує, чому деякі файли не чіпають у п’ятницю ввечері перед релізом.
Файл RefundPolicy.java сам по собі короткий. Але якщо на нього посилаються orders, payments, support і admin — це центральна точка ризику. Один автомат у щитку, від якого залежить пів квартири.
Знайти просто:
grep -R "RefundPolicy" backend/src backend/test
# шукаємо, де в проєкті згадується RefundPolicy
Багато збігів по різних модулях — сигнал: правка логіки повернень ударить одразу по кількох частинах. Позначте такий файл у CODEBASE_INVENTORY.md як ризиковий центральний файл.
Розрізняйте два питання:
| Питання | Що воно означає |
|---|---|
| Від чого залежить payments? | що самому модулю потрібно для роботи |
| Хто залежить від payments? | кого цей модуль може зачепити під час зміни |
Друге питання важливіше під час оцінювання ризику. Модуль може залежати від двох сусідів, але від нього самого — шість інших частин проєкту. Тому зворотні залежності часто цінніші за прямі.
Claude і тут працює предметно:
Для модуля payments знайди:
- які внутрішні файли й сервіси використовуються найчастіше,
- на які класи є багато посилань із інших модулів,
- які файли виглядають як центральні точки ризику.
Підтверджуй висновки посиланнями на імпорти, references або результати пошуку.
Математичної ідеальності не чекайте. Потрібен інженерний результат: місця, де маленька зміна дає великий радіус ураження. Це кандидати до секції high-risk вашого inventory.
5. Layer violation і цикли: помітити, не лікувати
Коли карта вимальовується, спливають два неприємні сюрпризи: порушення шарів і циклічні залежності. Не катастрофа просто зараз, але це попередження: правте тут обережно.
layer violation — коли нижчий, більш технічний шар знає про верхній, бізнесовий. Платежі тягнуть у себе логіку замовлень:
package com.commerceos.payments;
import com.commerceos.orders.OrderService; // тривожний сигнал
public class PaymentAuditService {
private final OrderService orderService;
}
Сам імпорт ще не доводить катастрофу — можливо, у команди була причина. Discovery потрібен, щоб такі місця помічати, а не бігти переписувати. Ви фіксуєте докази, не рефакторите.
Цикл гірший: два модулі тягнуть одне одного по колу.
orders ──► payments
payments ──► orders
Коло означає, що модулі перестають нормально відокремлюватися. Правка в одному тягне другий. Тестувати, перевикористовувати, пояснювати новачку — усе складніше.
Дисциплінарне правило: не лікуйте цикл у тій самій сесії, де його знайшли. Завдання на цьому етапі — discovery: записати, де знайдено цикл, якими файлами це підтверджується, наскільки ви впевнені. Хороший запис у чернетці:
Можливий цикл між orders і payments: знайдено імпорт PaymentService у OrderService і посилання на OrderService у payments. Потрібно додатково перевірити, це реальна бізнес-залежність чи локальний обхідний шлях.
У такому формулюванні є evidence і немає паніки. «Архітектура жахлива, треба все терміново переробити» — це емоції, а не analysis.
6. Dependency map у CODEBASE_INVENTORY.md
Перетворіть знахідки на артефакт. Усе про залежності кладіть у той самий CODEBASE_INVENTORY.md, а не в окремі файли: на першому проході статична карта проєкту зручніша в одному місці.
Поряд із ризиковим висновком залишайте коротку опору на джерело: import, reference, test або команду пошуку. Тягнути весь лог пошуку не потрібно.
Фрагмент dependency-секції:
## Карта залежностей
### Зовнішні залежності
- Бекенд: Gradle, Spring Boot 4.0.6, драйвер PostgreSQL
- Фронтенд: Next.js 16.2, React 19.2
- Джерело істини: `build.gradle`, `package.json`, lockfiles
### Напрям внутрішнього модуля
- `orders` -> `catalog`, `payments` (imports всередині `orders/`)
- `support` -> `customers`, `ai-assist` (imports всередині `support/`)
- `dashboard` -> `orders`, `support` (references із `dashboard/`)
### Ризикові центральні файли
- `payments/RefundPolicy.java` — використовується в кількох модулях, змінювати обережно (`grep -R "RefundPolicy" backend/src backend/test`)
- `orders/OrderStatus.java` — багато посилань із різних частин проєкту (`git grep "OrderStatus"`)
### Підозрілі точки
- можлива циклічна зв’язка `orders` <-> `payments` (`orders/OrderService` імпортує `PaymentService`; `payments/PaymentAuditService` імпортує `OrderService`) [потрібно підтвердити]
- підозра на порушення шару в `payments/...` через прямий імпорт `orders` (`payments/PaymentAuditService`)
Позначайте, що підтверджено, а що лише ймовірно: [підтверджено], [потрібно перевірити], [не перевірено]. Чесний inventory корисніший за красивий. І не малюйте величезний граф — зберігайте компактні висновки: хто з ким пов’язаний, де центральні вузли, які файли небезпечні для правок.
Так CODEBASE_INVENTORY.md перестає бути акуратним markdown і стає робочою картою проєкту. Повернетеся до Commerce OS за тиждень розбирати задачу по поверненнях — і не доведеться заново згадувати, чому RefundPolicy хочеться чіпати в рукавичках.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ