Перейти к основному содержимому

Как читать чужой код

Разработчику Архитектору

Главное правило

Не читайте всё подряд. Репозиторий на десятки тысяч строк нельзя освоить за один вечер. Читайте целенаправленно: от симптома или задачи к точке входа, затем — только связанные модули.

Чужой код — норма первой работы и open source. Навык чтения так же важен, как написание.


Алгоритм входа в проект

ШагДействие
1README, docs/, схема в wiki — назначение проекта и как собрать
2Точка входаmain, Program.cs, index.js, manage.py
3Сценарий — один пользовательский путь (логин, создание заказа)
4Слои — UI → сервис → репозиторий → БД
5Зависимости — кто кого вызывает (IDE: Find References, graph)
6Тесты — показывают ожидаемое поведение
7Git historygit log -p -- path/to/file — история изменений

Структура папок — Организация структуры кодовой базы. Legacy-системы — 7.11 Легаси-код.


Точка входа

Точка входа (entry point) — место, где ОС или runtime (среда выполнения) начинает выполнение:

  • консоль: static void Main, if __name__ == "__main__";
  • веб: Program.cs + Startup, app.js + router, wsgi.py;
  • job: cron → скрипт из README.

От entry point проследите первый HTTP-маршрут или первую команду CLI, которая относится к вашей задаче. Маршруты и HTTP — Веб-разработка.


Слои и логические блоки

Разбейте код на блоки ответственности:

СлойВопрос при чтении
UIОткуда приходят данные формы?
ЛогикаКакие правила и исключения?
ДанныеSQL, ORM, внешний API?

Сначала разберите правило в сервисе, потом углубляйтесь в ORM. MAPPER и культура кода помогают сопоставить код с предметной областью.


Граф зависимостей

Граф зависимостей (dependency graph) — кто импортирует или инжектит (передаёт через конструктор) кого. IDE строит Call Hierarchy, Find All References, diagram imports.

Практика:

  1. Откройте класс или функцию из задачи.
  2. Посмотрите вверх — кто вызывает (контроллер? тест?).
  3. Посмотрите вниз — что вызывает сам (БД? почта?).

"Божественный объект" на 3000 строк — признак, что граф разросся; ищите швы для понимания — Безопасные изменения в легаси.


Методики чтения

Top-down (сверху вниз)

Сначала архитектура (README, диаграмма), потом детали. Подходит для нового проекта.

Bottom-up (снизу вверх)

От одного бага или unit-теста вглубь. Подходит для точечной задачи — Как искать баг.

По тестам

Тесты — исполняемая спецификация. Characterization tests фиксируют поведение legacy до рефакторинга — Тестирование для разработчика.

Псевдокод на русском

Перепишите метод блоками:

Шаг 1 — загрузить пользователя по id
Шаг 2 — если не найден — ошибка 404
Шаг 3 — применить скидку
Шаг 4 — сохранить заказ

Так же учат в 4.01–4.03 — привычка снимает страх синтаксиса.


Пошаговый разбор входа в репозиторий

Допустим, задача: "исправить баг при сохранении профиля". План чтения:

ШагДействиеИнструмент
1Найти текст кнопки или URL /profileпоиск по проекту (Ctrl+Shift+F)
2Открыть обработчик сохраненияGo to Definition
3Проследить вызов в сервисCall Hierarchy
4Найти запрос к БД или APIFind References
5Прочитать тест test_save_profileсписок тестов в IDE
6git log -p -- path/to/profile_service.pyтерминал

Не открывайте utils/ "на будущее" — только цепочка от симптома.


Структура типичного веб-проекта

project/
├── README.md
├── package.json / pyproject.toml / *.csproj
├── src/
│ ├── controllers/ # HTTP — точки входа запросов
│ ├── services/ # бизнес-правила
│ ├── repositories/ # доступ к БД
│ └── models/ # сущности данных
├── tests/
└── docs/

Имена папок различаются (handlers, api, domain), слои — одинаковые. Подробнее — 116 организация.


Файлы конфигурации — что искать

ФайлСодержит
README.mdсборка, запуск, архитектура
.env.exampleкакие переменные нужны (без секретов)
package.jsonскрипты npm start, npm test, зависимости
docker-compose.yamlкакие сервисы поднимаются локально
appsettings.json / config.pyпорты, строки подключения
.editorconfigотступы, кодировка

Контейнеры, .env.


IDE — инструменты чтения (VS Code)

  • Go to Definition (F12) — перейти к объявлению функции.
  • Peek Definition (Alt+F12) — посмотреть без ухода с места.
  • Find All References (Shift+F12) — кто вызывает.
  • Call Hierarchy — дерево вызовов вверх/вниз.
  • Outline — структура файла (классы, методы).
  • Breadcrumbs — путь по символам вверху редактора.
  • GitLens (расширение) — blame, история строки.

DevTools — для фронтенда в браузере.


git blame и git log

git blame — кто и когда изменил каждую строку:

git blame src/services/order.py

git log — история коммитов по файлу:

git log --oneline -- src/services/order.py
git log -p -3 -- src/services/order.py # последние 3 с diff

Сообщение коммита часто объясняет почему код выглядит странно — 1141 типовые Git.


Чтение HTTP-маршрутов

Пример (псевдо-Express / FastAPI):

POST /api/users/:id/profile → ProfileController.update
GET /api/users/:id → UserController.show

Найдите регистрацию маршрутов (app.get, @app.post, MapController) — оттуда цепочка в контроллер → сервис. HTTP и REST.


Паттерны, которые часто встречаются

MVC (Model – View – Controller)

  • Model — данные и правила;
  • View — UI (HTML, React);
  • Controller — принимает запрос, вызывает model, отдаёт view.

Repository

Слой Repository скрывает SQL/ORM от сервиса:

UserService → UserRepository → PostgreSQL

Сервис не пишет SELECT напрямую — проще тестировать с fake repository.

Dependency Injection

Зависимости передают извне (конструктор, параметр), а не создают внутри new Database(). Упрощает подмену в тестах — 4.09 / 12.


Таймбоксинг — сколько читать

ЗадачаРазумный лимит
Мелкий баг1–2 часа чтения + repro
Новая фича в знакомом модулеполдня
Вход в новый проект1–3 дня на README + один сценарий

Если за 2 часа не нашли entry point — спросите коллегу "с какого файла начать?", не стесняйтесь.


Вопросы команде (шаблон)

  • Где точка входа для сценария X?
  • Есть ли диаграмма архитектуры?
  • Какой тест ближе всего к задаче?
  • Есть ли feature flag или legacy-ветка?
  • Кого тегнуть в PR по этому модулю?

Чек-лист онбординга в код

  • Проект собирается локально по README
  • Тесты запускаются (pytest, npm test)
  • Прочитан один end-to-end сценарий от UI/CLI до БД
  • Понятны слои (UI / service / data)
  • Настроена IDE (Go to Definition работает)
  • Известно, как оформить PR — 117

Legacy и сложный код

СимптомЧто делать
Нет тестовНаписать characterization test перед правкой — 7.11 / 3
Непонятные именаПереименовать локально + IDE refactor, маленькими PR
Комментарий "не трогать"Выяснить историю в git blame, спросить команду
КопипастаИскать отличия копий — там часто баг

Что такое легаси, Понимание системы, Стратегии модернизации.


Стили и соглашения

Один проект — один стиль (отступы, имена, слои). Найдите:

  • CONTRIBUTING.md, .editorconfig, линтер-конфиг;
  • Стили кода;
  • как в проекте именуют ветки и PR — Git / 114.

В первом PR придерживайтесь стиля репозитория, а не личных предпочтений.


Чтение при code review

Ревью — чтение diff (разницы изменений), а не всего файла. Те же вопросы: логика, границы, тесты, безопасность — Код-ревью и PR.


Чего избегать

  • Читать файл за файлом по алфавиту.
  • Менять код до понимания причин текущей реализации.
  • Стыдиться вопросов автору или в issue.
  • Полагаться только на ИИ-summary без проверки по исходникам.

Связанные материалы