2. Модульные тесты невозможно написать[92] из-за ошибок в проектировании системы. В этом случае нежелательно кидать все силы на рефакторинг системы и постепенное покрытие кода тестами. Этот процесс может затянуться, а при нехватке опыта у разработчиков рефакторинг может оказаться безуспешным. Лучше будет составить план по рефакторингу и постепенно брать из него задачи на реализацию. Если собственных компетенций не хватает, стоит пригласить внешнего консультанта.
Где можно найти тестовые сценарии?
Перед внесением изменений всю систему надо протестировать. QA-инженеры обязательно спросят про тестовые сценарии и документацию, чтобы сделать полное тестирование текущей версии. Также будет необходимо получить доступ к bug-tracker'у для актуализации известного списка ошибок и задач.
Если тестовых сценариев нет, а документация устарела, то желательно рекомендовать заказчику полное тестирование системы и составление тестовых сценариев. Это необходимо для указания на уже имеющиеся баги и дальнейшего регрессионного тестирования.
Какие требования предъявлялись к системе?
На протяжении разработки унаследованной системы к ней предъявлялся ряд требований. Желательно найти все документы/письма/страницы в описании проекта, где эти требования написаны. Кроме списка задач, которые должна решать система, в требованиях вы можете найти полезные для бизнеса метрики:
1. Максимальное время отклика веб-интерфейса при обычной нагрузке.
2. Максимальное время отклика веб-интерфейса при пиковой нагрузке.
3. Ожидаемая нагрузка на систему.
4. Частота бэкапов.
5. …
Если требования не оформлены, то желательно уточнить их у заказчика и оформить в соответствующие документы. Если вы нашли эти документы, лучше их актуализировать.
Очевидно, что список требований к системе нужно знать до начала внесения первых изменений. Команда QA-инженеров должна провести анализ системы, уточнить, какие из требований в данный момент выполняются, а какие нет. В дальнейшем QA-инженеры должны постоянно проверять систему на соответствие этим требованиям и фиксировать улучшения или ухудшения ситуации.
Общие рекомендации для начала работы
1. Для анализа кода можно прогнать его через различные инструменты аналитики и визуализации кода и архитектуры. После анализа можно исправить самые критичные ошибки, которые выявят инструменты.
2. Заказчик может предложить включить техлида унаследованной системы в новую команду. Это довольно хорошая практика, но надо быть осторожным. Если этот техлид участвовал в разработке неудачной версии, которая провалилась, то он может продолжить реализацию ошибочных идей уже в вашей команде. Согласитесь, трудно признавать своё творение ужасным.
3. Несмотря на это, взять разработчика из предыдущей команды, который находится на проекте на правах консультанта, это хорошая идея. Он может предупреждать о проблемах, когда вы будете придумывать решения, испытанные до вас и оказавшиеся неудачными по ряду причин, специфичных для проекта. Эти знания об истории развития проекта очень пригодятся.
4. Кроме числовых метрик, вам будут нужны люди, способные понять, что система становится лучше или хуже. Скорее всего, это будет кто-то из отделов техподдержки, аналитики, представители бизнеса или один из ключевых пользователей. Используйте любые возможности для закрепления текущего состояния системы, чтобы при каждом изменении делать сравнение.
5. Нужно собрать и занести в таблицу все технологии, фреймворки, ОС, СУБД и т. п., которые используются в системе. Посмотреть их версии, выделить те, которые уже не поддерживаются, и составить план по обновлению. Замена технологий – рискованные и длительные изменения, поэтому к ним нужно готовиться заранее.
6. Если в системе нет тестового сервера (staging, UAT), то желательно его развернуть в самом начале. Это может оказаться трудоёмкой задачей из-за сложности инфраструктуры проекта или больших объёмов данных, необходимых для работы системы.
Стратегия изменения
После проработки вышеперечисленных вопросов вы должны поймете, что за система вам досталось и в каком она состоянии. После этого надо решить, как двигаться дальше.
Набор конкретных тактик и стратегий замены унаследованных систем уже описан в книгах:
1. Мартин Фаулер. Рефакторинг. Улучшение существующего кода при тестировании.
2. Джошуа Кериевски. Рефакторинг с использованием шаблонов.
3. Майкл К. Физерс. Эффективная работа с унаследованным кодом.
В этих книгах разобраны конкретные примеры и даны ответы на вопросы про улучшение кода и его покрытие тестами. Например, что делать с длинным методом, который сложно тестировать? Как разорвать ненужные зависимости? Как убрать зависимость от статического класса? И многое-многое другое. Рекомендую прочитать эти книги, тогда 90% проблем в коде не будут для вас проблемой; вы и ваши инженеры разберётесь с тактическим уровнем работы.
Давайте подробнее рассмотрим основные стратегии, которые можно использовать при работе с унаследованными системами, оценим их плюсы и минусы.
1. Переписать
Вы смотрите на чужой код и дизайн и видите в них множество недочётов. Хочется просто написать правильно с нуля. Почему бы и нет? Один из возможных вариантов развития старой системы – это её перерождение в greenfield-проекте.
Плюсы:
1. Проанализировав унаследованный код, мы узнаем, как не надо делать.
2. Система наверняка будет содержать много хороших решений, которые можно будет взять как есть. Это сэкономит время при создании проекта с нуля.
3. Повышенная мотивация в команде, так как кодовая база будет полностью вашей.
Минусы:
1. Бизнес оплатит создание той же системы во второй раз.
2. Заказчик долго не увидит разницы между тем, что было и как стало. Первый релиз новой системы, который превзойдёт старую по количеству фич, появится нескоро.
3. Если система уже используется, то переписывание старых функций может занять значительное время.
4. Вам придётся поддерживать одновременно и старую и новую системы, пока все пользователи не перейдут на новую.
5. Система может оказаться сложнее, чем вы изначально предполагали, поэтому есть шанс сделать так же плохо, как было, или хуже. Вы не знаете всех нюансов системы и подсистем, которые копились годами.
Рекомендация, когда стоит браться за переписывание всей системы с нуля:
1. Заказчик даёт время и деньги на переписывание старой системы с нуля, а вы, со своей стороны, уверены в своих силах.
2. Систему ещё не начали использовать; возможно, она представляет из себя прототип или proof of concept.
3. Система действительно не работает, пользователи отказываются от неё. Например, у меня был проект, который предыдущая команда писала год[93], но в итоге он просто не соответствовал заявленным характеристикам. Дописывать или рефакторить его не было смысла. Мы проанализировали недочёты и реализовали с учётом предыдущих ошибок новую версию с нуля.
2. Оставляем как было
Вы можете принять решение не трогать то, что уже написано. Новый код будете