Legacy-код - це рак

Все частіше і частіше я бачу, що люди ухиляються від новітніх технологій, роблячи вибір на користь зворотної сумісності. «Ми не можемо підвищувати мінімальні вимоги до PHP до 5.5, тому що у нас 50% користувачів ще на 5.4» кажуть вони. «Немає ніякого способу оновитися до
Guzzle 4+
, у нас бекенд на версії 3 і переробляти його занадто довго і дорого». І найкращий аргумент від WordPress: «Ми не може прийти до повного ООП, тому що більшість користувачів сидять на shared-хостингах з 5.1 або не знають про MVC».

Нонсенс.

Legacy-код — це велике НЕМАЄ

Можливо, це спірний висновок, але я твердо впевнений, немає місця для legacy-коду в сучасних системах. Скажу кілька слів, перш ніж ви почнете точити свої вила і запалите смолоскипи. Я маю на увазі, що не повинно бути ні найменшого приводу підтримувати старий функціонал, ви додаєте оновлення заднім числом до старої версії тільки тому, що деякі люди все ще використовують її. Навіть якщо цих людей більшість — не робіть так.

Для уточнення: виправлення помилок попередніх версій до тих пір, поки їх контракт на довгострокову підтримку не закінчиться, так. Додавання нового функціоналу, який можна випустити у версії
X
, у версії
X-1
, тільки для того, щоб не ображати користувачів
X-1
— абсолютно і 100% немає. Аналогічно, додавання
X-1
коду версію X тільки тому, що він може «знадобитися», має бути визнане неприпустимим. Якщо ви берете з людей плату за
X-1
і будуєте свої апгрейди поверх цього, то у вас дуже поганий бізнес-план.


Хоча, хто я такий, щоб нести таку нісенітницю? Я ніколи не підтримував великий проект з купою зацікавлених сторін і саппортом, який розвивається супермедленно і робить всіх щасливими. Наскільки довго він робиться і як працює не важливо, адже потенційно він може працювати в 100 разів безпечніше і в 1000 разів швидше, вірно? Не зовсім. Моїм найбільшим дитиною був сайт великого видавця зі складним бекендом на ZF1.

Якщо ви коли-небудь робили проекти на
ZF1
, то знаєте, цей фреймворк — вихор з милиць і анти-патернів. Коли програма почала показувати ознаки погіршення через збільшення трафіку, я перебудував фронтенд найбільш інтенсивно використовуваної частини програми повністю на роботу через ajax і виклики API. Навантаження різко впала і цим ми купили собі достатньо часу для перенесення всіх інших частин програми на
Zend Framework 2
. Тим, хто робив щось подібне відомо, що це все та ж суміш з милиць і анти-патернів, але трохи менш щільна.

Я намагаюся сказати, що великі зміни і переформатування може відбутися лише в тому випадку, коли за ними стоять здібні люди. Якщо все що ви робите — це суцільні agile-мітинги і мозкові штурми, то ніяке кількість LTS контрактів не може перешкодити вам нерозумно виглядати протягом п'яти років.

Навіть якщо ви робите безкоштовну та/або open source роботу, звичайно, ви не повинні ламати сумісність для X-1 користувачів. Роблячи їм ласку, розвиваючи старі версії, при глобальному оновлення ви можете зіткнутися з потенційною втратою зворотної сумісності. Просто засвойте одну річ — вони повинні або пристосуватися, або померти.

Так все ж, чому ми повинні вигнати legacy-код з сучасних систем?

Нескінченне LTS прокляття

Підписуючись під підходом «підтримуємо всі так довго, як тільки можемо», ви хоронитесь у бездонну яму, і, дивлячись на себе через кілька років, коли ви опинитеся змушені підтримувати чотири різні версії вашого продукту, ви будете битися головою об стіну з-за того, що не відмовилися від користувачів V1 і V2, якщо могли. У спробі зберегти аудиторію розробники часто виходять за рамки своїх можливостей і несправляются під гнітом тонн legacy-коду. З тієї ж причини WordPress і опинився в своєму нинішньому стані. Не дозволяйте приковувати себе до старої версії.



Ці користувачі — мертвий вантаж, вони повинні бути знищені незалежно від того скільки грошей вони вам приносять. Дайте їм можливість переходу і рухайтеся далі, якщо вони здатні, то наздоженуть вас. Якщо ж ні, то вони того не варті.

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

Ви отчуждаетесь і негативно впливаєте на просунутих користувачів

В останній раз я стикався з відчайдушним legacy-кодом я стикався, коли встановлював
CMS
, що виявилося дуже важким заняттям у середовищі
Vagrant
— не тільки з-за проблем з
symlink
, які зараз широко відомі всім (навіть творцеві
Vagrant
), але і з тим, що багато залишають застарілі версії
CMS
, оскільки частина модулів/плагінів ще не випустили свої оновлення. Раз немає оновлень модулів, то до чого оновлювати ядро? Навіщо поспішати, якщо ти до них не готовий?

Залишаючи legacy-код в новій версії, ви в кінцевому підсумку отримуєте монстра Франкенштейна, який начебто як і раніше працює, але погано, і новий код, який має потенціал, не може його розвинути через безладдя в успадкованої кодової базі. Такий підхід хоч і робить роботу компаній-розробників, які все ще застрягли десь у 90-х, простіше, але в теж час просунутим користувачам стає складніше працювати з продуктом. Рішеннями, прийнятими для натовпу, яка вже давно і безнадійно відстала від технологій, ви відчужуєте і негативно впливаєте на просунутих користувачів, здатних принести набагато більші гроші.



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

Невдачі іноді віщують успіх

Звичайно, іноді це просто неможливо, і подібні винятки є дуже рідкісним і цінним навчальним матеріалом. Один з цікавих випадків версионирования — 2й і 3й Python. Python — це дивовижний мову, з ним ви можете зробити практично все що завгодно. Але він не буде працювати також як міг би мову, побудований спеціально для вашої мети, це загальний недолік «майстра-на-всі-руки» мов — вони можуть зробити що-то дуже добре, але немає жодного варіанту зробити роботу з допомогою них бездоганно. Коли прийшов Python 3, у нього були введені деякі фічі, ламають сумісність і користувачі 2ї версії вже не могли так просто перейти на нього.

Більшість відмовок на кшталт «поки ще не вистачає Py3 пакетів» і «у нас занадто багато коду в Py2, щоб переписати все це» отримують від мене відповіді — «портируйте те, що вам потрібно» і «Бідні програмісти, їх змушують писати код», відповідно. Згоден, тут було кілька аргументів, але і ті, як правило, беруть приклад проекти, які були спочатку неправильно спроектовані, що і вилилося у їх абсурдно великий розмір.

Насправді зараз протистояння Py2 проти Py3 вже перетворилося в розлом, з обох боків якого стоять програмісти. Але багато хто не замислюються про те, що до того часу як буде Python 4, люди, які так затято відмовлялися від переходу на версію 3+ будуть залишатися на Py2 і несумісність стане ще більше. До того моменту вони могли б освоїти іншу мову, а не опиратися змінам в поточному. З іншого боку, ті, хто «наважився» переступити через розлом і переписав свій код на 3+ без довгих коливань, отримають всі новітні можливості майбутніх версій з нульовими трудовитратами.



Злам зворотної сумісності досить ефективно відсік ледачих і підготував Python для нового покоління розробників. На мій погляд, це величезний успіх. Програмування, як і багато інші сфери життя, все ще базується на виживанні найбільш пристосованих, і якщо ви не можете використовувати нові технології адекватно — відійдіть з дороги, не заважайте тим, хто може.

Програми vs Бібліотеки/Пакети

Також є питання щодо протистояння додатків і бібліотек. Іншими словами, якщо правило «не застарівати» застосовується для додатків, наприклад при отриманні нового релізу фреймворку, то воно повинно поширюватися і на бібліотеки?



Так.

Бібліотеки, що отримали бамп
X+1
, повинні чітко дотримуватися шляху до прогресу — з моменту, коли ваша версія бібліотеки стала публічно доступна, підтримуйте тільки виправлення останньої.

Додатки, які використовують такі бібліотеки, перебувають у більш складній ситуації через їх залежності від API, які, можливо, можуть змінитися. Розумний підходом буде чекати відгуків ком'юніті про стабільність, перш ніж почати перехід. Протягом перехідного періоду, як стара, так і нова версії бібліотеки/фреймворку можуть залишатися у використанні, і після того, як всі необхідні частини будуть модернізовані, стара версія повинна бути видалена. Адже це не займе багато часу, правда?

Не буває достатньо великого програми

«Але Бруно, деякі програми величезні і їх переписування займе кілька місяців», скажете ви. «Перехід з ZF1 на ZF2 — це рік роботи!», на що я відповідаю: нісенітниця. Немає достатньо великого веб-додатки, апгрейд якого займе подібні терміни. Я піду ще далі і скажу, що насправді немає веб-додатків досить великих, які могли б зрівнятися за розмірами з Symfony або Zend.

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

Схема оновлення

Як правильніше всього оновлюватися? Є тільки один прийнятний варіант оновлення програмного забезпечення, якого повинні дотримуватися розробники незалежно від популярності їх застосування/бібліотеки:

  1. Створіть нову гілку для нової версії
  2. Позначте стару версію/гілку як deprecated
  3. Публічно заявіть, скільки ви ще будете підтримувати стару версію
  4. Попередьте всіх користувачів старої версії
  5. Впроваджуйте нові функції ТІЛЬКИ в новій гілці, у старій — багфікси
  6. Коли час життя старої версії закінчиться, обривайте всі кінці. Не виправляйте, не радьте, взагалі видалити згадування про старій версії документації. Вбийте її.
Після проходження даної процедури ви ніколи не отримаєте у спадок неприємності.

Один з проектів, следущий цьому шляху — Guzzle. У нього є 3+ версія і 4+, для тих, хто хоче жити в ногу з часом і завжди бути на вістрі прогресу.

Висновок

Як веб-розробник, я твердо впевнений, legacy-код повинен бути викинутий, коли мова заходить про нових фичах або мажорному оновленні версії. Якщо у вас є великий проект, який використовує код версій, що вийшли два або більше місяців тому, ви повинні припинити всі дії з ним і переписати під свіжу версію, особливо, якщо продукти, якими ви користуєтеся, критично важливі для бізнесу. Немає в світі досить великих додатків, яким потрібно більше двох місяців для повного переходу, а якщо і є, то вони повинні бути переписані з нуля — веб набагато простіше, ніж ви завжди припускали.

А що думаєте ви? Слід legacy-код зберігати необмежений час? Певне число версій? Можливо не всі? Як ви ставитеся до legacy-кодом сторонніх проектах? Повинен розробник хвилюватися про проблеми з legacy в бібліотеках, якими він користується? Помилився я в цій статті? Даним постом я хотів почати дискусію про це — в кінці кінців, мої погляди на проблеми і переживання — лише моя точка зору. Дайте знати в коментарях нижче.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.