Короткий ответ
#Почему важен порядок
Почти все начинают не там, и это «не там» — код.
Читать большую незнакомую кодовую базу файл за файлом ощущается как прогресс, а прогрессом не является. Через месяц у вас частичная картина, живёт она только в вашей голове, воспользоваться ею больше никто не может, и вы не можете сказать, сколько осталось, — а именно от этого работа с легаси и кажется бесконечной.
Порядок ниже переворачивает это. Каждый проход даёт что-то конкретное в форме, которую может прочитать кто-то другой, и каждый сужает то, на что придётся смотреть следующему. К пятому проходу у вас вместо безграничного страха ограниченный список вопросов.
#Семь проходов
-
Что запущено и где
До всякого кода: какие есть среды, что в каждой развёрнуто, что работает по расписанию и что работает, чего в репозитории нет вовсе.
На последнем спотыкаются все. Cron на сервере, облачная функция, созданная в консоли, скрипт на ноутбуке, таблица, которую кто-то ведёт руками. Смотрите в консоль облака и в crontab, а не только в код.
-
Опись
Каждый компонент с типом и одним читаемым предложением о том, зачем он. Сервисы, модули, базы, очереди, задачи по расписанию, фронтенды, внешние системы.
Это самый плоский артефакт, который вы произведёте, и тот, который делает возможным каждый следующий разговор. Обычно это же и момент, когда находится компонент, о существовании которого никто не знал.
-
Внешние границы
В какие внешние сервисы система ходит? Кто ходит в неё? На чьём аккаунте каждая зависимость? На какие входящие интерфейсы кто-то опирается?
Исходящие потоки, о которых никто не думает, — ночной файл, аналитика, выгрузка партнёру — живут здесь.
-
Проследите данные
Где живут клиентские данные, как они туда попадают и куда уходят? Именно здесь пересекаются регуляторные обязанности, бизнес-риск и части, которые нельзя ломать.
-
Запишите, что установить не удалось
Явно, с приоритетами и причинами. Этот список и есть настоящий результат упражнения; карта делает его убедительным.
Уверенная картина без дыр либо получена из полного анализа, либо превратила свои дыры в молчание, а снаружи это выглядит одинаково.
-
Читайте выборочно, идя по дырам
Вот теперь открывайте код — именно те части, на которые указывает список. Чтение с вопросом эффективнее чтения ради картины на порядок.
-
Разберите список, а потом начинайте менять
Каждый закрытый вопрос — это возвращённый кусочек контроля. Структурные изменения после этой точки становятся обычной инженерией, а не актом веры.
#Как читать код, когда до него дойдёт
К шестому проходу у вас есть конкретные вопросы, и это полностью меняет технику. Четыре вещи, которые работают:
- Проследите один запрос от начала до конца. Возьмите самый коммерчески важный путь — платёж, регистрацию, заказ — и пройдите его от точки входа до базы. Один путь учит большему, чем пятьдесят файлов.
- Читайте тесты раньше реализации, где тесты есть. Они описывают намерение, а там, где расходятся с кодом, отмечают что-то интересное.
- Читайте историю рискованного файла, а не только его текущее состояние. Почему он менялся и как часто — обычно информативнее того, что в нём написано сейчас.
- Записывайте каждый ответ туда, где его найдёт кто-то другой. Ответ, оставшийся в вашей голове, воспроизвёл исходную проблему с новым человеком посередине.
#Как найти рискованные части
Не всё в легаси-системе одинаково опасно, и знание, какие части опасны, — это бо́льшая часть пользы.
Четыре признака, и все видны из структурной картины, а не из чтения:
- Концентрация. Один компонент, от которого зависят многие. Менять его дорого; не иметь возможности его менять — хуже.
- Скопление неизвестного. Шесть открытых вопросов по одной подсистеме — это не то же самое, что шесть равномерно размазанных. Скопление отмечает часть, которую никто никогда и не понимал.
- Внешняя граница с неподтверждённым поведением. Исходящая интеграция, у которой не удалось установить повторы, таймауты и обработку сбоев, — это живой бизнес-риск, а не пункт технического долга.
- Заявленное расходится с наблюдаемым. Там, где комментарий, README или проектная заметка говорят одно, а код делает другое, чья-то картина мира уже неверна.
#Что перестать делать
Прибираться по ходу дела.
Вместо этого Ничего не меняйте, пока нет картины. Наводить порядок в коде, которого вы не понимаете, — это то, как работающая система перестаёт работать, и подозревать это изменение не станут: оно же «ничего не делало».
Читать файл за файлом в надежде, что картина сложится.
Вместо этого Сначала выведите структуру, потом читайте выборочно. Месяц чтения даёт карту хуже, чем один анализ, и в месте, куда больше никто не дотянется.
Заказывать проект по документированию.
Вместо этого Проекты по документированию легаси почти никогда не заканчиваются: они безграничны, и никто не может сказать, сколько осталось. Выведенная картина ограничена и завершается.
Считать комментарии и README фактами.
Вместо этого Считайте их заявлениями, которые стоит записать. README, описывающий систему по состоянию на 2021 год, не нейтрален — он активно вводит в заблуждение.
Решать переписывать до того, как научились это описывать.
Вместо этого Сначала опишите. Описание обычно меняет решение и всегда меняет оценку.
#Сколько это занимает
| Проход | Трудозатраты |
|---|---|
| Что запущено и где | Полдня, в основном в консолях |
| Опись, границы, данные | Часы, если выводить. Недели, если собирать руками |
| Запись неизвестного | Час, когда проходы выше уже сделаны |
| Выборочное чтение | Дни-недели, ограничено списком |
| Разбор списка | Недели-месяцы, и он заметно сокращается |
Важно здесь последнее: он заметно сокращается. Работа с легаси кажется безнадёжной обычно потому, что никто не может сказать, идёт ли дело. Список, который становится короче, это чинит.
#Чего этот метод не делает
Чего это не делает
- Он не восстанавливает, почему что-то было построено именно так. Из одного кода этого не может никто.
- Он не говорит, надо ли переписывать. Он даёт опись и список рисков — то, что является входом для этого решения.
- Он не оценивает качество кода и не ищет уязвимостей.
- Он не устанавливает поведение во время работы. Ничего не запускается, поэтому нагрузка, задержки и то, что видит конкретный пользователь, — вне его.
- Он не видит того, что настроено только вне репозитория: такое всплывает как открытый вопрос, а не как компонент.