Технічний борг є невід'ємною характеристикою програмних систем — наслідком недосконалих знань на момент проектування, змінних вимог з часом і практичної необхідності йти на компроміс між швидкістю та досконалістю. У комерційному програмному забезпеченні технічний борг управляється через рефакторинг, переписування або заміну системи — цикли, які зазвичай відбуваються протягом трьох-семи років. У оборонному програмному забезпеченні часовий горизонт принципово інший. Основні оборонні системи регулярно функціонують протягом 20–40 років. Система, розроблена та закодована у 2005 році, може все ще функціонувати у 2045 році, працюючи на апаратному забезпеченні третього покоління, яке обслуговують інженери, які ще не були в робочій силі, коли писався код.

Цей розширений часовий горизонт створює проблему технічного боргу, яка якісно відрізняється від того, для чого розроблені підходи управління комерційним програмним забезпеченням. Стратегії, що працюють для п'ятирічного продукту SaaS, не перекладаються безпосередньо на оборонну систему, яка очікується служити три десятиліття. У цій статті розглядається, чому технічний борг накопичується інакше в оборонних системах, категорії боргу, що мають найбільше значення, та підходи, які досвідчені програми оборонного програмного забезпечення використовують для управління боргом без порушення операційної безперервності.

Чому оборонні системи накопичують більше технічного боргу

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

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

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

Втрата знань є структурною та неминучою. Протягом 30-річного терміну програми оригінальна команда розробників розпорошиться повністю — через звичайну кар'єрну мобільність, вихід на пенсію та природне вибуття. Це не є провалом управління знаннями; це неминучий наслідок тривалості програми. Документація, яка здавалася адекватною, написаною проти неявних знань, якими володіли автори, стає неадекватною, коли ці знання зникають. Архітектурні рішення, прийняті з причин, що більше не є очевидними, стають «священними коровами» — кодом, який ніхто не бажає змінювати, тому що ніхто не розуміє наслідків.

Еволюція технологій створює борг залежностей. Компонент, що включав найкращі криптографічні алгоритми у 2005 році, може використовувати застарілі алгоритми до 2025 року. Фреймворк, що активно підтримувався у 2010 році, може бути покинутий і вразливим до 2030 року. Програмне забезпечення продовжує функціонувати — можливо, дуже надійно — тоді як його рівень безпеки знижується, а підтримуваність зменшується, накопичуючи борг, який є невидимим, поки не стає критичним.

Типи технічного боргу, що мають значення в обороні

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

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

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

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

Ефект накопичення боргу: Категорії технічного боргу взаємодіють. Архітектурний борг ускладнює вирішення боргу коду, тому що рефакторинг у погано структурованій системі є більш ризикованим. Борг залежностей робить вирішення архітектурного боргу більш дорогим, тому що оновлення залежності може вимагати архітектурних змін для врахування змін API, що ламають зворотну сумісність. Документаційний борг погіршує всі інші борги, тому що обслуговуючі особи, що працюють без адекватної документації, з більшою ймовірністю внесуть новий борг, намагаючись погасити існуючий.

Патерн «Strangler Fig» для поступового рефакторингу без простоїв

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

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

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

Рамка пріоритизації: ризик проти вартості у місіє-критичному контексті

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

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

Пріоритизація також повинна враховувати залежності між елементами боргу та часову вартість накопичення: борг, що є дешевим для вирішення сьогодні, може бути дорогим для вирішення через п'ять років, якщо він накопичився з іншими елементами боргу або якщо вікно можливостей (персонал, що розуміє задіяний код, заплановане відключення системи, поточний огляд акредитування) закрилося. Найкращий час для вирішення боргу майже завжди раніше, ніж він стає терміновим — другий найкращий час — зараз.