что значит legacy код

Что такое легаси в коде

Однажды, Симба, всё это будет твоим

Иногда программисты на вопрос, почему программа работает именно так, отвечают, что это «легаси» и исправить ничего нельзя. Разберёмся, что это значит, насколько это мешает разработке и что делают с легаси-кодом.

Что такое легаси

С английского legacy переводится как «наследие». Легаси-код — это код, который перешёл «по наследству» от предыдущих разработчиков. Чаще всего это происходит так:

👉 Проще говоря, легаси — это код, про который говорят: «Это ещё Михалыч писал 8 лет назад для синхронизации с сервером, он работает, мы его не трогаем, потому что иначе всё сломается». При этом Михалыча в компании давно нет, документации тоже нет, и проще этот код не трогать совсем.

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

Откуда берётся легаси

Причин появления легаси может быть несколько:

Легаси — это не какое-то преступление, а часть жизни любой живой ИТ-компании. Рано или поздно у любого продукта появится легаси. И чем крупнее проект, тем больше его будет. Например, в исходном коде Windows 10 до сих пор остаются фрагменты кода, написанные ещё 20 лет назад для Windows 3.1.

Легаси — это плохо?

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

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

Что значит «поддерживать старый код»?

Например, в старом коде для запроса к серверу идёт сначала адрес, а потом номер запроса. Спустя 10 лет требования сервера изменились, поэтому сначала должен идти запрос, а потом уже адрес. Значит, нужно изменить порядок полей в коде.

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

Что делать с легаси-кодом

Если легаси-код работает и не требует вмешательства и поддержки — то можно пока ничего не делать, пусть работает. Будет время — перепишем на новый фреймворк, а если нет, то и так пока поработает.

А если нужно срочное вмешательство — пахнет бедой. Зовите менеджеров.

Источник

Что такое legacy code?

Не могу найти перевод. Можете объяснить в двух словах что это такое? Что за понятие?

5 ответов 5

Legacy code — тяжелая наследственность : ) Устаревший код, который более не поддерживается и не обновляется, но используется. Второе значение — код от сторонних разработчиков, или из старых версий.

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

Legacy code — код, подпадающий под один или несколько признаков:

Требование «опыт работы с legacy кодом» в вакансии означает, что вам достанется код, написанный лет 10-20 назад давно уволившимися программистами. Не исключено, что он изначально был плохо написан, что требования к проекту менялись уже много раз и каждый раз код правился как придётся в режиме жёсткого дедлайна, что документацию никто не писал и рефакторинг не делал. Поэтому вместо того чтобы писать новый код на прогрессивных технологиях, вам большую часть времени придётся разбираться в старом и править его, ловя потом каскады багов. Добро пожаловать в чудесный мир кровавого энтерпрайза, основного потребителя Java.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками терминология или задайте свой вопрос.

Связанные

Похожие

Подписаться на ленту

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2021 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2021.11.10.40696

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Источник

Укрощая зверя: legacy-код, тесты и вы

Legacy-код — это «старый» код, возраст которого может быть как 2 месяца, так и 10 лет. Часто его писали разработчики, о которых в компании смутно помнят. Возможно, их вообще не было, а legacy-код родился вместе со Вселенной во время Большого Взрыва. С тех пор требования к нему менялись много раз, код правили в режиме «нужно было еще вчера», а документацию никто не писал, как и тесты. Legacy-код запутан и хрупок, в нем не видно ни начала, ни конца. Как к нему подступиться?


Здесь и далее кадры из сериала «Рик и Морти». Авторы Джастин Ройланд и Дэн Хармон.

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

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

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

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

Чего здесь не будет:

Что такое legacy-код

Определений много. Я считаю, что это «достаточно старый» код возрастом от 2 месяцев до 10 лет. Legacy-код запутан и хрупок, но как гигантский змей пожирает свой хвост.

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

Возможно ли побороть этого зверя? Да, но нужна подготовка.

Подготовка

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

«Зачем я это делаю?» Серьёзно, зачем? Ведь варианта всего два.

«Знаю ли я, что делаю?» Если вы писали тесты, то знаете. Если нет, то прежде чем бросаться на монстра, овладейте азами: напишите 3-4 теста, покройте небольшую часть кода, набейте руку и почувствуйте силу.

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

Когда вы ответите на все вопросы утвердительно — переходите к следующему этапу.

Разведка местности

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

Составьте схему зависимостей. Ни один проект не живет в вакууме. Базы данных, внешние сервисы, библиотеки — все это может использоваться в проекте.

Что сделано до вас? Возможно, вы не первый, кто боролся со зверем. Изучите наработки «предков», которые сгорели и ушли с проекта.

После разведки переходим к боевым действиям.

Борьба с организацией

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

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

Руководитель не против ваших начинаний. Он против того, чтобы вы кидались на проект с криками: «Тесты! Тесты! Тесты!». Если будете так делать, он посмотрит на вас как на человека, который тратит его время и тормозит остальных.

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

Тест не стоит подавать так:

Свои идеи надо продвигать так:

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

Произнося «оптимизация, деньги, экономия времени», вы говорите на языке менеджера. Когда он слышит эти слова, то проникается идеей. Он видит в вас не очередного оголтелого программиста, увлеченного свежей технологией, а человека, который заинтересован в улучшении продукта. Все ваши идеи он не одобрит сразу, но высока вероятность, что предложит сделать Proof Of Concept.

Читайте также:  что делать если потерял очки для зрения

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

Не обещайте много. Для менеджера важны цифры: какие результаты, сроки и какими силами. Но менеджер — существо жадное до результатов. Не обещайте слишком много с самого начала. Если пообещаете решить все проблемы сразу, менеджер пойдет с этим к начальству. Начальство скажет: «Замечательно!», но сократит финансирование и срежет сроки в надежде, что мы сдадим систему намного раньше.

Когда договоримся с менеджером, переходим к тем, с кем приходится работать каждый день.

Коллеги

Не любят перемены. Типичный коллега на типичном legacy-проекте — это человек, который потерял веру в жизнь и будущее. Он не склонен к изменениям и смирился с судьбой: «Я здесь навсегда, выхода из болота нет». Проблема в том, что вы начинаете мутить воду в этом болоте. Вы требуете, чтобы он писал и запускал какие-то тесты, а он хочет выполнить свою работы, закрыть задачу и уйти домой.

Заинтересуйте коллег пользой — объясните, почему им станет лучше. Например, они постоянно тратят время и силы, оставаясь после работы, чтобы залечить какие-то баги. Надавите на это: «Если не деплоить на продакшн сломанный код, не придется тратить время на его починку. Напишем тесты, будем вылавливать такой код, меньше будет ломаться».

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

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

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

Разделяйте и властвуйте. Подойдите к одному из коллег за обедом или в уголке и скажите: «Вся команда уже подписалась, ты один тормозишь процесс. Может быть, мы найдем общий язык?»

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

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

Борьба с машиной

Это хитросплетение кода, которое называется продуктом. Начнем с азов.

Разберите хлам. Тестировать необходимо так, чтобы при минимальном воздействии на систему получать проверяемый результат. Но любая legacy-система полна данными: они добавлялись годами с момента запуска и влияют на поведение системы. Поэтому необходимо тестировать «с чистого листа».

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

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

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

Начните с «главного объекта». Чтобы разобраться с лесом зависимостей, попробуйте задуматься о том, какой объект главный. Например, для системы учета склада главный объект — «ящик». С ним связан объект «полка», а с «полкой» — объект «ряд».

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

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

Переходим к тестированию. Для запутанных старых продуктов хорошая стратегия — это smoke-тесты.

Smoke-тесты

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

В информационных системах концепция smoke-тестов достаточно простая. Представим веб-сервис, у него есть endpoint. Попробуем отправить ему GET-запрос без параметров. Если по какой-то причине продукт неожиданно сломался (ошибка 500), то что-то пошло не так.

Smoke-тест — хорошее начало. Это тест, который проверяет некоторую функциональность и дает понять, что система работает или сломана. Даже простой запрос к самому простому endpoint уже затрагивает больше 1% кода. Такими небольшими тестами готовим плацдарм для дальнейшего тестирования.

Smoke-тест вскрывает множество проблем. Возможно, что за все время функционирования сервиса никто не догадался отправить запрос без параметров.

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

Функциональные тесты

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

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

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

Функциональные тесты — средство, а не цель.

На иглу функциональных тестов легко подсесть: «Я же тестирую реальный функционал! Это то, с чем сталкиваются пользователи».

Функциональный тест задействует большие куски кода, которые могут взаимодействовать с гигантскими объемами данных. Поэтому 3-4 функциональных теста — это хорошо, 10 хуже, а тысячи тестов, проходящие 9 часов, — перебор. К сожалению, такое тоже бывает.

После функциональных тестов беритесь за unit-тесты. Но о них я не буду рассказывать — вы и так все знаете.

Мы прошлись по азам машинного тестирования и возвращаемся к основной теме. Коллеги и менеджер — не самый страшный враг в бою с legacy. Самый страшный враг — вы сами.

Борьба с собой

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

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

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

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

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

Теперь обидное, горькое и вечное.

Напутствия

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

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

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

«Автобусное» число не шутка. Вы не сможете всегда тащить проект на себе. Каждый может выгореть, уйти в отпуск или уволиться. Поэтому передавайте коллегам ваши знания и ответственность, которая необходима, чтобы справиться без вас. Это поможет избежать неприятных звонков, когда вы расслабились на пляже, а CI снова красный.

Улучшайте механизмы тестирования. Многих проблем можно избежать просто потому, что медленные тесты неожиданно стали быстрыми. Раньше они занимали 20 строк кода, а теперь одну. Вы этого не замечали, потому что один раз что-то написали и забыли: «Работает — не трогай!» Но это правило не всегда применимо.

Читайте также:  что делать со старыми календарями с изображением святых

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

Не хочу, чтобы вы оказались этим человеком. Не превращайтесь в ограничивающий фактор.

27 марта на Moscow Python Conf++ Кирилл расскажет о технической стороне рефакторинга кода с Python 2 на Python 3 — что может быть актуальнее в 2020 году.

Что еще нас ждёт на конференции, можно посмотреть в статье с обзором программы или в соцсетях (fb, vk, twitter) и telegram-канале мероприятия. Скоро увидимся!

Источник

О Legacy-коде без максимализма: что делать

Представьте, что вам дали задачу поправить часть кода. В голове возникнет много мыслей. Кто его написал? Когда? А может он — legacy? Где документация? Давайте попробуем разобраться с «наследием» основательно и со всех сторон. Поможет нам в этом вопросе Андрей Солнцев @asolntsev (http://asolntsev.github.io/), разработчик из таллинской компании Codeborne. Начнём.

— Андрей, вы знакомы с трудами Michael Feathers, например, «Working Effectively with Legacy Code»? В книге акцентируется внимание на важности тестирования и выделяется одно из ключевых отличий legacy от не legacy-кода — это наличие тестов. Вы согласны с этим мнением?

Я очень люблю книгу Robert C. Martin «Clean Code» («Чистый код»). Это для меня настольная библия. Категорически всем советую. Кстати, его блог тоже великолепен.

— С чистым кодом понятно. А при чём тут TDD? Код без багов — это ведь не то же самое, что хороший код?

Все думают, что TDD — это про тесты, а значит, это скучно.
Ерунда!
TDD — это про разработку (test driven DEVELOPMENT). Это способ создания кода таким, чтобы он был НЕ legacy. Таким, чтобы его было возможно поддерживать: отлаживать, исправлять, рефакторить, дорабатывать. На данный момент это единственный известный человечеству способ. Всё остальное — от лукавого, не дайте себя обмануть.

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

TDD нужен вовсе не для того, чтобы находить баги.
Тест — это первое использование твоего кода. Шерлок Холмс говорил: «Сначала собираешь факты, а уж потом выстраиваешь теорию. Иначе ты подсознательно начнёшь подтасовывать факты под свою теорию». Ты даже сам не заметишь, как это случится! Так же и с кодом: когда ты пишешь тест до кода, ты вынужден подумать о том, как его удобнее использовать, как назвать класс, метод; какие параметры передать. А если сначала написать код, то начнёшь подтасовывать тесты под него. В итоге доля тестов окажется слишком сложна, другая — трудна для исправления, а часть останется ненаписанной. И вот перед нами legacy-код собственной персоной!

— В продолжение разговора о тестировании — на ваш взгляд, какие тесты корректны и в каких ситуациях, например, юнит-тесты?

Начнём с юнит-тестов. Они необходимы в каждом проекте, тут без вариантов.

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

— А каким должно быть покрытие кода тестами? Достаточно ли 70%? Как не переборщить с «диагностикой» проекта?

Безусловно, нужно стремиться к максимальному покрытию. Все эти разговоры про 30% или 70% покрытие — от непонимания. Надо стремиться к 100% (хоть это и недостижимый предел).

Всем известно, что 100% покрытие невозможно, но не все правильно понимают, почему. Вовсе не потому, что «надо тестировать только критичное», «незачем тестировать геттеры» и «у нас есть дела поважнее».

Полное покрытие невозможно потому, что в любой системе код общается с внешним миром. Отрисовка пикселей на экране, управление устройствами и так далее — для этого кода юнит-тесты невозможны, это нужно проверять своими глазами. Наш профессионализм состоит в том, чтобы этот слой «общения с внешним миром» держать максимально тонким, и всю логику выносить из него. И вот её-то нужно тестировать.

Грубо говоря, если просроченные кредиты нужно подсвечивать красным, то логику «какие просроченные» нужно выносить в отдельный метод с юнит-тестами, а «подсвечивание» — отдельно. Ну там, css или как там ещё. И TDD стимулирует разделять эти слои, вот что замечательно. В этом его сила! А тесты — это лишь побочный эффект.

— Сколько времени нужно уделить созданию юнит-тестов, и на каком этапе проекта они играют ключевую роль?

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

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

— Как у вас выглядит процесс написания тестов?

Ты пишешь красный тест 10 минут, делаешь его зелёным 10 минут, рефакторишь 10 минут. Никто, конечно, не замеряет это время точно — иногда это 5:30:0, а иногда 180:5:60. Неважно. Важно, что ты с таким же темпом, с предсказуемой скоростью сможешь менять код и через месяц, и через год. Постоянная скорость в долгосрочной перспективе гораздо важнее высокой мгновенной скорости на старте.

Советую вот это видео, где понятно и весело показано TDD: «Пацан накодил — пацан протестил!» Не пугайтесь длины, там про юнит-тесты только первые 30 минут.

— Андрей, если TDD так полезен, почему его так мало используют?

Всё просто. TDD — это дисциплина. Это как спорт: все знают, что спорт полезен, но ленятся. Самые честные признают, что им лень, остальные находят отговорки, а особо отъявленные начинают придумывать объяснения, почему спорт, оказывается, даже вреден. Так же и с TDD.

Забавная разница в том, что люди, лежащие на диванах, не называют себя спортсменами. Тут всё честно. А кодеры не пишут тестов и при этом называют себя разработчиками. Невероятно, правда? Но заканчивается это всегда одинаково. Спортсмен, пропускающий тренировки, быстро проигрывает соревнования. Так же и код, написанный не через тесты, моментально становится legacy. Тут всё честно.

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

TDD — это теорема, которую надо доказывать каждый день.

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

Я вам расскажу одну байку. Мой брат работал в химической лаборатории тартуского университета. К ним приехала делегация откуда-то из Европы. Им всё показали: новые помещения, новое оборудование, все дела. И тут они обратили внимание на старый советский агрегат где-то в углу. Делегаты сделали круглые глаза и спросили, мол, а что ж вы его не выкинете? На что последовал ответ: «Не поверите! Потому, что он… РАБОТАЕТ!»

Тут нет единого ответа. Можно ежедневно обновлять все зависимости и относиться к этому как к необходимой гигиене. Можно даже попросить Maven или Gradle делать это автоматически. А можно сделать fork оригинальной библиотеки и сидеть двадцать лет на старой версии. Пожалуй, это зависит от зависимостей. Если я сильно завишу от Selenium, использую новые фичи, то я его часто обновляю. Если я никак не завишу от новых фич log4j, я сижу на древней версии. Всё ж работает.

Чем старше я становлюсь, тем больше склоняюсь к тому, что не стоит гнаться за обновлениями. Новый Play framework оказался не лучше, чем Struts2. Maven не лучше (и даже хуже), чем Ant. TestNG однозначно хуже JUnit (а ведь «new generation» в названии!). Hibernate3 был сложнее, чем Hibernate 2. Spring boot сложнее, чем Spring MVC. А ведь лет 10 прошло! Про новые JavaScript библиотеки я уж молчу.

Так что не всё то новьё, что обмазано солидолом.

— В вашей практике встречались подобные ситуации (дополнительно к предыдущему вопросу)? Как вы выходили из подобных ситуаций? Какой стратегии вы придерживаетесь, переписать всё (часто используется термин — greenfield) или сделать рефакторинг?

Конечно, встречались.
Да это просто вопрос организации. Если приспичило обновить какую-то зависимость, которая обратно несовместима, надо просто выделить для этого время, договориться с командой, чтобы ни у кого ничего срочного в этот момент не было, да и отрефакторить. Многие начнут плакаться: «Нам не дают на это времени». Ну не знаю, может, не так уж нужно обновляться? Было бы критично — дали бы время.

Насчёт greenfield я довольно скептично настроен.
Конечно, плох тот солдат, который не мечтает всё переписать с нуля.
Но я за всю свою жизнь ни разу не видел, чтобы систему переписали с нуля и стало лучше. Обычно получается так же или хуже. Переписывальщик начинает с большим азартом, потом сталкивается с одной проблемой, с другой; понимает, что уже не успевает… Оставляет технический долг в одном месте, в другом — и вот у вас уже legacy-код в новом проекте, хотя ещё и половины-то не написано.

Читайте также:  что такое авермектиновые препараты

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

— Может быть, существует проверенный «гибридный» вариант?

Гибридный вариант есть. Можно переписать с нуля какую-то часть системы, самую легасисястую. Причём оставить старый вариант тоже, так чтобы они работали параллельно. И переводить на новый вариант все куски системы постепенно, один за одним. Да, это требует терпения и времени, но это единственный способ. Неохота? Тогда вообще не начинай. Торопыгам тут не место.

— Как вы отличаете плохой, попадающий под определение legacy-код, от максимально «разогнанного»? Стоит ли гнаться за производительностью в ущерб будущей поддержке?

Разогнанный код — это типа десяток строк заумных операций с байтиками, чтобы работало быстрее? Я думаю, что такой код в реальной жизни из разряда баек. Все думают, что только крутые перцы так умеют, и тоже хотят научиться. В прикладном программировании это почти никогда не нужно.
А если всё-таки нужно, то никто не мешает сделать этот код и «разогнанным», и хорошо читаемым, и протестированным. Давай, ты же профессионал. Сначала напиши юнит-тесты, а потом разгоняй. Не осилил юнит-тесты? Нечего и разгонять — нос не дорос.

— Как вы думаете, legacy-код может тормозить развитие всей системы?

Конечно, может! И тормозит!
Собственно, это самое главное, что обычно тормозит. Каждое следующее изменение вносить всё сложнее, риск что-то сломать всё больше.

— Вы можете дать совет о необходимости избавления от ужасного и медленного «монстра» в проекте, если его увидите? Как на это реагировали (если такие ситуации происходили)? Изменения провели к положительно эффекту (если такие ситуации происходили)?

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

Но тут важно не уйти слишком далеко. Надо сделать чуть чище поляну, а не перепахать весь лес без оглядки. Это я видел (и делал) много раз: очередная горячая голова решает всё переписать, уходит на несколько часов/дней в жёсткий рефакторинг, вязнет, тонет и в итоге делает только хуже. В лучшем случае откатывает свои изменения и отделывается лёгкой потерей времени.

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

НО.
Чинить legacy-код — то же самое, что рубить голову гидре. Вырастет три новых. И ещё окажется, что та первая не до конца отрубилась, и мало того, что тебя укусила, так ещё из неё вылилось что-то липкое и зелёное и запачкало всё вокруг. А потом пришёл менеджер и сказал: «Нафига ты вообще это трогал, работало же?»

Поэтому если вы чините legacy-код, всерьёз надеясь улучшить что-то в проекте — удачи, здоровья и хорошего настроения. Что-то где-то подпилите, но по большому счёту ничего не изменится. Это тот самый случай, когда надо лечить на симптом, а болезнь. Не прыщик выдавливать, а идти на улицу бегать. Разберитесь, в чём на самом деле проблема. Почему у вас в команде пишут плохой код? Люди слишком спешат? Не понимают архитектуру? Конфликтуют между собой? Не умеют договариваться? Всё это я встречал в реальных проектах с умными взрослыми людьми. И вот это надо лечить, а не переменные переименовывать.

— Вы придерживаетесь мнения, что красота кода — это ещё не показатель legacy-статуса?

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

— Можно ли утверждать, что нарушение стандартного соглашения по оформлению кода — это legacy?

Стандартные соглашения полезны, но не стоит их переоценивать. Любые соглашения о коде становятся legacy ещё быстрее, чем сам код. Их же никто никогда не читает. У лебедя, рака и щуки были верёвки стандартной длины — и сильно им это помогло?

И не стоит ради них тратить свои силы. Настройте один раз IDE всех участников проекта, чтобы она сама форматировала код как надо, и больше не думайте об этом.

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

Конечно, менялось. Вначале я, как и все, думал, что плохой код пишут индусы и тупые коллеги. Или «джуниоры». Но всё не так просто.

Я не люблю слишком простые объяснения. Слишком легко свалить всё на «тех придурков». А legacy-код возникает и у самых умных людей, и в самых лучших проектах.

О да. О да!
Вот я тут вещаю, такой умный, про legacy-код, а у меня самого есть open-source проект Selenide, который legacy-кодом зарос по самое не моргну. Нет, он отлично работает, пользователи довольны, но мне его менять со временем всё сложнее. Есть тикеты, которые висят уже пару лет, потому что мне реально сложно их сделать. Поменяешь в одном месте — ломается в другом. Да, там есть интеграционные тесты, благодаря которым я не боюсь что-то сломать. Но от них нет помощи в том смысле, что менять-то код не получается.

Однажды я понял: ключевая проблема в том, что в этом проекте я изначально не писал юнит-тесты. Казалось, зачем тесты, если эта библиотека сама предназначены для написания тестов? Она и так будет протестирована вдоль и поперёк. А оказалось — вон оно что, Михалыч! Юнит-тесты нужны для избежания legacy-кода.

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

—Как вам кажется, в каких оттенках стоит воспринимать legacy-код? В каких случаях оправдано его наличие?

У меня есть простой рецепт. Отвлекитесь на секунду от лямбд и скобочек и представьте себя на месте клиента. Это здорово прочищает мозги.

Как клиент, привозите вы свою машину в автосервис, просите посмотреть, что там стучит.
А вам механик говорит: «Я поменял то, что стучало, но у вас ещё и топливный насос дырявый, — будем менять?» Это хороший механик. Плохой механик поменял бы насос сразу. А хороший механик сообщил о проблеме и расписал варианты: можно заменить сейчас — будет стоить столько-то. Можно не менять, тогда зиму ещё доездите, но потом и все шланги полетят — выйдет втрое дороже. И вы сами как клиент решаете. Один скажет: чего два раза ходить, меняй всё! Другой скажет: «Сейчас денег нет, а мне ещё зимнюю резину нужно. Давай до весны подождём».

А знаете, что сделает самый худший механик? Промолчит. Сделает только то, что просили.

А как ведём себя мы все с вами, дорогие программисты?
Те самые горячие головы, что норовят тут же всё порефакторить — они как кто? Правильно, как плохой механик. А те «повзрослевшие», что решают оставить всё как есть? Увы, как самый худший. А что должен сделать с legacy-кодом хороший механик? А как часто мы так делаем? Вот и думайте.

— Андрей, TDD, юнит-тесты — всё это звучит хорошо, но вы же понимаете, что для 99% наших читателей это неподъёмно в силу самых разных причин, часто от них не зависящих. А можете напоследок дать простой рецепт, как бороться с legacy-кодом?

Вы хотите рецепт, но когда я даю рецепт — проверенный, надёжный, вы говорите, что у вас нет на это времени. И продолжаете жаловаться на legacy-код. Вы что же от меня ждёте, красной пилюли — выпил, и ты уже в матрице? Не будет пилюли.

Люди как люди. Любят торопиться, но ведь это всегда было… Человечество любит простые рецепты… В общем, напоминают прежних… микросервисный вопрос только испортил их…

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

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

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

Спасибо за внимание и за терпение!

Больше интересных докладов, технических, хардкорных, вы найдете в программе Joker 2016. Если вы работаете с легаси, вам стоит обратить внимание на следующие доклады:

Источник

Строительный портал