Легасі — це не просто старий код. Це працююча система, яка приносить бізнесу гроші, але гальмує розвиток. У мобільній розробці легасі може бути написане на Objective-C, використовувати застарілі бібліотеки або архітектурні патерни. За даними звіту CAST Software (2024), середній вік рядка коду в enterprise-проєктах перевищує 14 років. Стратегія роботи з легасі визначає, чи перетвориться воно на гальмо чи залишиться керованим активом.
Головне
Легасі — код або система, які продовжують працювати в продакшені, але вже не відповідають сучасним стандартам якості. Легасі може бути написане застарілою мовою (наприклад, Objective-C замість Swift), використовувати непідтримувані бібліотеки або архітектурні патерни, які давно визнані антипатернами.
Ключова властивість легасі — відсутність тестів. За визначенням Michael Feathers (2004), легасі-код — це код без тестів. Якщо не можна безпечно змінити поведінку, система в статусі легасі незалежно від віку. Свіжий код без unit-тестів — це легасі першого дня.
Легасі не обов'язково погано. Добре спроєктована система на Java 8 може бути надійнішою та зрозумілішою, ніж хаотичний код на Kotlin з корутинами. Вік коду не є показником якості — важливо, наскільки система піддається змінам та розширенню.
Кожна успішна система з часом стає легасі. Це природний процес: технології розвиваються швидше, ніж код може бути переписаний. Застосунок, написаний 5 років тому на Swift 2, сьогодні — легасі, хоча в момент створення був сучасним.
Бізнес-цінність легасі часто недооцінюють. Система стабільно працює, обробляє транзакції, зберігає дані — переписування несе ризики. За даними Standish Group (2024), 35% проєктів повного переписування закінчуються провалом. Економічно виправдано не позбавлятися від легасі, а навчитися з ним працювати.
Найкращі стратегії — поступова міграція, інкапсуляція старого коду за новими інтерфейсами та автоматизоване тестування. Легасі стає проблемою тільки коли перестає піддаватися змінам з передбачуваною вартістю.
Відсутність автоматичних тестів — головний індикатор. Якщо після зміни одного рядка розробник не може запустити тести та переконатися, що нічого не зламалося — перед вами легасі. Додаткова ознака: процедура деплою займає години та потребує ручних дій.
Документація не відповідає коду — ще один маркер. Архітектурні діаграми застаріли, коментарі описують поведінку, яка вже змінилася. Time-to-ramp-up для нового розробника перевищує місяць — ознака високої складності та низької підтримуваності системи.
Додаткові ознаки: монолітна архітектура без чітких меж, ручне тестування як основний метод перевірки, довгий CI-пайплайн (більше 30 хвилин), використання бібліотек без актуальних версій та неможливість оновити залежності без поломки суміжних модулів.
Феномен «крихкого коду» — зміна в одному місці ламає три інших. Це наслідок щільної зв'язаності (tight coupling), коли модулі знають занадто багато один про одного. Чим вищий coupling, тим швидше система переходить у категорію легасі.
Зниження швидкості — основний ризик. Додавання простої фічі потребує годин на вивчення коду та днів на тестування. За даними Stripe (2024), розробники витрачають 33% часу на подолання технічного боргу, який прямо пов'язаний з наявністю легасі-модулів у проєкті.
Витік експертизи — автори оригінального коду йдуть з компанії, а документація неповна. Нові розробники бояться торкатися незрозумілих модулів, що призводить до ефекту «застиглого коду»: модуль не розвивається, але продовжує працювати. Bus factor таких систем критично низький.
Безпека — застарілі бібліотеки містять відомі вразливості. Використання OpenSSL 1.0.2 або застарілих версій Jackson в Java-проєктах — прямий шлях до інцидентів безпеки, які можуть коштувати бізнесу репутації та клієнтів.
Демотивація команди — робота з легасі без стратегії його покращення знижує задоволеність розробників. Команда перестає пишатися продуктом, плинність кадрів зростає, що ще більше сповільнює розвиток системи.
Characterization tests — перший крок перед будь-якою зміною легасі-коду. Запустіть код на відомих вхідних даних і запишіть очікуваний вивід. Ці тести фіксують поточну поведінку як специфікацію. Golden master testing — варіант, коли вихідні дані порівнюються з еталонним файлом.
Seam-аналіз — пошук точок, де можна розірвати зв'язаність без зміни поведінки. Michael Feathers виділяє кілька типів seam: preprocessor seam, object seam, link seam. Object seam — найпоширеніший: заміна реального об'єкта на тестову заглушку через інтерфейс.
Sprout method і Sprout class — техніки додавання нового коду поруч зі старим, а не всередині нього. Замість зміни існуючого методу створіть новий метод з потрібною логікою і викликайте його зі старого. Так мінімізується ризик поломки працюючого коду.
class LegacyPaymentProcessor {
def process(payment) {
// 200 рядків легасі-коду, яких не слід торкатися
logPayment(payment) // метод sprout
}
def logPayment(payment) {
// новий код доданий поруч з легасі
}
}
Strangler Fig pattern — рекомендований підхід для міграції легасі. Новий модуль створюється паралельно, трафік поступово перемикається зі старого на новий. Старий модуль «вмирає» природно, коли перестає отримувати запити. Патерн мінімізує ризики, дозволяє відкотитися при проблемах.
Branch by Abstraction — техніка, при якій створюється абстракція поверх старої та нової реалізації. Код клієнта перемикається на абстракцію, стара реалізація поступово замінюється новою. Приклад: заміна мережевого шару з AFNetworking на Alamofire через єдиний протокол NetworkService.
Поетапна міграція — розбиття переходу на маленькі кроки: інкапсуляція старого модуля → написання тестів → створення нового модуля → паралельний запуск → видалення старого модуля. Кожен крок завершується стабільним станом системи, що дозволяє розгорнути зміни в будь-який момент.
Часті запитання
Повне переписування — найризикованіший варіант. Лише 25% проєктів Big Rewrite завершуються успішно вчасно. Краще застосовувати Strangler Fig pattern: замінюй модулі поступово, без зупинки продукту. Кожна ітерація приносить бізнес-цінність, а ризики розподіляються в часі.
Почни з characterization tests: запусти модуль на відомих даних, запиши результат. Golden master testing — простий спосіб зафіксувати поведінку. Додавай тести кожного разу, коли торкаєшся рядка коду. Через 6 місяців у тебе буде каркас, що захищає від регресій.
Якщо система стабільна, не потребує частих змін і не впливає на швидкість розробки інших модулів — залиш її. «If it ain't broken, don't fix it» — розумний підхід для ізольованих легасі-модулів з низькою частотою змін. Торкайся коду тільки коли в нього потрібно внести бізнес-зміни.
Використовуй semantic versioning та оновлюй по кроках: patch → minor → major. Для кожної бібліотеки пиши тести сумісності. Dependabot або Renovate автоматизують створення PR на оновлення. Якщо бібліотека deprecated — плануй заміну через абстракцію.
Техборг — метафора для оцінки вартості відкладених покращень. Легасі — конкретна система або код, які вже застаріли. Техборг можна накопичити і за місяць, легасі потребує часу. Не будь-який техборг стає легасі, але будь-яке легасі містить техборг.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також