Привет, Хабр! У вас, наверно, бывали ситуации, когда вы начинали работать с легаси-проектами. У наших коллег такой опыт был. На прошедшем 28 января Luxoft TechFest наш Senior Team Lead Михаил Занкович рассказывал про кейс, с которым столкнулся на практике. Сегодня он хотел бы поделиться дополнительными мыслями, замешанными на содержании этого доклада, который вызвал достаточно бурное обсуждение во время митапа.
Какие эмоции и ассоциации вызывает у вас фраза: «У нас легаси проект»? Чаще всего — отсутствие структуры, бардак, тонны не документированного кода, ужас, архитектурная анархия, отвращение, море костылей, надо бежать! Мои эмоции: «О! Наконец-то, что-то интересное. Давайте заставим это работать!» Подозреваю, что это очень не типичная реакция.
В этой статье я попытаюсь раскрыть иную идеологию работы с легаси. Обозначим ее как «реставрация ПО». Я не ставлю цель поменять ваше отношение к легаси, но если получится хотя бы заронить зерно сомнения о том, что легаси — это может быть интересно, я буду рад.
Типичный legacy
Что такое легаси? По моему опыту, можно составить следующий чек-лист на соответствие продукта «легаси»:
- Отсутствует явный владелец продукта.
Т.е. тот, кто хорошо понимает что и для чего делается, понимает стратегию развития и видит перспективы системы.
- Неактуальная документация.
Затрудняет сопровождение проекта, формирует из продукта black-box. Увеличивает время погружения новых сотрудников. и плавно приводит к следующей характеристике. - Отсутствие архитектурного плана развития системы.
Функционал дублируется между модулями, нет четкой декомпозиции и зон ответственности между компонентами. - Низкая культура кода.
В первую очередь отсутствие или избыток комментариев. Отсутствие единого соглашения о наименовании объектов/интерфейсов классов и т.д.
Всё это приводит к тому, что сопровождать такой проект с каждым релизом становится все сложнее, ровно как и прорабатывать новую функциональность/новые требования. Любое изменение превращается в reverse-engineering с обязательным регрессионным тестированием и т.п. И в результате проект становится дорого поддерживать и его «замораживают» в существующем виде с минимизацией каких бы то ни было изменений.
Но из-за чего появляются legacy продукты?
Редко какая команда осознанно и целенаправленно создает некачественный продукт. Чаще всего это результат возможностей, ограниченных текущей ситуацией на проекте.
Нет четких требований — нет возможности сбалансированного проектирования функционала приложения.
Постоянное изменение требований, нечеткое формулирование, сжатые сроки имплементации, постоянно растущий технический долг — явные признаки гибких процессов разработки в команде, которая не смогла полностью адаптироваться к этим самым «гибким» подходам. И из «гибкого» работает только «быстро меняющиеся запросы от бизнеса».
Нередко это приводит к повышенной ротации внутри команды, что в свою очередь не сказывается позитивно на качестве. Представьте, новый специалист подключился к команде, два-три месяца только вникает в процесс, затем полтора-два месяца реализует какой-то функционал и готовится покинуть проект. Он не заинтересован в качественном продукте, в полноценном документировании своей части, передаче знаний коллегам и т.д. Экспертиза размывается.
В определенный момент принимается роковое решение: легче заменить/выключить, чем сопровождать. И проект переходит в фазу «low maintenance», когда его поддержкой занимаются по остаточному принципу, пытаясь минимизировать изменения, создать дополнительные «костыли», которые реализуют новые запросы быстро, но некачественно. А зачем качественно? Продукт же будет меняться. В таком режиме продукт может просуществовать долгие года, обрастая «костылями» и становясь все более монструознее.
Резюмируя все вышесказанное, можно выделить следующий основные причины возникновения legacy продуктов:
- сжатые сроки на реализацию функционала;
- отсутствие четких требования/интенсивно меняющиеся требования;
- повышенная ротация внутри команды;
- неправильное планирование жизненного цикла.
Добавляем сюда уровень профессионального развития специалистов на этот момент. Откройте свой проект пяти-, а лучше десяти летней давности. Уверен, без труда найдете элементы, которые сейчас бы вы реализовали иначе.
Итак, берем за аксиому: «код не создается изначально плохим». А значит в любом продукте была заложена какая-то идея. И если код вышел в продакшен, значит он работал и удовлетворял запросам бизнеса на тот момент.
Подход сопровождения
Задачи со стороны заказчиков достаточно просты: поддерживать наследие в рабочем состоянии, не нарушая текущие бизнес-процессы (часть из которых вообще никому не известны), при этом развивать функционал согласно новым требованиям согласно бюджету, который скорее всего ограничен.
Типичный подход команды, высадившейся на проект – продолжать медленно, но верно усугублять ситуацию. Не трогать лишнего, менять только то, что попросят и только тогда, когда попросят. Если модуль работает, но требует модификации логики – оставить и не трогать – лучше создать еще один такой, но с нужной логикой. Хаос растет, приложение усложняется.
Подход реставратора
Подход реставратора ПО – разобраться, что за механизм перед ним. Какая основная идея была заложена его создателями. Попытаться отсечь всё лишнее и сохранить всё самое лучшее. Если и изменять существующую структуру, то крайне осторожно и внимательно к деталям. От взгляда реставратора не должна скрыться ни одна мелочь, влияющая на систему. Вносимые изменения сначала прорабатываются по логике сопровождения, а потом идет анализ на возможность имплементации полноценного решения.
Это сложная и трудоемкая работа. Далеко не каждый разработчик желает, а главное реально способен заниматься реставрацией. Требования к уровню реставратора на порядок выше, нежели для обычного девелопера. Без опыта в реальных проектах, без понимания того, как могут развиваться системы, без столкновения не только с лучшими подходами на практике, но и с явно неудачными имплементациями – заниматься реставрацией не имеет никакого смысла.
Вместо типичного первого позыва «Да это ж костыли! Здесь надо всё переписать!» – истинный реставратор задаст вопрос «Почему было сделано так? Как именно планировалось это использовать?». И только удостоверившись, что не было никаких явных предпосылок к созданию такого кода, реставратор может воскликнуть: «Да это ж костыли! Здесь надо всё переписать!», и с чувством выполненного долга может действительно отколоть ненужный нарост на закостеневшем остове программного обеспечения, сделав объект реставрации лучше и качественнее.
Но такое случается редко, хотя и доставляет непередаваемое удовольствие реставратору. Чаще всего приходится распутывать клубок зависимостей между различными модулями. Не редко нити тянутся далеко за пределы зоны ответственности разбираемого компонента (а иногда и системы). И все эти хитросплетения взаимоотношений модулей должны учитываться при реставрации.
Таким образом, реставратор ПО работает на стыке девелопмента, архитектуры, бизнес-анализа, тестирования и медицины. И сложно сказать, какие навыки из обозначенных областей наиболее приоритетны. Должен быть определенный баланс между ними, приправленный честным желанием заниматься реставрацией. Причем здесь медицина? Так основной принцип реставратора «primum non nocere» – прежде всего не навреди.
Собственно этот подход будем рассматривать далее на конкретных примерах, постепенно разбирая и реставрируя типичное наследие, доставшееся от предыдущих технических владельцев систем. И на конкретных примерах посмотрим, почему важны все вышеперечисленные навыки.
Реставрация хранилища данных
Что хранит система?
Высаживаясь на новый проект, реставратор обратит внимание на объекты, обрабатываемые системой. Для полноценного погружения в бизнес-потоки и исходный код, особенно в условиях отсутствия нормальной документации, потребуется не меньше нескольких месяцев.
Одна из первых задач реставратора – оценить эффективность хранилища. Можно ли что-то улучшить, не опираясь на понимание бизнес-процессов? Типичная болевая точка любого хранилища данных, в первую очередь, связана с объемом этих самых данных. Чем больше объем, тем больше стоимость владения системой.
Вторая болевая точка – рост этого самого объема, что негативно сказывается на производительности системы в первую очередь. Скорее всего, уже существуют некоторые практики удержания информации в системе, но насколько они эффективны?
Все рассматриваемые здесь практики в большей степени применимы к классическим РСУБД, но и для no-sql решений подход не сильно отличается.
Одной из основных тактик реставратора в этом направлении является создание мониторинга объектов хранения информации. В случае классических СУБД – мониторинг таблиц.
Необходим фреймворк, который позволит по метаданным системы собирать периодически данные о двух тривиальных параметрах – объеме данных и количестве элементов в каждой таблице. Периодичность придется подбирать вручную (об этом ниже), исходя из особенностей работы системы. Обычного стартового периода в 24 часа вполне достаточно для базового анализа.
Анализ данных
Что делать с данными? На что обращать внимание? Первый момент – выявить наиболее «тяжелые объекты». На практике работает стандартное правило 20/80 – не более 20 процентов объектов будут использовать более 80 процентов пространства. Это позволяет существенно сузить зону анализа на первом этапе.
Чем дольше и подробнее подобная статистика накапливается, тем более четко отражается поведение системы. Как показывает опыт, рекомендуемый период – не менее двух недель. Основная идея – «зацепить» нерабочие дни/периоды, в рамках которых чаще всего реализуются механизмы очистки и архивирования информации.
Итак фреймворк написан, и реставратор две недели ждет результатов? Конечно нет. Это не бьется с идеологией реставратора. Получив первую порцию данных, можно провести базовый анализ. А именно – посмотреть соотношение занимаемого объема к количеству хранимых объектов (строк). Чем больше эта величина, тем больше вероятность, что здесь хранятся BLOB поля. И как раз эти таблицы и поля становятся для реставратора объектом исследования и анализа.
Основные вопросы: как часто к этим объектам реально обращаются бизнес-процессы? Владелец системы, существующая команда может пролить свет на подобные моменты. И внезапно (а на практике очень часто) оказывается, что подобные поля хранят не важную для бизнеса информацию: дампы объектов / сообщений для анализа командой разработки, комментарии пользователей, отображаемые только при создании заказа и т.п.
Следующий шаг: если данные не используются часто, или не несут явной бизнес-ценности, почему бы их не переместить в архив? При этом кардинальный подход с разбиением монолитной таблицы на части, вынос BLOB-объектов на более дешевый/медленный носитель, но при этом с сохранением исходного интерфейса таблицы (основной момент – нет достоверных сведений о всех процессах, обращающихся к этой информации, а значит изменения не должны им навредить) – может стать достаточно интересной и сложной технической задачей.
Менее интересная, но не менее полезная задача – использовать встроенные средства системы хранения данных по архивированию значений определенных полей. К примеру, Sybase ASE имеет фичу ASE_Compression, Mongo DB позволяет задать опции компрессии для коллекций и т.д. Практически любая система хранения информации имеет опцию дополнительного сжатия данных «под капотом». Функционал будет работать прозрачно для внешних систем и не потребует кардинальных изменений. На практике (особенно в legacy системах) подобные опции сжатия данных не используются по умолчанию.
Конечно же, применяя компрессию, реставратор в первую очередь должен оценить влияние подхода на производительность, а для этого должны быть проработаны ключевые показатели производительности системы, или, на крайний случай, должны присутствовать элементы регрессионного тестирования.
В общем, есть чем заняться в течение пары недель, пока собирается полноценная статистика по объектам.
Большая статистика: на что обратить внимание
Получив статистику за длительный период времени, реставратор пытается разобраться, что происходит с динамикой используемого места. Выполняется нормирование всех значений для одной таблицы/объекта к исходному. Это позволит оценивать именно относительный прирост данных и выявить наиболее интенсивно изменяющиеся объекты.
Построенный профиль, скорее всего, будет соответствовать одному из следующих типов:
Профиль 1 – константное значение. С максимальной вероятностью, это статичные справочники и с ними не столь интересно работать. Можно применить подход архивирования, описанный выше, опираясь на интенсивность использования справочника.
Небольшие флуктуации по объему – профиль 2 – могут говорить как о справочнике, так и об оперативной таблице, в которой интенсивно идет чтение/запись данных. Это наиболее сложные объекты с точки зрения реставратора, т.к. надо максимально детально анализировать их поведение. Именно для этих объектов, имеет смысл повысить частоту сбора информации: не раз в день, а раз в час, раз в минуту. Основная цель – более детально прорисовать изменение профиля и понять зависимости поведения.
Больший интерес вызывают профили 3 и 4. Профиль 3 (“пила”) четко говорит о том, что эта таблица периодически очищается. Но растущий тренд – каждый раз после очистки итоговый объем несколько больше, нежели был до этого – говорит о неэффективности существующих механизмов очистки. Т.е. за определенный период времени в системе появляется данных больше, чем удаляется в конце периода. Это может быть вполне нормальный бизнес-процесс, классический рост нагрузки на систему.
Но для реставратора это, в первую очередь, сигнал: не упущены ли какие-то условия для удаления информации? Исходя из практики, скорее всего какие-то сущности, ввиду сложных условий удержания данных в системе, незаслуженно остаются навсегда в хранилище. Цель реставратора – выявить такие сущности и также включить их в периодические активности.
Если же профиль 3 вырождается в постоянный рост – это первый претендент на узкое место в системе. Во-первых, нет явных указателей на процесс архивирования, во-вторых ожидается деградация производительности с ростом данных.
Профиль 4 – типичный пример архивной таблицы с периодическим наполнением данных. Обратите внимание, что рост таблицы происходит только в определенные дни. Вполне возможно, будут заметны корреляции с таблицами третьего профиля. Для архивных таблиц важно также понять принцип их использования – есть ли обращение к ним от пользователей? Или это история для анализа? Или это данные для репортинговых систем? В зависимости от ответов на эти вопросы вполне возможно будет принято решение выделить архивные таблицы в отдельный контур, отдельную базу, отдельный раздел. Тем самым освободив оперативное пространство.
Как это работает на практике?
В рамках одного из проектов подобное упражнение было сделано в первые полтора месяца после подключения к проекту. Именно объекты профиля №3 были целью, и они были найдены. Применение описанных практик (улучшение условий очистки), удаление данных, которые не использовались в рамках системы и т.п. позволили снизить объем занимаемого места более чем на 25%, а также остановить интенсивный рост хранилища.
В итоге мы смогли внести первые технические изменения в проекте и представить планы по улучшению функциональности. Заказчик остался довольным результатом команды, и она расширилась с 3 до 9 разработчиков. В течение года мы продолжали investigations, точки улучшения функциональности были использованы для поддержки системы и её характеристик.
К нам добавилось 2 аналитика, соответственно команда начала заниматься собственным девелопментом – не сопровождением, а реализацией нового бизнес-функционала. Теперь мы занимаемся разработкой новой системы.
Зачем всё это?
Если вы дочитали до этого места, то скорее всего вы ищете ответ на вопрос: «А зачем всё это?». В первую очередь реставрация – это отдельный процесс, не похожий на разработку, не похожий на сопровождение, но совмещающий их.
Это отдельный драйв для технического специалиста – вникнуть в логику того, кто создавал этот продукт, понять его смысл, очистить продукт от лишнего и сделать его еще лучше, чем был. Приложение выглядит как квест, с множеством загадок и неизвестными поворотами сюжета.
Нет вы не создаете с нуля, вы восстанавливаете уже существующий, но, возможно, разрушенный временем продукт. Помимо прочего, у реставратора появляется уникальная возможность прокачиваться в любом из шести направлений (см.картинку выше), при этом имея в качестве тестовой базы под руками реальный продукт. Прокачивается и чувство самоконтроля – не свалиться в технический перфекционизм, а продумывать и вносить только изменения, которые необходимы системе с точки зрения улучшения процессов.
Все это делает работу с легаси системами увлекательной и необычной. Но окончательный выбор реставрировать или поддерживать – остается за вами.
Доклад Михаила Занковича на Luxoft TechFest можно посмотреть по ссылке.
Автор статьи Михаил Занкович MikhailZankovich