Как научиться писать тестируемый и сопровождаемый код

В вакансиях практически всегда есть требование "писать тестируемый и сопровождаемый код", но начинающие программисты далеко не всегда понимают, что это такое. Как начинающему программисту научиться писать качественный код, который будет легко сопровождать и тестировать?

Начнем с понятия сопровождаемости кода

Если кратко, сопровождаемость кода определяет насколько легко и просто посторонний человек может разобраться в том, что творится в предоставленном ему коде.Хорошо сопровождаемый код так же называют «чистым».Чем лучше и чище написан код, тем легче вникнуть в задачу новому сотруднику и тем меньше времени и усилий требуется создателю кода требуется на объяснение, что в нем происходит. В идеале, обращения к создателю быть не должно, все должно быть понятно по самому коду и комментариям.

Как этому научиться?

Первое чем стоит озаботиться — чтение соответствующей литературы. Сейчас доступно огромное количество информации, посвященной этому вопросу: книги (например «Чистый Код» Роберта Мартина) и статьи, дающие пояснения и выжимки из этих книг. Из этих источников можно получить начальные знания необходимые каждому разработчику. Они достаточно просты в освоении и хорошо написаны. Следующий шаг — изучение правил стилистики языка, на котором пишет разработчик. Для каждого языка есть общие правила, которые закладываются его создателями, а крупные фирмы, такие как Google, Yandex, Airbnb, имеют свой свод правил касательно того или иного языка программирования. Полезно изучить какой-либо из предлагаемых наборов правил и придерживаться его. Во-первых, это тренирует дисциплину, во-вторых вероятность что придется работать с кем-то, кто знает и использует такой же свод правил выше чем что-то придуманное самим. И третий шаг — это подробное изучение и следование стилю, используемому в команде, в которой работает разработчик. Скорее всего, в команде разработки, в которую придет начинающий разработчик, уже будет сложившаяся стилистика написания кода. Чтобы не возникало конфликтов и другим коллегам было легко и удобно разбираться в коде, лучше следовать устоявшимся правилам. Если они описаны в документации — это отлично, если документации нет — можно проанализировать код написанный другими сотрудниками и делать так же. Так же в помощь программисту сделано много вспомогательных утилит, которые следят за качеством кода и оповещают о нарушениях, например ESLint для JavaScript, Flake8 для Python и т.д. Конфигурационные файлы для этих утилит легко редактируются и распространяются внутри команды, что позволяет легче внедрять единую стилистику. Со временем использование этих правил и инструментов войдет в привычку и усилия на их соблюдение сведется к нулю.

Теперь перейдем к тестируемости кода

Для чего нужно тестирование и как писать тесты также описано во множестве книг и статей, углубляться в это не имеет смысла. Тестируемый код — это такой код, в котором мы можем убедиться, что любая написанная нами строчка делает именно то, что мы задумали.

Для достижения этого нужно следующее:

1. Код должен быть модульным. Каждый метод должен выполнять одну задачу, принимать определенный набор параметров и выдавать результат определенного типа. Таким образом мы можем легко написать тест под указанное поведение.

2. Не нужно заставлять метод выискивать значения в переданных аргументах. В метод нужно передавать только то, что метод будет использовать. Пример: передача объекта с множеством ключей, в котором метод использует только одно, глубоко зарытое: object.key.anotherKey. Это затрудняет как сопровождение кода, так и написание тестов под него.

3. Не использовать глобальные переменные.Глобальные переменные трудно отслеживать и изменение ее в одной части кода может пагубно сказаться в другой. Так же сами тесты могут перезаписывать их, тем самым влияя на последующие тесты. Исключение составляют только константы, которые не изменяются в процессе работы.

4. Конструктор должен заниматься только инициализацией. Добавление в конструктор каких-либо расчетов может замедлить инициализацию и тем самым тестирование. Выносить часть функционала конструктора в отдельный метод тоже плохая идея, т.к. это затрудняет понимание кода и добавляет необходимость добавлять тесты для вынесенного куска.

5. И напоследок, нужно помнить, что тесты должны быть быстрыми, иначе из полезного инструмента они превращаются в источник непрерывной боли, поэтому важно рефакторить код с учётом того что под него пишутся тесты. Желательно как можно больше сторонних библиотек, которые тестировать не нужно, заменять моками, имитациями этих библиотек, которые без обработки информации отдают заранее подготовленный набор данных. Это помогает существенно ускорить работу тестов, избавиться от зависимости от стороннего кода и тестировать только то что написано разработчиком.

Автор: Никита Гасов, старший разработчик ФармХаб/ Matchflow

1
Начать дискуссию