Статьи

Технический долг: спасение устаревшего кода путем рефакторинга

Как вы можете получить контроль над устаревшей кодовой базой и вывести ее на новый уровень зрелости? В этом посте Jeroen обобщает уроки, извлеченные из многолетней работы над большим унаследованным веб-приложением. Эта статья была первоначально опубликована Intracto .


Устаревший код может быть сохранен путем рефакторинга

У меня есть хорошие новости для вас! Белки сажают тысячи новых деревьев каждый год, просто забывая, где они оставляют свои желуди. Также: ваш проект можно сохранить .

Неважно, насколько ужасно запутался старый кодовый беспорядок, с которым ваш босс смело вызвался помочь вам, выход из грязи есть. По пути будут повороты, а за каждым другим деревом будет чудовище. Но, шаг за шагом, вы попадете туда.

Не бойся зла

Справедливо, вы не просили этот ужасный квест. Покрытый кровью знак «Здесь будут драконы» у входа в болото кодов побуждает к сильным побуждениям заболеть в течение следующих нескольких лет. На первый взгляд, вам лучше сначала немного пообедать и, возможно, неторопливо прогуляться по лугу после этого, чем быть окаменелым крестьянином, чтобы избавить указанное болото от своих монстров.

Мрачный лес

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

Запретите некоторые радикальные меры, вы не можете изменить эти основные факты. Однако вы можете превратить болото в великолепный луг с одним грязным участком, где живут коровы!

Технический долг: как это получилось?

Когда вы ткнете и подталкиваете область рядом с предупреждающим знаком палкой, вы можете задаться вопросом: с какой стати кто-то мог допустить, чтобы это произошло? Кто-то, должно быть, видел это, конечно? Были ли люди, написавшие этот код , некомпетентными?

Возможно. Но не более, чем кто-либо еще. Когда толчок приходит к толчку, какими бы уверенными ни казались люди, никто больше не знает, что они делают.

Некомпетентность далека от всей истории. Принцип работы здесь обычно упоминается с метафорой: технический долг .

Код рака

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

И так, постепенно, код проекта поврежден. Никто не заботится об этом, пока они не должны касаться этого. Но в конце концов кто-то должен, и, вероятно, это будет ты.

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

вечеринка болотный цвет

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

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

Убедить клиента

Герцог, являясь владельцем болота, должен немного рассказать о том, каких монстров вам следует добавить. Всегда есть новые функции, которые ваш клиент хочет реализовать, срок для каждой из них — на прошлой неделе, и вы должны чувствовать себя некомпетентным, потому что не завершили все из них две недели назад. Так что вам, вероятно, придется немного объяснить, чтобы убедить его, что ему нужно позволить вам восстановить то, что он уже ощущает как находящийся в его распоряжении.

Это критическая точка. Если вам не удастся заставить своего клиента начать платить то, что он должен, технический долг вырастет до такой степени, что он рухнет. Вы будете парнем, оставленным в руинах, привлеченным к ответственности.

нанесение увечья

В конце концов, ваш клиент и вы хотите в точности одно и то же : иметь веселую и безболезненную работу, которая зарабатывает всем вовлеченным в жизнь. Это следует из стабильного проекта, построенного из кода, который вы можете изменить, не обрушиваясь на вас.

Борись за свою свободу

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

  • Объясните, что означает технический долг и как он замедляет развитие, если оно становится слишком высоким. Заказчик должен понять, во что это обойдется: время, потраченное на поиск ошибок, их исправление и создание новых, недостаточно времени для добавления функций и развития своего бизнеса.
  • Рефакторинг с четкими краткосрочными целями . Вы можете добавить новую функцию через неделю, или вы можете провести рефакторинг в течение недели и добавить ее через день, с возможностью очень легко добавлять подобные функции в будущем. Покажите, как второй вариант будет дороже в краткосрочной перспективе, но бесконечно дешевле в долгосрочной перспективе.
  • Укажите, что вы хотите лучшего для себя и своего клиента , и что эти две проблемы действительно одно и то же.

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

Новое болото не делают

Вы можете оправиться от огромного беспорядка; не заменяйте его новым . Гринфилд переписывает редко удавалось; большинство никогда не выпускают.

Когда вы наконец убедите герцога, что люди, которые постоянно прогуливаются по его болоту, больше не выходят, он может захотеть создать новую версию. У вас может возникнуть соблазн подчиниться, начав заново, используя блестящие новые инструменты, убедившись, что все будет лучше, когда вы закончите. Не.

осторожность

Основными рисками переписывания, на мой взгляд, являются:

  • Переключатель большой красной кнопки : новый код никогда ранее не запускался и гарантированно взорвется при первом использовании.
  • Миграция данных : экспорт и импорт данных из старой системы при одновременном отслеживании поступающих данных в реальном времени, скорее всего, пойдет не так.
  • Ошибки старого и нового : при переписывании кода вы будете создавать ошибки, воссоздавать старые ошибки, пропускать тонкости и неявные функции … Часто эти проблемы возникают в тех частях системы, которые изначально не были проблемными. Вы теряете много времени, не добавляя никакой ценности бизнесу своего клиента.
  • В ногу с бизнесом : в течение долгого времени, когда вы работаете над новым проектом, старый проект также должен развиваться вместе с бизнес-потребностями. Новый код должен будет перестроить старые функции и добавлять новые функции, постоянно добавляемые в старый проект.

Так что не начинай сначала. Улучшите то, что у вас есть.

Сделать проблемы видимыми

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

Эти неприятности разрушают ваш проект , независимо от того, замечаете вы его или нет. Вы должны столкнуться с ними, чтобы избавиться от них. Вы должны быть в состоянии увидеть, что происходит в любой момент времени.

  • Визуализируйте ошибки : уделите некоторое время каждую неделю, чтобы исправить некоторые ошибки, которые происходят чаще всего. В конце концов график станет ровным, и мы надеемся победить вас.
  • Следите за своей средой : это важно для диагностики узких мест и надвигающихся кризисов (см. Следующий параграф).

ошибки

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

Бой, что болит больше всего

Далее, жизненно важно иметь представление о системе, какой она должна быть в идеальном мире, — мысленную картину вашей конечной поляны, направляющую каждое ваше движение:

идеальный луг

Поцарапайте его в грязи, чтобы не забыть. Делая небольшие промежуточные шаги в направлении неба , вы в конечном итоге окажетесь через забор.

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

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

Этот код мой

Решение проблем, которые важны, важно, но это не означает, что детали не имеют значения . На самом деле, они, вероятно, так же важны.

болотный кемпинг

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

Чтобы достичь этого, отношение это все. Стремитесь к чистому коду.

  • Вы должны быть осторожны : код принадлежит вам, и любой, кто прикоснется к нему, должен ответить вам. Неряшливость и невнимательность не терпят.
  • Всей команде нужно заботиться : как бы вы ни старались очистить проект, если кто-то отменит вашу тяжелую работу позади вас, вы не получите ничего.
  • Дисциплина имеет важное значение : как только вы ( или любой член команды! ) Начнете позволять вещам скользить, вам будет почти невозможно сбежать.
  • Продолжайте делать маленькие шаги : в правильном направлении, конечно. Прогресс гораздо важнее, чем достижение совершенства.
  • Небольшие победы генерируют импульс : вы начнете видеть действительно хорошие участки кода, побуждающие вас также очистить соседние участки.

Построить библиотеку

Хорошим показателем цивилизации является количество библиотек на квадратный метр. Поэтому, чтобы привнести цивилизованность в ваш проект, это кажется отличным подходом.

библиотека

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

Несомненно, код, который вы должны спасти, будет делать все неправильно. Он будет каким-то образом полностью игнорировать и обходить любые стандарты или лучшие практики, которые облегчат вашу жизнь разработчика. Никто не исправит это за вас, есть только один выход: начать следовать этим правилам и стандартам в вашем новом коде .

Сделайте доступными стандартные компоненты или модули и начните их использовать. У вас будет код, использующий старые или нестандартные способы выполнения задач, но это не значит, что вы не сможете создать новый материал надлежащим образом.

Рефакторинг с использованием ваших новых инструментов

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

Часто код был бы вполне приемлемым, если бы не многочисленные зависимости, разбросанные повсюду (например, доступ к сеансу, модули или службы, к которым обращались на месте). Хороший способ справиться с этим — вытолкнуть их из метода или функции, в которой находится код, чтобы они входили через параметры метода. Таким образом, вы делаете этот фрагмент кода автономным, и становится возможным его перемещать или разбивать дальше.

И как только код самодостаточен, вы можете проверить его .

Укрепление доверия: тестирование

Буйный огр, бродящий по грязи, может нанести больше урона, чем буйный огр в цепях. Отличным способом получить некоторый контроль над вашей системой является попытка наложить цепи на наиболее критичные части, которые потенциально могут нанести наибольший ущерб — тесты, предпочтительно автоматизированные, которые выполняются при каждой сборке.

цепь

Чем больше автоматических тестов вы должны проверять поведение системы, тем больше уверенности вы можете иметь при изменении ситуации. Потому что, если что-то сломается, ваши тесты покажут вам, что что-то не так, поэтому вы можете исправить это, прежде чем проблема попадет в производственную среду .

Тесты высокого уровня

Один из способов начать тестирование вашей системы — добавить приемочные тесты для критических сценариев в вашей системе. Для обычной системы электронной коммерции это определенно будет включать процесс оформления заказа: если не поступит ни одного заказа, вы потеряете деньги. Если поступают заказы, но есть проблема с их обработкой, это то, что вы можете исправить, не заметив ни одного клиента. С такими тестами вы можете защитить себя от непреднамеренного появления серьезных проблем.

Низкоуровневые тесты

На более низком уровне вы можете применять модульные тесты . При использовании подхода небольших шагов по выталкиванию зависимостей из ваших методов один за другим, результатом будет код, который имеет четкий ввод и четкий вывод . В этой ситуации становится возможным охватить функциональность этого кода с помощью модульных тестов. Вы определяете набор входных данных и объявляете выходные данные, которые, как вы ожидаете, будет генерировать ваш код, а ваш набор тестов будет следить за тем, чтобы часть кода продолжала работать так, как ожидалось .

Не проверяй все

Тестирование каждой отдельной строки кода в системе экономически нецелесообразно и не нужно. В принципе, было бы здорово быть абсолютно уверенным в каждом аспекте вашей системы, но стоимость создания всего тестируемого, написания тестов и сопровождения тестов в какой-то момент перевесит преимущества. По моему опыту, ваше время лучше всего потратить на написание тестов для нетривиальной бизнес-логики и частей системы, которые могут привести к хаосу в случае их неисправности (даже если код на самом деле прост).

Таким образом, вы получите самых опасных монстров в цепях, и болото станет для него более безопасным и предсказуемым местом.

Изолировать и заменить

Полезной техникой, которая объединяет практически все перечисленные выше стратегические схемы, является старый метод «изолировать и заменить».

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

  • Изолируйте грязную часть , поместите ее в отдельный метод или класс.
  • Выдвиньте зависимости, чтобы они вошли как параметры.
  • Разделить логику от побочных эффектов (например, сохранение в БД), используя метод небольших шагов.
  • Выделите логику отдельным методом.
  • Добавьте модульные тесты, которые охватывают поведение логики.
  • Переписать логику с нуля. Если он проходит тесты, он должен быть, по крайней мере, близок к поведению старой версии.
  • Запустите старую и новую версию логики бок о бок в производственной среде. Старая версия все еще используется.
  • Зарегистрируйте различия в выводе между новой и старой версией.
  • Контролировать журналы прилежно. Всякий раз, когда обнаруживается разница, добавьте новый модульный тест для этого случая и исправьте новую версию, чтобы пройти новый случай.
  • Повторяйте до тех пор, пока старая и новая версии не будут последовательно согласовываться друг с другом.
  • Переключите старую версию логики с новой верой с уверенностью.

Эта техника позволяет вам менять мотор автомобиля без поломки или даже замечая, что его внутренние детали были заменены.

Убедить себя

Мышление и инструменты, изложенные выше, оказались для меня успешным способом управления системой на грани краха от катастрофы.

дракон инь ян

В то время как изначально я не решался посвятить свои усилия постоянному труду, чтобы справиться с долгосрочным наследием, я теперь вижу множество способов, которыми он помог мне стать лучшим разработчиком :

  • Научитесь распознавать плохой код : вы учитесь видеть, что плохо, потому что именно на это вам приходится тратить больше всего времени. Шаблоны, которые вы видите здесь, не смущают вас, когда вы работаете над новым проектом, потому что вы знаете, как это повредит вам в будущем.
  • Возвращаясь к основам : в моем случае, каждый аспект системы должен был быть подвергнут сомнению и переоценке. Ничто не является святым, и вы получите высокую оценку многих проблем, с которыми сталкиваются современные фреймворки.
  • Вы эволюционируете вместе с системой : вы видите новые проблемы, возникающие по мере роста системы вашего обслуживания. Таким образом, вы узнаете, с какими узкими местами вам нужно справиться, поскольку все больше и больше людей используют вашу работу, и вам нужно расширяться, чтобы быть в курсе всех событий.
  • Люди постоянно генерируют новое блестящее наследие : старательно, быстрее, чем они создают в наших океанах мусорные пояса, знание того, как заставить это работать, — это хороший навык, который нужно иметь.
  • Удовольствие и награда : особенно оглядываясь на дорогу, пройденную хорошо, и осознание системы, которая у вас есть сегодня, совсем не похоже на систему, которую вы впервые встретили много лет назад, вызывает настоящее чувство выполненного долга.

луговая корова

Чтобы закрыть этот существенный (или длительный, по крайней мере) пост

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

Эпилог:

Через несколько лет вы прогуляетесь по лугу. На горизонте вы можете увидеть герцога, заменяющего старый знак «Здесь быть драконами» рекламой пива.

У него огромная улыбка на лице.