Как работать с легаси кодом
Перейти к содержимому

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

  • автор:

Эффективная работа с легаси-кодом. Майкл Физерс

Приёмы из этой книги мне помогают в работе, поэтому я решил составить по ней конспект. Примеры в ней написаны на Джаве и С++, поэтому не всё получилось перевести на JS. Я постарался вытянуть наиболее важное, но советую прочесть книгу и самим. Теперь к делу.

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

Глава 1. Изменение софта

Менять код нужно, чтобы:

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

В программе самое важное — её поведение. Пользователи любят, когда мы добавляем новое, и не любят, когда мы меняем старое. При добавлении нового поведения мы неизбежно меняем старое.

// до изменения class Player { addPlaylist(name, tracks) { // . } } // после class Player { addPlaylist(name, tracks) { // . } deletePlaylist(name) { // . } } 

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

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

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

Сохранить поведение неизменным трудно. Каждое изменение кода несёт риск изменения поведения. Чтобы смягчить риск, перед изменениями задавать себе три вопроса:

  • что надо поменять?
  • как узнать, что мы внесли изменения правильно?
  • как узнать, что мы не сломали остальное?

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

Глава 2. Работать на обратную связь

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

  • быстрый;
  • помогает найти проблему быстро;
  • не имеет внешних зависимостей.

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

Алгоритм изменения легаси-кода:

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

Глава 3. Распознавание и разделение

Для тестирования нужно разрывать зависимости в коде по двум причинам:

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

Класс NetworkBridge получает список узлов, каждый из которых открывает сетевое соединение и общается с другими узлами:

class NetworkBridge { constructor(endpoints) { // . } formRouting(sourceId, destId) { // . } } 

Как его тестировать? Если он связан с железом, можем ли мы себе позволить на каждый тест нагружать оборудование? Можем ли создать тестовый кластер? Есть ли на это ресурсы и время? Такие проблемы возникают, когда мы не понимаем, как выделить нужную часть и тестировать её изолированно. Здесь могут помочь фиктивные объекты.

Фиктивные объекты олицетворяют какой-либо класс во время тестирования. Например, у нас есть класс Sale , который сканирует штрих-коды, и выводит сообщения на экран устройства через класс Display :

class Sale { constructor(display) { this._display = display; } scan(barcode) { // сканирует // . // выводит сообщение this._display.showMessage('hello world'); } } class Display { showMessage(msg) { // . } } const display = new Display(); const sale = new Sale(display); 

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

class FakeDisplay { // вместо вывода на экран, будем запоминать сообщение // это метод, который имитирует настоящий метод класса Display showMessage(msg) { this.lastLine = msg; } // и потом выводить его по требованию // это доп. метод, который нужен именно в тестах getLastLine() { return this.lastLine; } } 

В тесте мы можем подменить класс, работающий с конкретным оборудованием на поддельный:

it('Выводит название товара на экран', () => { const fakeDisplay = new FakeDisplay(); const saleTest = new Sale(fakeDisplay); saleTest.scan('1'); expect(fakeDisplay.getLastLine).toEqual('Молоко'); }); 

Этот тест не упадёт, если не работает какая-то часть в настоящем классе Display . Но мы тестируем класс Sale , а не Display , поэтому конкретно в этом тесте это не важно.

Глава 4. Швы

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

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

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

Глава 5. Инструменты автоматизированного рефакторинга

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

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

// класс до рефакторинга class Example { alpha = 0; getValue() { this.alpha++; return 42; } doSomething() { let total = 0; const val = this.getValue(); for (let i = 0; i  5; i++) { total += val; } } } // после class Example { alpha = 0; getValue() { this.alpha++; return 42; } doSomething() { let total = 0; for (let i = 0; i  5; i++) { total += this.getValue(); } } } 

Лишняя переменная исчезла, но вместе с этим alpha++ вызвалось 5 раз вместо 1. Юнит-тесты помогут выявить это изменение.

В следующий раз

Поговорим об изменении кода, когда не хватает времени, добавлении фич, TDD и зависимостях.

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

  • Юнит-тестирование
  • Фиктивные объекты: стабы, моки
  • Модель швов

Советы по работе с легаси кодом в PHP

Сколько раз, приходя в новую компанию, вы получали в руки “большой комок грязи“, к которому каким-то образом нужно прикручивать новый функционал?

Без контроля версий.

Без какой-либо надежды на душевное равновесие в будущем.

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

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

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

Советы по отладке

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

Разбиение пополам (Half Splitting)

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

Пример А: База данных или код?

Допустим, у вас возникли проблемы с получением данных о клиентах. Это проблема проистекает из базы данных или из кода? Вы можете вставить SQL-запрос непосредственно в клиент MySQL, чтобы сразу понять, с чем конкретно связан проблема.

Пример Б: Здоровенный контроллер.

Допустим, у вас есть злополучный скрипт, который дает сбой. Когда-то давно мне приходилось работать с контроллер длиной в 45 000 строк. Нет, это не опечатка.

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

Я бы даже не пытался постигать такой монолит плохих практик. Я бы просто всандалил оператор die() или error_log() где-то около строки 22500 и посмотрел, присутствует ли еще ошибка.

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

Это глупо, это примитивно. Но очень часто это самый быстрый способ отладить что-то, особенно если это процедурно написанный код.

Пользовательское приемочное тестирование (User Acceptance Testing)

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

Как я уже говорил о превратностях работы с “большим комом грязи”, тут невозможно быть слишком осторожным.

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

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

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

Последнее изменение файла

Вы когда-нибудь встречали самодельные системы контроля версий, которые выглядели бы следующим образом?

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

Берем все под личный контроль

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

Бэкапим все

“Все, что не сохранено, будет потеряно”

— экран завершения работы Nintendo Wii

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

Вам нужны бэкапы:

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

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

Ограничиваем доступ

“Легче попросить прощения, чем получить разрешение” —

адмирал Грейс Хоппер

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

Я не могу сосчитать количество раз, когда на моей памяти производственный FTP-сервер использовался для хранения общих документов или архивов Outlook.

Если вы по какой-то причине не можете использовать службы обмена файлами, такие ​​​​как Dropbox или Google Drive, по крайней мере, создайте учетные записи FTP, которые ограничены выбранным каталогом. Хотя бы вы перестанете хранить PDF-файлы и шаблоны электронной почты в своей кодовой базе.

Контроль версий и локальная среда разработки

“Да, с помощью git легко отстрелить себе ногу, но также легко вернуться к предыдущей ноге и объединить ее с текущей ногой.”

— Джек Уильям Белл

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

Что хорошего в этих безнадежно устаревших кодовых базах, так это то, что они зачастую работают на очень простом стеке (Apache, PHP, MySQL).

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

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

И вместе с этим вы сможете даже уйти так, чтобы никто этого не заметил.

Заключительные размышления и рефакторинг

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

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

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

И, как всегда, не воспринимайте все близко к сердцу.

Перевод материала подготовлен в преддверии старта курса «PHP Developer. Professional».

Не приговор, а вызов. Как работать с легаси-кодом — практические советы разработчикам

Не приговор, а вызов. Как работать с легаси-кодом — практические советы разработчикам

Рассказывают Павел Попов и Александр Квасенко, PHP-разработчики из команды NIX

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

Но не все так плохо.

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

Павел Попов (слева) и Александр Квасенко (справа), PHP-разработчики из команды NIX

Как понять, что легаси-код нуждается в изменениях

Выявить проблемы на уровне бизнеса

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

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

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

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

Определить соответствие кода текущим задачам проекта

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

Работа с легаси-кодом: какие знания и навыки необходимы

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

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

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

Навыки рефакторинга важны и по другим причинам:

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

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

Как обновить легаси-код: основные шаги

1. Анализ кода

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

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

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

2. Создание роадмап

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

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

3. Рефакторинг

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

  • С одной стороны, проще и эффективнее работать с тем, что хорошо знаешь. Так можно реализовать максимум задуманного и использовать весь имеющийся функционал.
  • С другой — это не всегда работает. Иногда переписывание кода под «ваш» инструмент занимает много времени. Бывает быстрее изучить то, что уже применяют в проекте (особенно если речь идет об обновлении малого фрагмента кода), и таким образом прокачать свои хард-скилы. Да еще и используемые технологии могут быть более эффективными, чем те, с которыми работаете вы.

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

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

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

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

Никаких специфических проверок, набор стандартный:

  • юнит-тесты;
  • интеграционные тесты;
  • функциональные;
  • нагрузочное тестирование.

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

Рефакторинг не должен «застопорить» развитие проекта

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

Делайте небольшие итерационные изменения

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

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

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

Работайте над обновлением кода параллельно с основным проектом

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

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

Создавайте новую систему

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

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

Как документировать обновление легаси-кода

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

  • Пишите понятный код . Качественный код не нуждается в комментариях — в нем все и так понятно. Сегодня некоторые могут считать комментарии в коде олдскулом. Однако при желании можете добавлять их. Это точно не помешает новым разработчикам.
  • Ведите документацию . Это может быть техническая, функциональная и другие виды документации или гайдов. Их можно дополнять схемами или диаграммами для объяснения отдельных зависимостей между частями кода.
  • Фиксируйте и подробно описывайте в комитах каждое изменение в легаси: что и почему модифицируете, почему именно так и т. д. Нельзя допускать, когда что-то описано в Jira, а что-то — только в документации.
  • Описывайте не только новый код . В идеале надо вести документацию для всех фрагментов легаси, которые вы обновляете. Даже первичная документация станет полезной при работе над новыми фичами или в дальнейшей поддержке проекта.

Чек-лист оценки успешности рефакторинга

#1 Стабильная функциональность

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

#2 Выдержанные сроки

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

#3 Положительные отзывы

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

#4 Ускорение разработки

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

#5 Улучшение продукта

Здесь традиционные KPI: стабильность, скорость загрузки контента или отклика на запрос, уровень безопасности. Как минимум, эти показатели должны быть не хуже, чем до обновления. А в идеале — стать лучше.

Как не создать новый легаси

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

  • Думайте стратегически. Вы должны создать архитектуру со стабильным фундаментом для дальнейшего развития проекта. С другой стороны — стараться смотреть в будущее и видеть возможные пути развития продукта. Этот подход поможет заложить основу для добавления необходимого функционала. Если этого не сделать, то при изменении требований или для новых фич могут понадобиться какие-то «‎костыли».
  • Выбирайте долговременные решения. Это позволит дольше сохранить технологическую актуальность проекта. Учитывайте популярность фреймворка, частоту обновлений, активность сообщества, которое им пользуется, количество связанных библиотек, качество документации и т. д. Даже если разработчик такого решения вдруг остановит свою работу, фреймворк по инерции будет жить достаточно долго.
  • Соблюдайте правила программирования. По классике: пишите чистый и понятный код по принципам SOLID, следуйте правилам работы на вашем проекте, ведите документацию, внедряйте систему тестов и мониторинга. А еще не забывайте следить за техническим долгом. Иначе количество проблем быстро растет и словно снежный ком разрушает слаженную работу.
  • Настройте систему код ревью. Так вы будете видеть, в правильном ли направлении «распутываете» легаси, становится ли код понятнее, четче, действительно ли ваша работа помогает другим девелоперам.

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

Легаси-код

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

Освойте профессию
«Python-разработчик»

Python-разработчик

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

картинка - 2023-03-14T190323.524

Python-разработчик

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

dffsdd (3)

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

Существует несколько определений легаси-кода, каждое из которых на самом деле описывает один из его аспектов:

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

Чтобы понять, что такое legacy в разработке, достаточно взглянуть на общую схему появления такого кода:

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

К причинам появления легаси-кода можно отнести следующие:

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

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

Станьте разработчиком на Python и решайте самые разные задачи: от написания кода до автоматизации процессов

Достоинства легаси-кода

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

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

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

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

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

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

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

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

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

  • Осознать контекст. Перед тем как начать изменения, изучите код и разберитесь в его архитектуре и структуре. Понимание текущего функционала и основных проблем поможет вам определить, какие изменения необходимо внести и какие риски могут возникнуть.
  • Создать тесты. Прежде чем вносить изменения в легаси-код, создайте набор тестов, которые позволят вам проверить его работоспособность после внесенных корректировок. Тесты помогут избежать непредвиденных ошибок и подтвердить, что изменения не повлияли на работу системы.
  • Разделить код на модули. Если легаси-код слишком сложен для изменений в целом, попробуйте разбить его на отдельные блоки или компоненты. Это позволит вам работать с более маленькими и понятными частями, упрощая процесс изменений и обеспечивая более чистую архитектуру.
  • Постепенно вносить изменения. Вместо того чтобы пытаться переписать весь легаси-код сразу, начните с маленьких изменений. Поэтапное внедрение нового кода поможет контролировать риски и проверять работоспособность системы на каждом шаге.
  • Документировать изменения. Важно документировать все внесенные в легаси-код изменения, чтобы другие разработчики могли понять, что было изменено и почему. Это также поможет вам возвращаться к изменениям в будущем и понимать их влияние на систему.
  • Обратиться за помощью. Если вы столкнулись с особыми сложностями или не можете справиться со старым кодом самостоятельно, не стесняйтесь обратиться к коллегам или сообществу разработчиков за помощью и советами. Часто опыт других людей может быть очень полезным в работе с легаси-кодом.

Обязательно ли устранять или переписывать легаси-код

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

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *