
Привет, Хабр! Меня зовут Геннадий Круглов, я работаю в команде «Архитектура Банка» в Департаменте корпоративной архитектуры Сбера.
Когда мы сравниваем «архитектуры», на самом деле чаще всего мы сравниваем архитектурные стили. Как и в строительстве, где, например, мы можем отнести здания к готике, классицизму, барокко или эклектике, мы относим архитектуры программных систем к N-Tier, SOA или, допустим, к микроядерной архитектуре. Мы позаимствовали из строительства идеи архитектуры и архитектурных стилей, поэтому продолжим использовать аналогии из строительной сферы.
Монолитной архитектуры как архитектурного стиля не существует. Монолитным может быть изделие или конструкция. Давайте немного погрузимся в инженерию и разберёмся на примерах из строительства и разработки программного обеспечения, что такое изделие и конструкция.
Изделие
В самом общем смысле изделие — это предмет, продукт и т. д., который был произведён или сделан кем-либо (Толковый словарь русского языка, Д. В. Дмитриев, 2003). В контексте этой статьи под изделием мы будем понимать конечный продукт, предназначенный для определённых целей. Таким изделием может быть как здание, так и приложение. Изделие представляет собой воплощение конструкции, дополненное множеством различных деталей (например, отделкой помещений или цветами кнопок в приложении).
Конструкция изделия
Конструкция изделия — это устройство, состав и взаимное расположение его частей. Подобное определение понятия «конструкция» часто встречается в словарях и других источниках. Необходимо обратить внимание на два элемента определения конструкции: устройство (внутреннее строение) и взаимное расположение частей изделия. Понимание этих элементов важно для осознания особенностей монолита.
В зависимости от способа изготовления и сборки изделия конструкции могут быть монолитными, сборными и модульными. Ключевой момент заключается в том, что конструкция изделия формируется в процессе его изготовления и сборки. Монолитные конструкции изготавливаются цельными и неделимыми. Сборные конструкции состоят из заранее изготовленных элементов, таких как железобетонные плиты или металлические фермы. Модульные конструкции формируются из готовых модулей, которые являются завершёнными функциональными узлами, например, готовыми комнатами или вспомогательными помещениями.
Важно отметить, что изделия с монолитной конструкцией невозможно разобрать. Изделия со сборной конструкцией можно разобрать и собрать заново, а изделия с модульной конструкцией представляют собой конструкторы, при этом часто можно изменять состав такого изделия без прекращения его функционирования.
Эта классификация справедлива для строительства, но её можно также применить в области разработки программного обеспечения.
Примеры изделий и конструкций в строительстве
Монолитное изделие в строительстве — это завершённое здание, выполненное с применением непрерывного литья бетона, где основные элементы конструкции формируются на месте как единое целое. Монолитная конструкция практически не допускает его модификацию после завершения строительства.
Примером изделия со сборной конструкцией является быстровозводимый сборно-разборный мост, который собирается на месте строительства из элементов, изготовленных в заводских условиях и доставляемых на стройплощадку в готовом для монтажа виде.
В модульной конструкции здания элементы, такие как комнаты, санузлы или бойлерные, изготавливаются и монтируются отдельно, а само здание, то есть готовое изделие, по сути, представляет из себя конструктор.
В строительстве понятие конструкции интуитивно понятно. Конструкция и изделие неотделимы: внутреннее устройство и взаимное расположение элементов, то есть сама конструкция, определяют структуру изделия. Однако в программном обеспечении всё гораздо сложнее. Чтобы понять, что представляет собой конструкция в контексте программного обеспечения, необходимо сначала разобраться с понятием конструирования.
Конструирование в программном обеспечении
Немного истории: мало кто задумывается, что в одной из самых известных и значимых книг по разработке программного обеспечения — бестселлере Стива Макконнелла «Code Complete: A Practical Handbook of Software Construction, Second Edition» — используется термин Software Construction.
Приведу несколько цитат из этой книги:
"Construction» is the work «construction workers» do when they build a house, a school, or a skyscraper.
...
In common usage, «construction» refers to the process of building.
...
Construction focuses on coding and debugging but also includes detailed design, unit testing, integration testing, and other activities.
Конструирование в разработке программного обеспечения выполняется в процессе программирования или реализации. Это подтверждают и другие источники, включая стандарт ISO/IEC/IEEE 12207 «Systems and software engineering — Software life cycle processes", в котором говорится:
Software implementation includes various combinations of construction (coding of newly built software elements), acquisition of new software packages (e.g., from open source or a commercial or organizational source) or re‐use of existing elements (with or without modification).
Изделие и конструкция в программном обеспечении
Изделие в программном обеспечении — это приложение, которое доступно пользователю и готово к выполнению задач, для которых оно было предназначено.
С конструкцией всё обстоит сложнее. Конструкция приложения делится на две составляющие: внутреннее устройство и размещение компонентов. Размещение компонентов приложения принято называть развёртыванием. Внутреннее устройство приложения формируется в процессе программирования, воплощается в программном коде, то есть в программе, и включает в себя зависимости, модули, интерфейсы и другие ключевые абстракции, а также структуры данных. Внутреннее устройство приложения — это устройство его программы, кода. И здесь мы будем говорить про структуру программы.
Но кодом всё не ограничивается. Из кода собираются компоненты приложения, которые затем развёртываются в соответствующем окружении на заданной инфраструктуре. Структуру компонентов программы, развёрнутых в окружении, можно назвать структурой развёртывания. Именно эта часть конструкции и определяет свойства изделия в итоге.
Когда мы характеризуем конструкцию, то оцениваем именно структуру развёртывания, так как она определяет структуру изделия — работающего приложения.
Важно понимать, что структура программы, определяемая её внутренним устройством, существенно влияет на структуру развёртывания и в определённой мере её ограничивает.


Конструкция приложения определяется разными структурами. И это принципиально важно.
Модульная структура программы может обеспечить модульность конечного изделия — приложения, развёрнутого в окружении и готового к использованию. Однако это не всегда так: в монолитах модульность приложения утрачивается. Монолитная структура программы в принципе исключает возможность формирования модульной конструкции изделия.
Этот аспект важен для развития инженерной интуиции, и мы детально рассмотрим его на различных примерах в этой и последующих статьях.
Понимание «монолита» в программном обеспечении
Теперь у нас есть всё, чтобы предметно рассмотреть, что чаще всего подразумевается под монолитом в разработке программного обеспечения. Уточню, что далее речь пойдёт исключительно об архитектуре информационных систем и веб-приложений, то есть о решениях, которые, как минимум, включают в себя взаимодействие с пользователями, бизнес-логику и длительное хранение данных. Эти три «звена» архитектуры были, есть и будут, пусть они и по-разному могут конструироваться в разных архитектурных стилях.
В дискуссиях о монолитах слой бизнес-логики обычно называется «бэкендом», а слой данных — «базой данных». Слой представления оставим вне рамок нашего рассмотрения.
Монолитом обычно называют систему, в которой бэкенд развёртывается как единое целое и база данных имеет цельную и неделимую структуру.

Монолит — не монолит
Монолитная структура программы — это макароны (spaghetti) или большой ком грязи (big ball of mud). Это антипаттерн, который можно использовать только для создания самых простых программ, развитие которых не планируется. Такой случай является исключением, и мы его рассматривать не будем. В то же время монолитная структура базы данных часто имеет практический смысл.
Таким образом, под «монолитом» логично понимать решение с модульной, немонолитной структурой программы и, как правило, монолитной структурой базы данных.
Такие «монолиты» называют модульными, и только они имеют практический смысл, если не учитывать самые простые решения, как уже упоминалось выше.
Всё становится ещё интереснее, если обратить внимание на структуру готового приложения, развёрнутого в окружении. В самом простом случае «монолиты» как приложения состоят из двух компонентов: одного экземпляра (instance) бэкенда и одного экземпляра базы данных. Чаще всего эти два компонента размещаются на разных инфраструктурных узлах и взаимодействуют через сеть.

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

Ещё больше сложностей добавляет задача горизонтального масштабирования. С увеличением количества экземпляров бэкенда усложняется архитектура развёртывания, включая такие аспекты, как балансировка нагрузки и переключение основного узла базы данных в случае его отказа.

Становится очевидно, что структура развёртывания приложений, относящихся к монолитам, далеко не всегда монолитная.
Почему мы всё-таки называем это «монолитом»?
Как видно, с учётом отказоустойчивости и масштабирования, изделие уже трудно назвать монолитом. Почему же мы всё‑таки называем «монолит» монолитом, даже если такие изделия могут быть совсем не монолитными? Попытаюсь рационализировать это название.
Модульная программа бэкенда собирается в монолитный компонент изделия и развёртывается как единое целое: на одном инфраструктурном узле, в одной среде исполнения, с выполнением кода в одном процессе — и это ключевой фактор, который определяет важные свойства такого решения.
В программном обеспечении, в отличие от строительства, изменения в конструкцию изделия могут вноситься постоянно. Если решение развивается, код может претерпевать изменения ежедневно, и структура программы может быть весьма подвижной.
Однако если провести аналогию со строительством, бэкенд нельзя разобрать на части и пересобрать. Любое изменение требует полной сборки и поставки всего бэкенда. Фактически при развёртывании новой версии бэкенда монолитный бэкенд заменяется на новый целиком.
В этом случае мы имеем дело с монолитом, хотя следует помнить, что речь идёт лишь об одном из компонентов изделия.
Следует упомянуть, что есть и распределённые монолиты. Это решения, где несколько модулей развёртываются как отдельные компоненты изделия, но строго совместно, в рамках одной «транзакции» развёртывания.
А теперь мы можем перейти к рассмотрению свойств монолитов.
Главное свойство монолита
Главное свойство монолита — это простота. Именно это свойство и определяет ключевые особенности монолита. Простота монолита проявляется практически во всех аспектах архитектуры:
IDE упрощает перепроектирование и позволяет легко перемещать границы модулей, то есть изменять структуру программы;
внутрипроцессное взаимодействие значительно проще и нет необходимости разрабатывать API для каждого модуля и клиенты к API других модулей, особенно если учесть версионирование;
уменьшается количество векторов атаки;
отпадает необходимость в компонентном тестировании;
минимальное количество артефактов развёртывания и простая инфраструктура;
можно полагаться на гарантии ACID, предоставляемые СУБД.
Однако, с ростом сложности решения утрачивается и ключевое свойство «монолита» — простота.По мере увеличения требований, числа разработчиков и объёма кодовой базы начинают возникать противоречия и, как следствие, конфликты:
сложнее синхронизировать поставку обновлений разных модулей, что негативно сказывается на сроках вывода на рынок (TTM);
функциональность разных модулей может иметь разную критичность для бизнеса, а при сбое монолит выходит из строя целиком;
модули с разными требованиями к нагрузке конкурируют за ресурсы и доступ к базе данных;
модули могут обрабатывать данные с разной степенью конфиденциальности, и разграничение доступа становится всё более сложной задачей;
и так далее.
Переход к микросервисной архитектуре
Разрешить конфликты и устранить ограничения монолита позволяет придание модулям автономности, что в итоге приводит к переходу на микросервисную архитектуру.
Вопрос о модулях и модульности требует более глубокого рассмотрения. Решения, в которых база данных имеет немонолитную структуру, — это также отдельная тема. Мы разберём её в одной из следующих статей вместе с паттерном Monolith First. Напомню, что он служит основой для разделения монолита и обеспечения автономности его модулей
Заключение
Я показал, как концепции архитектуры и конструирования пересекаются в таких разных областях, как строительство и разработка программного обеспечения.
Аналогии из строительства помогли глубже понять, что архитектура приложения во многом определяется его конструкцией, которая, в свою очередь, влияет на свойства изделия, будь то здание или программный продукт.
Особое внимание было уделено монолитным решениям. Их сильная сторона — простота, проявляющаяся практически во всех аспектах архитектуры, и в разработке, развёртывании и обеспечении целостности данных. Однако эта простота становится их слабостью, когда система усложняется и сталкивается с ограничениями развиваемости, масштабируемости и отказоустойчивости.
Переход от монолитов к микросервисам — это не просто модный тренд, а закономерный шаг для разрешения архитектурных конфликтов, возникающих при усложнении требований.
При этом важно помнить, что микросервисная архитектура — не панацея. Она приносит свои сложности. Как и в строительстве, ключ к успеху — это баланс между текущими задачами и будущими перспективами. А значит, глубокая экспертиза и гибкость в выборе архитектурных решений становятся важнейшими навыками для каждого инженера.
В следующих статьях мы продолжим обсуждение, погружаясь в детали модульности, эволюции структур данных и перехода от монолитов к более гибким и масштабируемым решениям.
Комментарии (8)
Dhwtj
22.01.2025 12:23Пролистал до перечня достоинств и недостатков монолита. Много воды.
Достоинства согласен в принципе.
Недостатки:
Монолит сложнее синхронизировать поставку обновлений разных модулей, что негативно сказывается на сроках вывода на рынок (TTM);
Давайте развернем.
Синхронизация обновлений модулей это неплохо сформулировано.
Монолит имеет средства статической проверки исполнения контрактов кода, в том числе контрактов между модулями. Имеет простую систему юнит и интеграционных тестов.
В противовес распределенная система имеет иные методы управления стыковкой модулей: версионность, в том числе одновременно несколько версий, постепенный перенес нагрузки на новую версию и ещё много деталей. При экстренной замене сервис можно отключить, оставив копиться задачи в очереди. И быстро запустить новый.
функциональность разных модулей может иметь разную критичность для бизнеса, а при сбое монолит выходит из строя целиком
Что выходит из строя: монолит или его инстанс? Перенаправили на другой сервер, первый рестартанул и бежим дальше.
модули с разными требованиями к нагрузке конкурируют за ресурсы и доступ к базе данных;
Да. СУБД не имеют управления приоритетами запросов. А в монолите сложнее определить нагрузку на ЦП и ОЗУ от конкретного модуля: даже если разделить на DLL нельзя узнать сколько потребляет каждая.
модули могут обрабатывать данные с разной степенью конфиденциальности, и разграничение доступа становится всё более сложной задачей;
Да. Платежный сервис всегда отдельно. Но таких частей, требующих кардинальной изоляции обычно мало.
Я бы выделил, что монолит требует меньше человеко часов разработки одной и той же фичи чем распределенные системы. Но только до определенного размера кода и количества разработчиков.
Монолит подходит для водопадной системы управления продуктом, с вертикальной иерархией при согласовании изменений. Микросервисы хороши для нескольких команд (от 5 команд по 10 человек) с горизонтальными связями между командами.
GKruglov Автор
22.01.2025 12:23В комментарии я увидел внутреннюю дискуссию относительно достоинств и недостатков монолита и обеспечении развиваемости решения. Хочу уточнить, что в статье не рассматривались достоинства и недостатки монолита. Я лишь выделил ключевое свойство монолита — простоту, которая может быть преимуществом в одних условиях, но в других это преимущество может быть утрачено. Иными словами, монолит на старте всегда проще, чем любые альтернативы, но со временем простота может быть утрачена, и могут возникнуть противоречия.
В комментарии также прозвучал вопрос: "Что выходит из строя: монолит или его инстанс?" В статье речь шла об утрате работоспособности отдельного инстанса или всего кластера монолитного бэкенда, то есть о полной утрате работоспособности бэкенда.
На практике мне доводилось наблюдать падения/утрату работоспособности кластеров монолитов. Например, кластеров NiFi и Confluence, когда под нагрузкой происходит переполнение стека на одном из узлов, что приводит к каскадному отказу всего кластера.
vadimr
22.01.2025 12:23Вообще предмет "конструирование программ" преподают на профильных специальностях.
GKruglov Автор
22.01.2025 12:23Эта статья предназначена главным образом для новичков в разработке ПО, многие из которых не имеют профильного образования, а также для людей из смежных областей, проявляющих интерес к данной теме.
Grikhan
Архитектура чего-л. по определению - это структура, композиция. Об архитектуре вообще можно говорить только при наличии больше одной составляющей. Поэтому "монолитная архитектура" - это оксюморон. Отсюда уже можно заключить, что понятие монолита почти никогда, за исключением каких-то экстремальных случаев, не относится к системе в целом. Вы не можете построить по SOA систему на все времена - как только появляется дополнительная вариативность в бизнесе, у вас тут же появляются монолитные компоненты, которые раньше были вполне себе сервисами (логическими компонентами, решающими определенную бизнес-задачу), а теперь стали монолитами, которые нужно пилить на сервисы дальше (или можно обнести костылями, то есть решениями по обходу ограничений, что уже будет являться этими вашими спагетти, комами грязи и прочими мнемоническими понятиями для описания частных антипаттернов). Вот в этом уже заключается Архитектура, как искусство - соблюдение баланса между ростом энтропии системы и сложностью реализации актуальных задач, реализующаяся со своими историческими стилями в их диалектическом развитии.
GKruglov Автор
Любой монолит всегда является частью какой-либо системы — здесь сложно найти исключения. Любое монолитное здание представляет собой элемент системы и на определённом уровне является частью города.
Однако, чтобы эффективно и с пользой рассуждать о том, что такое система в целом, необходимо учитывать точку зрения наблюдателя и соответствующий уровень рассмотрения. Например, для тестировщика, который пишет поведенческие тесты, опираясь исключительно на API монолитного бэкенда, сам этот монолит может (и должен) восприниматься как система в целом.
Монолитная архитектура, несомненно, является оксюмороном, с чем я полностью согласен.
Темпоральность же только добавляет динамики: монолитный бэкенд, существующий сегодня, то есть его текущая версия, завтра может быть разделён на части и наоборот. Как уже отмечалось, структуры программных решений могут быть весьма изменчивыми во времени.