Как не сойти с ума, разбирая чужой код: 8 простых шагов
Крутой фреймворк для тех, кому трудно даётся этот чёртов чужой код. Или свой — после пары недель отдыха :)
Кадр: фильм «Миссия невыполнима: Племя изгоев»
Ребекка Тэн (Rebecca Tan)
Об авторе
Воплощает в жизнь проектные решения с помощью программирования.
Переводчик
Олег Щербаков
Мало того, что чтение чужого кода — сложная задача, так она ещё и занимает больше времени, чем создание нового кода. Устраиваетесь на работу — и для начала вас просят изучить кодовую базу. Или дают чужой код и просят пофиксить баги. А может, добавить в него новую фичу. Бывает, что при выполнении подобных задач вы чувствуете себя слегка растерянно и неловко. А зря — кто обвинит вас в том, что вы не можете прочитать чужие мысли?
Впрочем, даже в этом нелёгком деле нужно с чего-то начинать. В этой статье я поделюсь приёмами, которые помогают мне решить проблему.
Шаг 1
Начните с конца
Если код нужен для поискового компонента со сложной системой фильтров на фронтенде, разберитесь, как с этим компонентом взаимодействует пользователь и как он работает в интерфейсе. Попробуйте решить разные задачи и посмотрите, что из этого получится.
Если код нужен для API поиска на бэкенде, который выдаёт результат в разных форматах в зависимости от параметров, начните с поиска допустимых параметров и посмотрите, как будет отличаться ответ API.
Когда закончите экспериментировать, запишите всё, что вы хотите выяснить о реализации кода.
У вас может получиться большой список вопросов, но не пытайтесь, разбирая этот треклятый код, найти ответы сразу на всё — решайте каждый вопрос по отдельности.
Например, вы хотите понять, откуда на фронте берётся текущее поведение объекта, при котором первый фильтр влияет на второй, а второй — на следующий. Или как на бэкенде реализована механика, когда при нажатии на одну родительскую категорию товаров выдаётся вложенная подкатегория, а при нажатии на другие — плоская подкатегория.
Что бы вы ни проверяли, фокусируйтесь на том, чтобы разобраться, как именно достигается результат.
Шаг 2
Открывайте только нужные вам файлы
Когда вы поигрались с конечным результатом, увидели, как код работает в пользовательском интерфейсе, и определили, что именно хотите выяснить, спускайтесь на уровень ниже. Если у репозитория логичная структура с понятными названиями папок и компонентов, вы безошибочно определите все нужные файлы.
Шаг 3
Разберитесь, что делают функции, и протестируйте их методом чёрного ящика
Вы должны чётко понимать, за что отвечает каждая функция. Я предлагаю делать это последовательно:
Посмотрите на юнит-тесты. Мне кажется, это самый простой способ понять, что делает каждая функция, — ведь юнит-тесты чётко описывают ввод-вывод и помогают подтвердить, что каждая функция выполняет именно то, что должна. Но юнит-тесты будут далеко не везде. Если вам не повезло или остались вопросы — переходите ко второму способу.
Просмотрите комментарии к каждой функции. Если над функцией в коде есть комментарии, изучите их. Но не верьте комментариям «на слово» — сравните, совпадает ли описание с тем, что происходит в коде на самом деле. Если же код совсем плохо сопровождался и в нём нет ни комментариев, ни тестов — переходите к третьему способу.
Сделайте логическое предположение и проверьте его. Если разработчик пишет код по правилам, то по имени функции должно быть понятно, что она делает. Функция с именем generateImageUrl обычно (но не всегда) выдаёт URL изображения. Из имени функции можно сделать разумное предположение, затем прочитать код и удостовериться, что она действительно выдаёт URL картинки.
Если же и это не помогло — пишите три письма, как тот сисадмин из анекдота :)
Шаг 4
Сконцентрируйтесь на нужных функциях и игнорируйте все остальные
Раз вы проверяете, как первая панель фильтра влияет на вторую, а вторая — на третью, можете смело пропускать функции, которые на этом этапе неактуальны, например generateImageUrl. Смотрите на те функции, которые относятся к вашей цели, — loadX, loadY, triggerSearch и так далее.
Шаг 5
Отследите последовательность действий в нужных функциях
Чтение кода — это не чтение книги. Нельзя прочитать код от начала до конца, думая, что он выполняется последовательно. Чтобы понять, что за чем следует, воспользуйтесь командой console.log.
- Для функции Х: console.log("I am at loadX").
- Для функции Y: console.log("I am at loadY").
- Для функции Z: console.log("I am at loadZ").
- Для функции triggerSearch: console.log("I am at triggerSearch").
В итоге вы получите примерно такую последовательность: loadX → triggerSearch → loadY → triggerSearch → loadZ → triggerSearch, а может — такую: loadX → loadY → triggerSearch → loadZ → triggerSearch.
Шаг 6
Тщательно проанализируйте каждую функцию и пройдитесь по каждой строке кода
Поняв workflow, изучите код нужных функций построчно. И обязательно логируйте все возможные пути и ветвления (if, else и другие) в пределах функций.
Попробуйте проделать разные преобразования — например, воспользуйтесь методом happy flow или другими методами тестирования потока. Можно, например, начать поиск, не применяя фильтр, а потом применить только второй фильтр и так далее. Затем просмотрите журнал выполнения операций.
Теперь у вас есть представление о том, как работает код.
Шаг 7
Закомментируйте фрагмент кода, если его логика не совсем ясна
Если даже после тщательного вычитывания кода по строкам я сталкиваюсь с чем-то неочевидным, то пытаюсь закомментировать такие строки и смотрю, к чему это приведёт и что сломается.
Возможно, после этого не загрузятся какие-то чекбоксы в выпадающем списке фильтра. Зато теперь вы точно будете знать, какой фрагмент кода отвечает за эту операцию. А сейчас вернитесь к шестому пункту: теперь вы знаете, что делает этот фрагмент кода, а значит, сможете вычитать его более осознанно.
Шаг 8
Напишите дополнительную функцию, чтобы проверить свои догадки
На этом этапе я создаю случайную функцию, например createFilterLabels, которая задействует механики чужого кода. Так можно убедиться, что понял всё правильно.
Заключение
На вопрос, как прокачать скилл чтения чужого кода, часто отвечают — больше практиковаться. Это, конечно, справедливо, но ещё лучше — читать код в правильной последовательности.