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, не ощущение «тут вроде современный фронтенд».
На backend в 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
# сохраняем дерево backend-зависимостей в файл
npm ls --all > deps-frontend.txt
# сохраняем дерево frontend-зависимостей в файл
Вы разворачиваете дерево, чтобы увидеть не только прямые зависимости, но и транзитивные — те, что притянула за собой другая библиотека.
Просите 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-секции:
## Карта зависимостей
### Внешние зависимости
- Backend: Gradle, Spring Boot 4.0.6, PostgreSQL driver
- Frontend: Next.js 16.2, React 19.2
- Source of truth: `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 хочется трогать в перчатках.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ