Легаси

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

Знаю, конечно. Интранет и до тебя был отличным, и как ты ушёл остался замечательным, даже лучше стал. Ты же там видел только костыли и легаси – потому что мыслишь узко. Бойцы типа тебя – не те кто инфраструктуру пилит, которую якобы не очень видно на фоне кораблей, бороздящих просторы созвездия Лебедя, а те, у которых предел мечтаний отрефакторить код, чтобы можно было прикрутить любимый (модный, надежный, whatever) фреймворк.

Так что не надо, пожалуйста, прислоняться к действительно талантливым и толковым ребятам, тиражируя мемуары. У меня всё.

Не сомневаюсь, что без меня везде становится только лучше, но любимая мозоль (легаси) была задета. Отсюда и тема.


Начну с формальностей. «Официальное» толкование термина в Википедии само по себе кажется вариантом legacy, потому озвучу свой вариант, которым в голове постоянно оперирую и который подспудно везде подразумеваю.
Легаси — код, для которого через AND (со|на)блюдается следующее:

  1. Находится в production’е, т.е. каким-либо образом используется на текущий момент.
  2. Вносить в него изменения либо невозможно, либо неадекватно дорого.
  3. Не в полной мере удовлетворяет актуальным требованиям, при этом количество таких требований со временем возрастает.

По номерам пунктов и разверну.


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

Во-2-х. Кейс с потолка. Программа библиотечного учёта. Вроде работает, библиотекари даже прижизненный томик Льва Толстого подарили на радостях. Спустя год потребовалось добавить новое поле к карточке. Да фигня, там же тех полей и так много, скопипасть соседнее, переименуй, вот и всё, десять минут работы. Разработчик смотрит в код. Документации, к слову, нет, потому в код смотрит прям сразу. Делает чай. Смотрит ещё раз. Закуривает. Смотрит. Чертит схемы на бумажках. Добавляет сто строк кода и спустя сутки без сна рапортует об успехе. Одно поле. Сто строк. Сутки работы. Знакомо, нет? Если нет, не завидую, у вас впереди свежесть эмоций от осмысления пропасти между простотой задачи и сложностью реализации. Одна из самых характерных черт легаси. Таких задач всё больше. Каждое впиливание в легаси нового продуктового заказа делает код сложнее для впиливания следующего заказа. Лапша из костылей. Если потом упороться и собрать годовую статистику «потратили столько часов, а, казалось бы, должны были столько», волосы дыбом мурашками шевелятся. Дешевле было заново сервис написать. Год, другой, третий жуют кактус. На четвёртый героически переписывают. Ура.

В-3-х, актуальные требования. Тут четыре вектора.
Продуктовые требования. Есть простое эмпирическое правило: если хочешь получить легаси со старта, напиши сервис ровно по ТЗ. Тютя в тютю. Мир меняется, люди меняются, да чего там, гречка дорожает. Сегодня одно ТЗ, а уже через год жизни в production хотелок накидывают столько и таких, что повторно написанное ТЗ породило бы другой сервис. Хороший код обладает запасом гибкости, позволяющим менять сервис точечно, и прочности, позволяющей сохранить при всех изменениях исходную архитектуру. Легаси же этим не обладает. Потому часть задач не делается сейчас. Часть не сделается никогда. Часть делается в муках. Новых требований всё больше, нового [полезного] кода всё меньше.
Требования стабильности. Новые версии софта выпускаются не только потому, что дяденькам for fun чиселкам плюс-плюс делать, но ещё и потому, что есть security fixes, например. Или вдруг обнаруживается memory leak (который вы счастливо прохлопываете в продакшене, старательно убивая worker’ы uWSGI после малого N запросов). Или «о, блин, народ, мы тут sleep десятисекундный забыли, простите, вот новая версия». В который раз настоятельно советую читать changelog’и MongoDB и Java. Возможно, на сотом багфиксе что-то станет более понятным в контексте «надо обновляться».
Ресурсные требования. Если у вас сто машин на десять сервисов, а вам нужно ещё два сервиса добавить, но некуда, начинаете думать и смотреть с лупой на код. Мне с этой позиции интересен недавний микрокейс. Стоял nginx 1.10, в который впилили скрипт на Lua, который генерировал uuid для request’ов. Стоял давно, впилили тоже давно. Работает и ладно. Нормальный талантливый человек пройдёт мимо. Ненормальный мыслит узко и вспоминает, что в nginx 1.11 добавили штатный request_id через SSL RAND_bytes, потому что? Потому этот скрипт можно выпилить, апнув nginx. Профит. Если масштабировать этот подход к тем десяти сервисам… вот кажется, что всё-таки после массовых обновлений всего можно там выпилить, сям подпилить, вон там «само» ускорится. И потому пару машинок уже можно отобрать.
Наконец, требования современности. Код на Java 1.2 (релиз 1998 года), на дворе Java 1.9 (2017 год), на рынке джависты с опытом Java 1.6, 1.7, 1.8. Проблема ясна? Или другой вариант: в коде Django 1.6 (релиз 2013 года), на дворе Django 1.11 (релиз 2017 года, к слову, последний релиз с поддержкой Python 2.7, вдруг кому интересно ещё раз подумать о том, что такое легаси на практике). С каждой новой выходящей версией чего-нибудь теряется поддержка старого чего-нибудь. Поддержка людьми, поддержка рынком, поддержка информацией, банальная техническая поддержка («мы эту фичу сделали только с версии N.M»).

Таким макаром в самом кошмарном варианте вы получаете чудище из страшных снов разработчиков, пользователей и заказчиков: фичи не добавляются, поддерживать тошно, ресурсы жрёт как не в себя, болтается на стремительно устаревающем техностеке, дырявое аки решето. Самое время, чтобы подумать «ой, чёт хочу вкрутить свой любимый фреймворк, надо бы порефакторить!» ^_^
Самое, пожалуй, фиговое, что заполучить легаси очень просто. Достаточно поступать вот так:

  • Генерируйте велосипеды, подключайте велосипеды. Наверняка они не будут заброшены авторами. Всегда интереснее тащить в будущее сервис с десятью полузаброшенными велосипедами, чем скучно апать версию популярной библиотеки.
  • Техдолг откладывать. Нет, сегодня мы не обновимся, есть дела важнее. Завтра тоже. И через месяц. Вот планы на год, обновления тут нет. Всё и так работает.
  • Думать некогда. Делать правильно некогда. Надо делать быстро прямо сейчас, решая именно текущие задачи. Когда появятся другие задачи, тогда и подумаете, как их в код впилить. Или не вы, но другой Вася, его ни капли не жалко.

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


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

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