Анализ результатов исследования факторы поддерживаемости backend-проектов с точки зрения Эргономичного подхода

October 21, 2025

Введение

Я проанализировал (совместно с GPT-5) результаты опроса «Характеристики поддерживаемых кодовых баз backend-приложений». С учётом ограниченного размера выборки (60 анкет) и моей квалификации в анализе данных, этим результатам нельзя безусловно доверять, однако, на мой взгляд, их вполне можно считать косвенным подтверждением тех или иных тезисов и идей.

И в этом посте я прохожусь по ключевым идеям Эргономичного подхода и сверяю их с результатами анализа.

TL;DR

Судя по данным, собранным в рамках исследования:

  • три из девяти рекомендаций Эргономичного подхода (пишите тесты, держите тесты быстрыми, исключайте циклы в зависимостях) ведут к повышению поддерживаемости;
  • ещё пять (минимизация моков, разбиение модели на агрегаты, разделение IO и логики и использование неизменяемой модели данных, ограничение кол-ва зависимостей до 5–7 на компонент, использование открытой архитектуры), как минимум не снижают поддерживаемость, либо имеют небольшой тренд на её повышение;
  • наконец, последняя рекомендация — не вводить интерфейсы без необходимости — никак не связана с поддерживаемостью: не повышает, но и не снижает её.

Хоть выборка у нас получилась и небольшая, но, на мой взгляд, голословные утверждения и немного статистики - это немного лучше, чем просто голословные утверждения.

Рекомендации Эргономичного подхода

Пишите тесты

Одной из главных (а, возможно, и самая главная — никак не могу решить) идей ЭП является то, что код должен быть покрыт надёжным набором тестов. Который, среди прочего, покрывает и код взаимодействия с инфраструктурой.

И судя по результатам анализа, наличие такого набора тестов действительно повышает поддерживаемость кода (или как минимум восприятие поддерживаемости последователями) - связь между процентом покрытия тестами и поддерживаемостью хоть и погранично значима, но зато самая сильная среди всех факторов (см. Статистический ликбез).

Здесь у меня есть ещё одно интересное наблюдение: я пытался найти хоть сколько-нибудь авторитетный источник, который бы говорил, что тесты писать не надо. И не нашёл ни одного.

И тем не менее я регулярно сталкиваюсь с разработчиками, считающими, что тесты неважны.

Но они важны, и эта рекомендация Эргономичного подхода согласуется с данными и здравым смыслом.

Минимизируйте использование моков (используйте Детройтскую школу тестирования)

В последнее время я думаю о том, если сетап моков и верификацию скрыть за моими Test Apis и Fixture Presets, то такая конструкция окажется не менее устойчивой к рефакторингу, чем работа с реальными зависимостями или самописными тестовыми дублями (как у Саши Раковского).

А если ещё и, как в подходе Саши, покрыть адаптеры интеграционными тестами, то такой набор тестов не будет (существенно, по крайней мере) уступать и в надёжности тестам по ЭП.

Поэтому я рассматриваю вариант замены цели «Минимизируйте количество моков», на дефолтное (но не единственно возможное) правило «По дефолту пишите интеграционные тесты через публичное АПИ» для достижения цели «Обеспечьте себе надёжный набор тестов».

И в целом эта идея согласуется с результатами анализа — вопросы «Детройтская vs Лондонская школа» показали слабые и противоречивые сигналы:

  1. С одной стороны, между детройтской школой и уверенностью разработчиков в тестах есть умеренная, но статистически незначимая связь;
  2. с другой стороны, между используемой школой и поддерживаемостью проекта в наших данных вообще никакой корреляции нет;
  3. с третьей стороны, между временем запуска одного теста и поддерживаемостью есть погранично значимая, но сильная (почти что очень сильная) связь с поддерживаемостью. И больше всего поддерживаемых (10 из 13) проектов было в категории «2–10 секунд». В то время как для категории «0-1 секунду» только лишь 2 из 7 проектов были поддерживаемым.

    Здесь уже начинаются чистой воды спекуляции на результатах анализа совсем маленькой выборки (23 ответа на этот вопрос), но, кажется, эти данные можно проинтерпретировать как дважды косвенное подтверждение идеи, что фокус на качественных (работающих до 10 секунд) интеграционных тестах повышает поддерживаемость.

То есть рекомендация минимизировать количество моков, судя по всему, не повышает, но и не снижает поддерживаемость систем и, возможно, немного повышает надёжность набора тестов.

Держите тесты быстрыми

Это вроде бы самоочевидное утверждение оказалось не так просто. Как написано в разделе выше, в нашей выборке тесты, работающие за 2–10 секунд, ассоциировались с поддерживаемыми проектами, в то время как тесты, работающие за 0–1 секунду, ассоциировались с неподдерживаемыми проектами.

То есть и снова выходит, что рекомендация ЭП подтверждается данными. Совпадение? Не думаю.

Исключайте циклы в зависимостях

По большому счёту прописная истина, но которой до сих пор пренебрегают.

И результаты анализа дают ещё одно и относительно сильное подтверждение тому, что делают это зря — и для отсутствия циклов между модулями и для отсутствия циклов в модели есть сильная и статистически значимая связь с поддерживаемостью, подтверждённая ML-анализом.

Исключение циклов в зависимостях — это рекомендация ЭП, которая в наибольшей степени подтверждена данными. И здравым смыслом.

Разбивайте модель на модули с явными границами

ЭП рекомендует в качестве модели данных использовать набор небольших деревьев структур данных (DDD-агрегатов), связанных между собой ссылками по идентификатору (а не прямой ссылкой на объект).

И эта рекомендация слабо, но подтверждается данными. В данных есть два тренда:

  • В проектах, где моделирование выполнялось с помощью плоских структур и небольших деревьев структур, процент поддерживаемых был выше, чем в среднем по выборке. А где использовалась модель единого графа объектов, связанных по прямой ссылке на объект - ниже среднего по выборке.
  • В проектах, где для работы с БД использовался чистый SQL либо легковесные ORM-ы без ленивой загрузки (и, как следствие, с разрывом связей между сущностями), процент поддерживаемых также был выше, чем в среднем по выборке. Аналогично в проектах с полноценными ORM-ами, процент поддерживаемых был ниже, чем в среднем по выборке.

Соответственно, даже по самой консервативной оценки, рекомендация разбивать модель на слабосвязанные модули как минимум не снижает поддерживаемость.

Разделяйте IO и логику; используйте неизменяемую модель данных

На основе практики применения, ЭП постепенно дрейфует от преимущественно функционального стиля к мультипарадигменному. Но тем не менее в нём всё ещё остаётся две рекомендации, родом из функционального подхода:

Прямых вопросов об этом в анкете не было, но были косвенные:

  • Какая была основная парадигма программирования;
  • следовала ли команда принципу Command Query Separation;
  • применялось ли реактивное программирование (Project Reactor, Rx* и т. п.).

И в вопросе о парадигме статистически значимой связи между парадигмой и поддерживаемостью не нашлось.

А вот у следования CQS и применением реактивного программирования и поддерживаемостью обнаружилась сильная и погранично значимая связь. Правда, для вопроса о реактивном программировании 73% ответов — «никогда» и «не знаю/не помню». Но для этих категорий поддерживаемость ниже средней по выборке (56% против 64), для остальных — выше (78% поддерживаемых).

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

Ограничьте количество зависимостей компонентов 5–7 штуками

ЭП рекомендует ограничить количество зависимостей (полей) одного компонента 5–7 штуками.

И эта рекомендация слабо подтверждается данными — в них наблюдается тренд (умеренная, но статистически незначимая связь) между небольшим (2–5 штук) количество зависимостей и поддерживаемостью.

Используйте открытую архитектуру

Это скорее «разрешительная» рекомендация: использовать открытую архитектуру (например, вызывать DAO/репозитории из контроллеров) — можно.

И данные её слабо подтверждают. В данных наблюдается слабый тренд на то, что проекты с открытой архитектурой более поддерживаемые: среди них процент поддерживаемых чуть-чуть выше среднего по выборке (66% против 64%), а среди проектов с закрытой — ниже среднего (52%).

Опять же по консервативной оценке, эта рекомендация как минимум не снижает поддерживаемость.

Вводите интерфейсы, только когда они нужны

Ещё одна «разрешительная» рекомендация: если вам не нужны полиморфизм или создание дополнительной границы между клиентами и реализацией, чтобы в будущем свободно менять реализацию — интерфейсы можно не вводить.

И данные её не опровергают: ни прямой вопрос о среднем количестве реализаций, ни вопрос о применении DIP-а не показали статистически достоверной связью с поддерживаемостью. То есть если у вас контроллер будет зависеть напрямую от класса сервиса, а не от интерфейса — то, судя по данным, на поддерживаемости это не скажется.