Ни один современный проект не пишется с нуля: за формы, работу с датами, обработку изображений, авторизацию и десятки других задач отвечают сторонние библиотеки. Это разумно — писать своё там, где есть проверенное решение, дорого и бессмысленно. Проблемы начинаются позже, обычно на втором году жизни проекта: библиотека заброшена, обновление ломает совместимость, в пакете нашли уязвимость, а заменить его нельзя, потому что он вплетён в половину кода. Ниже разбираем, как выбирать зависимости и что делать дальше, чтобы через год проект не пришлось переписывать.
Почему зависимости стареют быстрее вашего кода
Ваш код меняется только тогда, когда его меняете вы. Внешний код живёт своей жизнью: у него другой график релизов, другие приоритеты и другой автор, который может потерять интерес к проекту. Плюс к этому меняется всё вокруг — версии языка, платформы, браузеров, протоколов. Библиотека, которая год назад была очевидным выбором, сегодня может не собираться на актуальной версии среды.
Второй источник старения — количество. Каждая подключённая библиотека тянет свои зависимости, и реальное дерево оказывается в десятки раз больше видимого списка. Обновить один пакет часто невозможно без обновления соседних, и проект оказывается заперт в старой версии целиком.
Что проверять до подключения
Оценка занимает десять минут и экономит недели. Мы смотрим на несколько признаков, и почти все они видны на странице проекта.
| Признак | Хороший вариант | Тревожный вариант |
|---|---|---|
| Последние изменения | Коммиты и релизы за последние месяцы | Тишина год и больше |
| Кто поддерживает | Команда, компания или активное сообщество | Один человек без соавторов |
| Открытые вопросы | На обращения отвечают, есть обсуждение | Сотни необработанных, ответов нет |
| Документация | Примеры, описание версий, история изменений | Три строки в README |
| Размер и охват | Соразмерен задаче | Большой пакет ради одной функции |
| Свои зависимости | Немного, все известные | Тянет десятки чужих пакетов |
| Лицензия | Разрешает коммерческое использование | Ограничения, несовместимые с проектом |
| Тесты | Есть, проходят на актуальных версиях | Отсутствуют или давно красные |
Отдельно стоит посмотреть, как автор обходился с несовместимыми изменениями раньше. Если в истории версий видно, что переходы описаны и сопровождаются инструкцией по миграции, обновляться будет спокойно. Если несовместимость появлялась в минорных версиях без предупреждения, это повторится.
Вопрос, который снимает половину зависимостей
Прежде чем подключать пакет, полезно спросить: сколько строк собственного кода он заменяет? Если ответ — двадцать, библиотеку подключать не стоит. Функция форматирования телефона, проверка адреса почты, простой генератор идентификаторов пишутся быстрее, чем читается их документация, и не создают обязательств на годы вперёд.
Обратная ситуация тоже встречается: своими силами пытаются сделать то, где ошибиться легко и дорого — шифрование, разбор дат с часовыми поясами, обработку загружаемых файлов, работу с платежами. Здесь брать проверенное решение обязательно, и здесь же требования к выбору самые высокие.
Изоляция: как заранее удешевить замену
Любая зависимость когда-нибудь заменяется. Стоимость замены определяется не качеством библиотеки, а тем, насколько глубоко она проросла в проект. Если вызовы разбросаны по сотне файлов, замена превращается в отдельный проект. Если библиотека спрятана за собственным тонким слоем, меняется одна реализация.
- Оборачивайте внешний код собственным интерфейсом, описанным в терминах вашей задачи, а не в терминах библиотеки.
- Не пропускайте типы и структуры данных из библиотеки через всю систему — конвертируйте на границе.
- Держите в одном месте всё, что касается конкретного внешнего сервиса: ключи, обработку ошибок, повторные попытки.
- Пишите тесты на своё поведение, а не на поведение библиотеки. Тогда после замены тесты остаются рабочими.
Оборачивать имеет смысл не всё подряд: язык, фреймворк и драйвер базы данных изолировать бессмысленно, они и есть основание проекта. Обёртка нужна для того, что с высокой вероятностью придётся менять, — внешние сервисы, платежи, рассылки, хранилища файлов, узкоспециальные утилиты.
Что устаревает быстрее всего
По нашему опыту порядок примерно такой. Быстрее всех стареют инструменты сборки и всё, что связано с внешними API: у сервисов меняются версии, условия и способы авторизации, и это происходит по их графику, не по вашему. Затем — библиотеки интерфейса, потому что вместе с ними меняется мода и требования браузеров. Дольше живёт то, что ближе к языку и базе данных: работа с запросами, валидация, вспомогательные утилиты.
Практический вывод: чем ближе библиотека к бизнес-логике проекта, тем осторожнее её нужно выбирать и тем тщательнее изолировать. Ошибка в выборе инструмента сборки стоит нескольких дней, ошибка в выборе основы для доменной логики — переписывания.
Регламент на год
Обновления не должны быть событием. Проект, в котором зависимости не трогали три года, обновляется тяжело и с сюрпризами; проект, где это делают ежеквартально, обновляется незаметно. Мы придерживаемся такого порядка.
- Версии зафиксированы, файл блокировки в репозитории. Сборка должна быть воспроизводимой: одна и та же команда через полгода даёт тот же результат.
- Раз в месяц — проверка уязвимостей в подключённых пакетах штатным средством менеджера зависимостей. Критичные исправления ставятся вне очереди.
- Раз в квартал — обновление до актуальных версий на тестовом контуре, прогон тестов, ручная проверка ключевых сценариев, потом выкладка.
- Раз в год — ревизия: что из подключённого больше не используется, что дублируется, что можно заменить встроенными средствами.
- При каждом подключении — короткая запись, зачем эта библиотека и что она заменяет. Через год никто не помнит, ради чего в проекте пять похожих пакетов.
Последний пункт кажется формальностью, но именно он позволяет спустя время спокойно выкидывать лишнее. Без записи никто не рискнёт удалить непонятную зависимость, и она остаётся в проекте навсегда.
Что делать с унаследованным проектом
Ситуация, с которой мы сталкиваемся чаще всего: сайт или сервис достался в поддержку, зависимости не обновлялись годами, документации нет. Здесь важно не бросаться обновлять всё сразу.
- Сначала зафиксировать текущее состояние: рабочая копия, снимок базы, воспроизводимая сборка на тестовом сервере.
- Составить список зависимостей с версиями и отметить, какие из них заброшены и какие содержат известные уязвимости.
- Разделить обновления на безопасные (внутри мажорной версии) и требующие переделки. Первые сделать сразу, вторые запланировать по одной.
- Начинать с того, что даёт наибольший риск: публично доступные компоненты, работа с загрузками, авторизация.
- Каждое обновление проверять на тестовом контуре и выкладывать отдельно — тогда при поломке понятно, что именно её вызвало.
Если заниматься этим некому
Регламент обновлений работает только тогда, когда за него кто-то отвечает и у этого человека есть выделенное время. Мы берём такую работу на себя: следим за версиями и уязвимостями, обновляем на тестовой копии и выкладываем на рабочий сайт. Посмотрите, как устроена техническая поддержка сайта, и напишите нам — разберём состояние вашего проекта и предложим план.











