Чому більшість кастомного програмного забезпечення стає непідтримуваним через 12 місяців
Патерни, що перетворюють працюючий софт на технічний борг. Що йде не так, чому це трапляється і як будувати системи, що залишаються підтримуваними.
Обрив через дванадцять місяців
Більшість кастомного програмного забезпечення працює ідеально при запуску. Функції відповідають специфікації. Клієнт задоволений. Усі рухаються далі.
Через дванадцять місяців щось потрібно змінити. Нова функція. Інтеграція. Виправлення для робочого процесу, що більше не відповідає реальності. І раптом те, що мало зайняти дні, займає тижні. Те, що мало коштувати 500 EUR, коштує 5 000 EUR. Прості зміни ламають непов'язаний функціонал.
Це не невезіння. Це передбачувано. І причина — майже завжди одні й ті самі патерни.
Патерн 1: Відсутність документації (Проблема "Все в мене в голові")
Розробник, який побудував систему, розумів її ідеально. Кожне рішення мало сенс у контексті. Архітектура була елегантною в його уявленні.
Потім він перейшов на інший проєкт. Або залишив компанію. Або просто забув деталі, попрацювавши над іншими речами.
Що губиться:
- Чому були прийняті конкретні архітектурні рішення
- Що від чого залежить (прихована зв'язаність)
- Як налаштувати середовище розробки
- Що насправді потребує процес деплоймента
- Які частини крихкі та чому
Рішення: Документація не є опціональною. Як мінімум: README, що пояснює налаштування, огляд архітектури та коментарі в коді для неочевидних рішень. Це забирає приблизно 10% додаткового часу під час розробки, але економить 500% під час підтримки.
Патерн 2: Нашарування функцій без рефакторингу
Версія 1 мала три функції. Архітектура прекрасно підтримувала три функції.
Потім клієнт запросив четверту. Вона не зовсім вписувалася в архітектуру, але дедлайн тиснув, тому її просто прикрутили. Потім п'яту. Потім шосту. Кожне додавання ускладнювало фундамент, який ніколи не був розрахований на таке.
Що відбувається:
- Функції розростаються з 20 до 200 рядків
- Файли перетворюються на звалища слабко пов'язаного коду
- Управління станом стає хаотичним і непередбачуваним
- "Тимчасові" хаки стають постійними елементами
- Нові функції вимагають змін у 15 файлах замість 2
Рішення: Закладайте бюджет на рефакторинг. Коли функція не вписується чисто — або скажіть ні, або виділіть час на реструктуризацію. Підхід "швидко зліпимо зараз, виправимо потім" ніколи не виправляється потім.
Патерн 3: Залежності як міни
Сучасне програмне забезпечення залежить від сотень зовнішніх пакетів. Кожен пакет має свої залежності. Кожна залежність — свій цикл оновлення.
Що йде не так:
- Вразливості безпеки вимагають термінових оновлень
- Оновлення ламають сумісність з іншими залежностями
- Застарілі пакети перестають отримувати безпекові патчі
- Різні пакети потребують конфліктуючих версій спільних залежностей
- Мажорні оновлення вимагають змін коду по всьому застосунку
Місяць 1: Все працює, залежності актуальні. Місяць 6: Кілька пакетів застарілі, термінових проблем немає. Місяць 12: Декілька пакетів мають відомі вразливості, оновлення потребують каскадних змін, деякі пакети застаріли. Місяць 18: Оновлення чого-небудь — це багатоденний проєкт з непередбачуваними наслідками.
Рішення: Регулярне обслуговування. Оновлюйте залежності щомісяця, а не щорічно. Ретельно фіксуйте версії. Уникайте зайвих залежностей. Обирайте зрілі, добре підтримувані пакети замість модних нових.
Патерн 4: База даних відрощує зуби
Початкова схема бази даних мала сенс для початкових вимог. Таблиці чітко відповідали концепціям. Запити були простими.
Потім вимоги змінилися. Нові поля додавалися. Старі неможливо було видалити (щось може від них залежати). Зв'язки, що здавалися зрозумілими, стали неоднозначними.
Типові симптоми:
- Таблиці з 50+ стовпцями, більшість рідко використовуються
- Поля з назвами
new_statusтаactual_status, тому що зміна оригіналу була занадто ризикованою - Запити, що з'єднують 8 таблиць для відповіді на прості питання
- Неузгоджені дані через зміни правил валідації при збереженні старих записів
- Загадкові nullable-поля, призначення яких ніхто не пам'ятає
Рішення: Ставтеся до змін бази даних так само ретельно, як до змін коду. Пишіть міграції, що дійсно мігрують дані, а не просто додають стовпці. Архівуйте або очищуйте застарілі дані. Документуйте схему.
Патерн 5: Тести, що не тестують
Система має тести. Тести проходять. Система все одно ламається.
Що насправді відбувається:
- Тести перевіряють, що код виконується, а не що він дає правильний результат
- Тести написані для ідеальних сценаріїв, ніколи для граничних випадків
- Інтеграційні тести мокають настільки багато, що не тестують інтеграцію
- Тести ламаються при будь-яких змінах коду, тому розробники перестають їх запускати
- Метрики покриття підроблені (100% покриття з безглуздими ассертами)
Рішення: Тестуйте поведінку, а не реалізацію. Пишіть тести, що виявили б реальні баги, які ви бачили. Підтримуйте тести як production-код. Видаляйте тести, що не виявляють реальних проблем.
Патерн 6: Розбіжність середовищ
Розробка працює. Стейджинг працює. Продакшен ламається.
Чому це трапляється:
- Розробка працює на іншій версії ОС
- Стейджинг має менше пам'яті/CPU, ніж продакшен
- Змінні середовища різняться непомітно
- Продакшен має патерни даних, яких немає в тестових середовищах
- Кешування поводиться інакше під реальним навантаженням
Рішення: Контейнеризуйте. Використовуйте однакові Docker-образи у всіх середовищах. Автоматизуйте налаштування середовища. Тестуйте з production-подібними обсягами даних.
Патерн 7: Відсутній bus factor
Одна людина глибоко розуміє систему. Всі інші мають поверхневе знання.
Ризик:
- Ця людина стає вузьким місцем для всіх рішень
- Коли вона недоступна, прогрес зупиняється
- Коли вона йде, інституційне знання йде з нею
- Вона накопичує "незадокументовані рішення", що стають мінами
Рішення: Парне програмування. Code review, що дійсно передає знання. Вимоги до документації. Перехресне навчання. Жодної одноособової власності на критичні системи.
Як насправді виглядає "підтримуваний" софт
Підтримуваний софт — це не ідеальний софт. Це софт, де:
1. Новий розробник може розібратися за дні, а не тижні. Структура очевидна. Конвенції послідовні. Документація існує.
2. Зміни локалізовані. Модифікація функції X не ламає функції Y та Z. Межі між компонентами чіткі.
3. Залежності керовані. Оновлення не каскадують непередбачувано. Є чіткий процес підтримки актуальності.
4. Тести виявляють реальні проблеми. Коли тести проходять, команда має реальну впевненість. Коли тести падають, збій вказує на реальну проблему.
5. Середовища відтворювані. Налаштування розробки — за скриптом. Стейджинг відповідає продакшену. Деплої передбачувані.
6. Знання розподілені. Кілька людей можуть вносити зміни. Документація фіксує рішення.
Чому це постійно повторюється
Патерн повторюється через невідповідність стимулів:
Під час розробки:
- Швидкість винагороджується
- Працюючі функції видимі
- Документація невидима
- Технічний борг невидимий
- Бюджет фіксований
- Швидкість залежить від якості коду
- Кожен "зріз" стає видимим
- Відсутня документація блокує прогрес
- Технічний борг вимагає оплати
- Бюджет на "прибирання" важко обґрунтувати
Як ми будуємо в QPC8
У QPC8, підтримуваність — не опціональна. Кожна система, яку ми випускаємо, дотримується одних і тих самих принципів:
Документація — частина постачання. Ми не вважаємо проєкт завершеним, доки README не пояснює налаштування, архітектура не задокументована, а деплоймент не описаний у скрипті.
Ми рефакторимо під час розробки. Коли вимоги змінюються в процесі проєкту (а вони завжди змінюються), ми реструктуруємо, а не прикручуємо. Це коштує більше в короткостроковій перспективі. Це коштує драматично менше за час життя системи.
Залежності — консервативні. Ми обираємо зрілі, добре підтримувані пакети. Уникаємо модних бібліотек, які можуть бути покинуті наступного року. Тримаємо кількість залежностей низькою.
Тести виявляють реальні баги. Наші тести фокусуються на поведінці, що має значення. Ми не женемося за метриками покриття — ми женемося за впевненістю.
Жодного одноособового знання. Наші системи задокументовані достатньо, щоб будь-який інженер міг їх підтримувати. Це не обговорюється.
Результат: системи, що залишаються здоровими з часом. Клієнти, які можуть вносити зміни, не натрапляючи на міни. Програмне забезпечення, що залишається активом, а не зобов'язанням.
Вартість правильного підходу
Побудова підтримуваного ПЗ коштує більше на старті. Можливо, на 20-30% більше за найшвидшу можливу постачання.
Але:
- Підтримка на 2-й рік на 50% дешевша
- Модифікації на 3-й рік на 70% дешевші
- Система може еволюціонувати замість заміни
- Внутрішні команди можуть працювати без зовнішньої допомоги
- Ви можете змінити вендора без початку з нуля
Бізнеси, що інвестують у якість на старті, платять один раз та ітерують.
Запитання, які варто поставити розробникам
Якщо ви оцінюєте розробку ПЗ (або підтримуєте існуюче), запитайте:
1. Як мені налаштувати середовище розробки? Якщо відповідь займає більше 10 хвилин — є проблема.
2. Покажіть мені документацію. Якщо її немає — ви залежите від усного знання.
3. Коли ви востаннє оновлювали залежності? Якщо відповідь "при запуску" — у вас бомба сповільненої дії.
4. Що буде, якщо ви потрапите під автобус? Якщо ніхто інший не може підтримувати систему — у вас єдина точка відмови.
5. Як задеплоїти зміну? Якщо процес не задокументований і не автоматизований — кожен деплой ризикований.
Відповіді розкажуть, чи ваше ПЗ є активом чи зобов'язанням.
---
QPC8 будує production-системи, спроєктовані для довгострокової підтримуваності. Дивіться наші реалізовані системи або налаштуйте свій проєкт.
Need this built?
We build production systems that implement these concepts. Get transparent pricing on your project.
Configure Your System →Related Posts
Чому більшість SaaS-бекендів не витримують масштабування
Типові архітектурні помилки, що вбивають SaaS-продукти при зростанні. Як будувати бекенди, що витримують 10-кратне навантаження без переписування.
Web SystemsДешева веб-розробка на Коста дель Соль — що ви реально отримуєте за €290
Шукаєте дешеву веб-розробку на Коста дель Соль? Ось що саме ви отримуєте за €290 — справжній Next.js сайт, а не WordPress-катастрофу.
Web SystemsНайдешевший професійний вебсайт у Малазі — чому €290 краще за безкоштовно
Безкоштовні конструктори сайтів обіцяють все. Ось чому професійний Next.js сайт за €290 перевершує їх усіх — і реально допомагає вашому бізнесу в Малазі рости.