Как работать с легаси кодом

Добавил пользователь Владимир З.
Обновлено: 04.10.2024

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

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

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

  1. Команда делает продукт, внутри много разных возможностей.
  2. Часть функций со временем оптимизируется, а часть остаётся неизменной в виде старого кода, потому что и так работает.
  3. Некоторое время спустя в команде не остаётся тех, кто писал старый код.
  4. Текущая команда не знает, почему старый код написан именно так.
  5. В этих кусках сложно что-то поменять или разобраться, потому что всё остальное написано уже по-другому.
  6. Этот старый код, который сложно поддерживать и сложно разбираться — это и есть легаси.

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

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

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

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

  • команда перешла на другой фреймворк, но части программы остались на старом;
  • часть программы написана на старой версии языка;
  • старая команда не задокументировала свой код;
  • код написан в одном стиле, а команда давно перешла на другой стиль программирования.

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

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

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

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

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

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

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

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

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

[Перевод] Код без тестов — легаси

Если вы работаете в IT, то о легаси вы слышите часто — обычно с множеством негативных коннотаций. Понятно, что это не «хороший код», но какой? Может старый, может не поддерживаемый или не обновляемый, а может просто чужой? Есть ли «полноценное» определение «легаси», на которое можно ссылаться? А когда разберемся — что нам делать с легаси? Попробуем разобраться. Спойлер: выводы неочевидны.

Автор — Николас Карло , веб-разработчик в Busbud ( Монреаль , Канада ). Специализируется на легаси. В свободное время организует митап Software Crafters и помогает с конференциями SoCraTes Canada и The Legacy of SoCraTes.

Данная статья была скомпилирована (и отредактирована) из двух статей Николаса : «What is Legacy Code? Is it code without tests?» и «The key points of Working Effectively with Legacy Code». Показалось логичным рассказать о том, что такое легаси, а потом — как с ним работать.

Что такое «легаси»?

Возможно, если вы задавались этим вопросом, то встречали определение от Майкла Физерса. Майкл выпустил книгу «Working Effectively with Legacy Code» в 2004 году, но она до сих пор актуальна. Комикс это отлично иллюстрирует.

В своей книге Майкл пишет своё определение:

«Для меня легаси — это просто код без тестов».

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

Это хорошее определение: чаще всего тесты отсутствуют, так что это хорошее начало. Но это ещё не всё — есть нюансы.

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

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

Перейдём к моему определению легаси.

Легаси — это ценный код, который вы боитесь менять.

Например, мы ищем первопричину ошибки или выясняете, куда вставить свою функцию. Мы хотим поменять код, но это трудно, потому что непонятно как не нарушить существующее поведение. Готово — у нас легаси!

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

Хорошие тесты помогают легко менять незнакомый код. А плохие тесты не помогают. Отсюда и определение Физерса.

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

Легаси не виновато в том, что оно такое. Большая часть кода ужасна, потому что это результат работы многих людей в течение долгого времени с противоречивыми требованиями и под давлением дедлайнов. Это Рецепт Устаревшего Кода™. Когда мало времени и недостаточно знаний — рождаются костыли (ну вы знаете). В конце концов, мы достигнем состояния, когда каждое движение приводит к ошибке, а реализация любой функции занимает целую вечность.

А теперь один из важнейших нюансов.

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

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

Работаем с легаси-кодом

Артём Кошелев photo
By Артём Кошелев May 17, 2017 Comment Permalink

Никто не любит легаси-код

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

Удали всё лишнее

Чтобы не делать лишней работы, давай для начала удалим весь неиспользуемый код. В Intellij IDEA есть встроенные инструменты анализа, ими и воспользуемся. Кликай на нужной папке правой кнопкой -> Analyze -> Run inspection by name -> Unused declaration . Всё что там нашлось, обычно можно спокойно удалять. После первой волны репрессий, запускай анализ снова. После удаления кода, мог появится новый неиспользуемый код (который использовался только в том коде, который ты удалил). Поэтому повторяй процедуру до тех пор, пока список не опустеет или стабилизируется.

Удали ещё

После того как ты удалил явно не используемый код, наверняка остался фактически не используемый код. Обнаружить его помогут инстументы для анализа покрытия. Если есть такая возможность - собери покрытие с боевого приложения - это даст максимально точную картину. Если такой возможности нет - собери покрытие при прогоне end-to-end тестов. Ты же доверяешь своим тестам? ;)

Мануалов по настройке приложения для сбора покрытия предостаточно (я об этом тоже как-то писал Измерение покрытия java-бекенда*), поэтому я не буду сейчас останавливаться на технических деталях.

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

За последние два месяца, мы удалили таким образом

30% кода в одном из компонентов.

Работаем с тем что осталось

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

Один из возможных подходов здесь - посмотреть на суммарное покрытие класса end-to-end и юнит-тестами. Такую метрику умеет показывать SonarQube. Если покрытие хорошее, класс можно менять относительно безопасно, постепенно увеличивая покрытие юнит-тестами. В ходе рефакторинга потребуются небольшие изменения в соседних классах и постепенно код будет становиться более тестируемым.

Другой подход, который используем мы - risk-based. Мы определили опасный код, как имеющий большую сложность и маленькое покрытие. На основе данных о сложности и покрытии из SonarQube, мы составили приоритезированный список классов. Потом стали их рефакторить и покрывать юнит-тестами.

Итого

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

Что такое Legacy-код? 2 определения термина. 8 советов по работе с legacy кодом для облегчения жизни.

В этой статье простым языком даны 2 определения Legacy-кода. И 8 советов для упрощенной работы с Legacy кодом.

⭕ Мы дадим 2 определения Legacy кода, от которых можно смело отталкиваться. По каждому из них дан небольшой поясняющий комментарий.

1 определение. Legacy-код — это код без тестов.

Legacy-код мем из интернета

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

2 определение. Legacy-код — это код, который проблематично поддерживать.

Более универсальная трактовка. Это личное определение Николаса Карло с сайта understandlegacycode.com.

Legacy код — это код имеющий ценность для продукта, но который вы боитесь менять. Legacy Code is valuable code you’re afraid to change.

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

Тут важно усвоить пару значимых моментов:

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

Хорошие тесты помогут вам изменить незнакомый код. Отсюда и определение №1. Но плохие тесты не в кассу.

Большая часть кода ужасна, потому что он является результатом того, что многие люди работают над ним в течение длительного периода времени с противоречивыми требованиями и нехваткой времени. Legacy Code Recipe™. Имеем ограниченные знания и локально используем костыли чтобы вписаться в дедлайны. Это частая практика. Рано или поздно это приведет к достаточно плачевным последствиям — что не изменение, то вылезает баг.

Как работать с Legacy кодом. 8 принципов-советов для упрощения жизни

На таком фоне имеет смысл заручиться некоторыми принципами-правилами, которые упростят работу с Legacy кодом и сделают жизнь рядовому разработчику проще:

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

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

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

Переписывание устаревшей кодовой базы может быть заманчивым. Но обычно это ошибка.

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

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

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

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

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

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

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

Есть способ не сделать код более проблематичным. И это благодаря тому, что новый код чист.

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

Разобравшись детально в Codebase, вы сможете улучшить ее.

Для заминки добавим две книги рекомендации по работе в Legacy кодом: “Working Effectively With Legacy Code” by Michael C. Feathers и “Refactoring: Improving the Design of Existing Code” by Martin Fowler.

Эффективная работа с легаси-кодом. Часть 3

В прошлый раз мы поговорили о добавлении фич, TDD и зависимостях. Сегодня — об изменении непонятного кода, гигантских классах и методах.

Глава 16. Я не понимаю этот код. Как мне его менять

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

Глава 17. У приложения нет структуры. Что делать

При работе с легаси может помочь приём «описание системы». Задайте себе вопрос «что из себя представляет структура системы?» и отвечайте на него так, как будто вам заранее ничего о ней не известно. Когда вы начнёте себе объяснять, как система функционирует, вы будете упрощать логику её работы. Это поможет выделить по-настоящему важные элементы и построить идеальную схему взаимодействий внутри системы.

Глава 18. Тестовый код мне мешает

Помечайте тестовые классы или функции суффиксами .test, .spec, фиктивные объекты — .fake, .mock, .stub. Тесты также можно вынести в отдельную папку в проекте. Удобно когда структура файлов тестов повторяет структуру файлов проекта.

Глава 19. У меня не ООП. Как безопасно рефакторить код

Дилемма легаси: чтобы изменить код, надо его покрыть тестами, а чтобы покрыть тестами, его надо изменить. Эта дилемма справедлива не только для ООП. Решения те же: разрыв зависимостей, фиктивные объекты, TDD.

Глава 20. Класс уже огромный. Не хочу, чтобы он стал больше

Если в классе 50 методов, то приходится долго вникать в его работу перед тем, как внести какие-то изменения. Не увеличивать размер класса помогут почкование метода или класса, но это временное решение. Настоящее решение — рефакторинг.

Рефакторить большие классы нужно по принципу единой ответственности: когда одна сущность отвечает за одну конкретную задачу. Если причина для изменения какого-то метода класса всего лишь одна — вы сделали всё правильно.

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

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

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

Глава 21. Я изменяю одинаковый код снова и снова

Один и тот же повторяющийся код можно переструктурировать по-разному:

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

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

Глава 22. Мне надо изменить гигантский метод, и я не могу написать тесты к нему

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

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

Вводите новые переменные, чтобы определить, когда программа доходит до момента, который вы собираетесь рефакторить.

После завершения рефакторинга и тестирования переменную распознавания можно удалить.

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

Глава 23. Как мне узнать, что я ничего не сломал

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

Ссылки по теме

Что дальше

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

Legacy: что нужно знать о работе с чужим кодом

Legacy: что нужно знать о работе с чужим кодом

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

Пожалуй, первое правило звучит так:

«Если в коде что-то реализовано не так, как вы привыкли – это не значит, что оно реализовано неправильно.»

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

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

О рефакторинге есть не одна книга. Поэтому вторым советом будет обратиться к литературе, например, Working Effectively With Legacy Code.

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

Уважайте чужой труд

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

Legacy: что нужно знать о работе с чужим кодом

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

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

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

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

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

Учитывайте интересы бизнеса

Есть поставленные цели и задачи: их нельзя игнорировать. Учитывайте интересы бизнеса и вносите изменения, когда:

  • приняты правила того, как никто не должен делать;
  • есть негативное влияние на показатели бизнеса, такие как производительность, безопасность, etc.;
  • текущая система мешает бизнесу выйти на новый левел.

Умение правильно определять решения – тоже навык. Поэтому вместе с утверждением, приведенным в начале, спросите себя:

«Открою ли я новую возможность, которая была нереализуема до этого, и принесет ли это пользу кому-то, кроме меня?»

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

Проблема абстрагирования

Абстрагирование – это важный инструмент ООП наряду с полиморфизмом, наследованием и инкапсуляцией. Абстракция позволяет работать с объектами, не вдаваясь в подробности их реализации.

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

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

Правильный способ – упрощение существующего кода или рефакторинг.

Общайтесь

Да, бывает откровенно плохой код.

Legacy: что нужно знать о работе с чужим кодом

Но нужно сперва разобраться.

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

  • «Какой используется шаблон проектирования?»
  • «Как производятся тесты?»
  • «Каким образом разворачивается среда разработки?»
  • «Как получить доступ к данным?»
  • «Каким способом происходит миграция данных?»
  • «Как обеспечивается масштабирование, параллелизм, безопасность, аутентификация?»

Если разработчики недоступны, ищите ответы в коде.

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

А еще помните, что разработчики часто копируют код из интернета, и реализовывают идеи, которые изучили недавно (все этим грешат, верно? :) ). Для подозрительных отрывков кода используйте поисковики.

Следуйте сценарию использования для анализа уровней приложения с помощью debugger’а. Возьмите на заметку непонятные фрагменты и набросайте диаграмму архитектуры.

Работа с легаси-системами: стабилизация, мониторинг, управление

На самом деле, по-хорошему статью следовало бы назвать так: «Как работать с легаси-системами и сохранять психическое здоровье». Любой, кто имеет с ними дело, меня поймет. Эта статья — попытка обобщения многолетнего опыта знакомства с легаси-системами в виде набора подходов и практических советов. Примеры буду приводить из собственного опыта — в частности, работы с унаследованной Java-системой. Кстати, материалов о работе с легаси в структурированном виде почти нет — оба источника, посвященных именно ей, приведены в конце материала. И это при том, что на легаси приходится чуть ли не половина всего аутсорсинга.

Что такое legacy или унаследованная система

Легаси — в переводе с английского «наследство», и наследственность эта тяжелая. Почти всем доводилось, придя в проект, получить код десятилетней давности, написанный кем-то другим. Это и есть унаследованный код — то есть код исто(е)рический, который часто бывает ужасен настолько, что оказывается вообще непонятно, как с ним работать. И если нам достается легаси-система, то мы, кроме старого кода, также имеем:

  • устаревшие технологии;
  • неоднородную архитектуру,
  • недостаток или даже полное отсутствие документации.

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

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

Прежде всего, нужно понять две вещи:

  1. Мы не можем неуважительно относиться к системе, которая зарабатывает миллионы, или к которой обращаются тысячи людей в день. Как бы плохо она ни была написана, этот отвратительный код дожил до продакшна и работает в режиме 24/7.
  2. Раз эта система приносит реальные деньги, работа с ней сопряжена с большой ответственностью. С самого начала ясно, что это не стартап в стол, а то, чем пользователи будут работать уже завтра. Это подразумевает и очень высокую цену ошибки, причем дело здесь не в претензиях клиента, а в реальном положении вещей.

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

Что со всем этим делать

Для успешной работы с унаследованными системами нам придется много пользоваться приемами reverse engineering.

Прежде всего, нужно внимательно читать код, чтобы точно понимать, как именно он работает. Это обязательно — ведь достаточной документации у нас, скорее всего, не будет. Если мы не поймем хода мыслей автора, мы будем делать изменения, последствия которых окажутся не вполне предсказуемыми. Чтобы обезопасить себя от этого, нужно вникать еще и в смежный код. И при этом двигаться не только вширь, но и вглубь, докапываясь до самого нутра. Откуда вызывается метод с ошибкой? Откуда вызывается вызывающий его код? В легаси-проекте “call hierarchy” и “type hierarchy” используется чаще, чем что бы то ни было другое.

Конечно, придется проводить много времени с отладчиком — во-первых, чтобы находить ошибки, и во-вторых, чтобы понять, как все работает — потому что логика обязательно будет такой, что по-человечески прочитать ее мы не сможем. Собственно говоря, дебажить нужно будет вообще все, в том числе и open source-библиотеки. Даже если проблема где-то в Spring, значит, придется отлаживать и, возможно, пересобирать Spring, если возможности его обновить не окажется. Именно так нам неоднократно приходилось делать, причем не только со Spring.

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

Используя эти приемы, рано или поздно вы начнете более или менее понимать код. Но чтобы ваши усилия не пошли прахом, вы должны обязательно сразу же документировать результаты своих изысканий — для этого я советую рисовать блок-схемы или диаграммы последовательности (sequence diagrams). Конечно, вам будет лень, но делать это точно нужно — через полгода без документации вы сами в этом коде будете копаться как в первый раз. А если через полгода с кодом будете работать уже не вы, ваши последователи будет очень благодарны вам за имеющуюся документацию. Кстати, зачастую для себя и для бизнеса документацию нужно готовить разную: в вашей, рассчитанной на инженеров, представители бизнеса ничего не поймут. Им потребуется что-то понятное, описывающее функционирование системы на верхнем уровне. И наконец, нужно не забывать самим пользоваться этой документацией и читать ее. Однажды, решив проблему после двух дней героической борьбы, мы обнаружили собственный документ, подробно описывающий точно такой же случай.

А руками?

Не переписывать!

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

Бизнес-интересы и рефакторинг

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

Тестирование

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

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

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

DevOps и релиз

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

Релизная процедура может быть, например, следующей. Когда заканчивается разработка и пройдены две или три фазы тестирования, мы пишем письмо DevOps-команде за 36 часов до предполагаемого времени релиза. После этого созваниваемся с девопсами и обсуждаем все изменения окружений (мы сообщаем им обо всех изменениях в БД и конфигурации). На каждое изменение у нас есть документ (тикет в Jira). Затем во время релиза все причастные к этому собираются вместе, и каждый говорит, что он сейчас делает: «Мы залили базу!», «Мы перезапустили такие-то серверы!», «Мы пошли прогонять регрессионные тесты в рабочем окружении!». Если же что-то идет не так, запускается процедура отката релиза, точно описанная в изначальном документе на релиз — без такого документа мы обязательно что-нибудь забудем или напутаем (вспомните, в какое время суток обычно происходят релизы).

Организация кода

Очень важно выстроить правильную branching strategy. Основные модели бренчинга давно описаны на сайте того же Atlassian, их можно адаптировать под ваши нужды. Главное — ни в коем случае не коммитить изменения сразу в транк: должны быть stable trunk и feature branches. Я советую делать релизы из релизных веток, а не из транка. То есть у вас есть транк, от которого отходят ветки на конкретные фичи, соответствующие тикетам в Jira. Когда вы закончили разработку в спринте, вы собираете отдельную релизную ветку из готовых фич и ее сертифицируете. Если же что-то пойдет не так, из такой ветки можно будет легко устранить то, что по какой-то причине из релиза в итоге выпадает. Когда же релиз произошел, релизная ветка вливается в stable trunk.

Контроль качества кода

И наконец, code review — это, казалось бы, достаточно очевидная практика, к которой прибегают почему-то далеко не во всех проектах. Очень хорошо, если каждая часть кода проверяется более чем одним человеком. Даже в очень сильной команде в процессе code review обязательно обнаруживаются какие-то косяки, а если смотрят несколько человек, количество выявленных косяков возрастает. Иногда самое страшное находит третий или четвертый reviewer. Но во избежание как саботажа, так и излишнего фанатизма, необходимо договориться, сколько review достаточно для того, чтобы считать фичу готовой.

Для проверки можно использовать пул-реквесты (конечно, если у вас Git), далее есть Crucible и FishEye — оба прикручиваются к Jira. И наконец существует очень удобный инструмент Review Board, который работает и с SVN, и с Git. Он позволяет послать запрос на проверку кода, который соберет в себе все изменения в данном feauture branch.

Как этим управлять

Подбор команды

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

Глупые вопросы

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

Процесс, или «Здесь так принято»

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

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

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

Бизнес, tech debt и SWAT

При работе с легаси-системами нужно стараться противостоять потоку бизнес-требований, которые заказчик будет вам непрерывно поставлять. Заказчик не всегда осознает риски, связанные со стабильностью системы, поэтому вам придется постоянно о них напоминать. Бороться с этими рисками можно двумя способами: балансированием бизнес и стабилизационных задач в каждом спринте или отдельными стабилизационными проектами. Оптимальным кажется баланс 70 на 30, когда 30 % времени каждого спринта вы занимаетесь стабилизацией. Впрочем, заказчик скорее всего не даст вам сделать все, что вы хотите — поэтому записывайте технический долг по мере обнаружения. Из этого tech debt вы будете брать задачи на вышеупомянутые 30 %. А может, заказчик согласится на стабилизационный проект, особенно если вы покажете ему tech debt в ответ на вопрос, почему все в очередной раз упало.

Для экстренных случаев я советую иметь SWAT — «группы специального назначения», которые смогут быстро решать непредвиденные проблемы в любое время суток. Ведь если система вдруг завалится, заказчик тут же начнет вам звонить и в 2 часа ночи, и в 4 утра — это мы проверили на своем опыте. Поэтому хорошо бывает договориться, кто в какое время дежурит на случай таких происшествий. Это должны быть быстро соображающие люди, которые могут сидеть допоздна, соответственно, чаще всего, не семейные. Но основная их задача — это все-таки, брейнсторминг днем. В этом есть особый инженерный кайф — в стрессовой ситуации оперативно находить ошибки в чужом коде, понимая, что спасаешь мир в рамках отдельно взятой системы.

Примеры оптимизации

А теперь вкратце расскажу о способах оптимизации, которыми мы пользовались в разное время.

Во-первых, нужно уйти от традиции ежедневных перезапусков, если так было принято в проекте. Однако делать это нужно, конечно, с осторожностью — продолжать проверять логи и следить за всем, что может привести к падению системы, и бороться с этим. У нас была система, которые перезапускалась каждую ночь, т. к. не могла прожить и двух суток из-за memory и других leaks — теперь же она совершенно стабильно работает от релиза до релиза две-три недели (за редкими исключениями, о которых мы обычно узнаем в 4 утра).

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

Очень важный момент — проход по всем логам и составление отдельного эпика. Бывают, конечно, заказчики, которые долго не дают доступа к продакшн-логу. У нас, например, так продолжалось полгода, после чего случился переломный момент, когда нас самих попросили посмотреть логи продакшна. Просмотр затянулся на всю ночь. В системе, работавшей, как считалось, штатно и стабильно, нормальные логи попадались лишь иногда — в основном же записи были со сдвигом вправо и начинались с “at”. Это были сплошные стектрейсы, и их набиралось на десятки мегабайт в сутки. Конечно, мы завели эпик в Jira и создали тикеты на отдельные exceptions. Затем нам пришлось несколько месяцев выбивать время на стабилизационный проект. В итоге мы исправили множество ошибок, о которых никто не догадывался, и сделали логи информативными. Теперь любой стектрейс в них — действительно признак нештатной ситуации.

Еще советую обращать внимание на третьесторонние зависимости как на front-end (Google Tag Manager, Adobe Tag Manager и т. п.), так и на back-end. Например, если у нас на странице есть JavaScript со сторонних ресурсов, нужно посмотреть, завернуты ли эти скрипты в try..catch блоки. У нас были случаи, когда сайт падал из-за того, что ломался какой-то скрипт на стороне. Также важно предусматривать возможность недоступности любых внешних ресурсов.

Ну и последнее: следите за всем, за чем только можно, и грамотно агрегируйте логи. Ведь у вас может быть 12 продакшн-серверов, и вас могут попросить их логи посмотреть, что точно нужно делать не через tail. Мы использовали ELK — связку Elastic search – Logstash – Kibana. Очень полезен мониторинг: мы навесили Java Melody на все серверы и получили огромное количество новой информации, на основании которой многое исправили, осчастливив заказчика.

Старый (legacy) код - это конец карьере?

Рассказывал знакомый, который до этого рассказал про черный список HR.

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

А работать здесь никто не хочет. Стоит на собеседовании кому-то услышать про webforms или, о ужас, классическом asp, тут же делает ноги и не хочет работать, хотя ЗП и всё остальное устраивает.

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

Дубликаты не найдены

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

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

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

Да тут зачастую дело в том, что проекты сами по себе не имеют заоблачных требований по квалификации.

Если вы берёте senior'a и оставляете ему время на самообразование.

Вы его найдёте, не вопрос.

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

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

Сам бы, ну пошёл если заплатите больше чем текущий работодатель, ну скажем на 30%, и попросил бы себе два отпуска, с целью потратить второй просто на своё образование.

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

P.S. Наймите человеков, перепешите код под новый стек.

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

вы ещё вспомните о том, сколько сейчас стоят программисты на коболе

Одного нашёл, чем платить будешь ?

Джун мог взять саппортить старый код и по чуть-чуть переписать его под новые реалии, добавив себе офигительный плюс в резюме)

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

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

И "знакомые программисты" радостно побежали устраиваться на освободившееся место.

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

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


Следующий шаг — заблокировать Youtube на рабочем компе

Следующий шаг — заблокировать Youtube на рабочем компе


Хотел создать зомбаря а получился фулстак дев

Хотел создать зомбаря а получился фулстак дев


Когда слег stackoverflow, а тебе надо работать

Когда слег stackoverflow, а тебе надо работать

Мой самый эффективный способ изучения IT

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

Мой самый эффективный способ изучения IT IT, Учеба, Работа, Программирование, Длиннопост

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

Смотрю, чтобы было адекватное время – урок длиной в 12 минут вряд ли меня чему-то научит (а иногда и окажется просто болтовней без строчки кода), но и на серию из 19 уроков по 1,5 часа каждый не всегда есть мотивация. Хотя иногда заходят и такие серии – когда я только начинала переходить от уровня "Вот есть теги h1 и h2, а вот я смогла вывести картинку" к уровню "Ничего себе, плавный адаптив! Вау, заработала карусель слайдов!" я отсмотрела серию из 16-ти видео уроков, за которые автор создал весьма симпатичный лендинг. На одном из уроков разбиралась библиотечка запуска карусели баннеров на первом экране, на другом – верстка и задание одинаковой высоты карточкам товаров, на третьем – отправка формы обратной связи аяксом. Для новичка полезно было все. Но чаще всего мне нравятся уроки длиной в 1,5-2 часа.

Сейчас для меня актуальнее чисто фронтенд – javascript и vue js, я смотрю уроки в основном по ним, а вёрстку по возможности использую авторскую, чтобы не тратить на нее время. Многие авторы делятся своим кодом, оставляя ссылки на проект. Но некоторые пытаются и продать доступ к коду.

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

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

Из последнего сделанного – случайно увидела статью на Хабре с описанием приложения, которое отслеживает и визуализирует положение МКС. Результатом является html-страничка, где в реальном времени показана статичная точка МКС, а под ней вращается планета. Делается с помощи 2-х библиотечек, своего кода там немного, но делать интересно, МКС же)) не видео, но формат аналогичный – автор подробно описывает каждый шаг с кусками кода. До этого по видео делала прогноз погоды из открытого API и приложение для ведения бюджета.

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

Единственный минус, что иногда поиск подходящего видео занимает времени больше, чем сам просмотр :)

Читайте также: