Привет, Хабр! Меня зовут Геннадий Круглов, я работаю в команде «Архитектура Банка» в Департаменте корпоративной архитектуры Сбера.
Когда мы сравниваем «архитектуры», на самом деле чаще всего мы сравниваем архитектурные стили. Как и в строительстве, где, например, мы можем отнести здания к готике, классицизму, барокко или эклектике, мы относим архитектуры программных систем к 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. Напомню, что он служит основой для разделения монолита и обеспечения автономности его модулей
Заключение
Я показал, как концепции архитектуры и конструирования пересекаются в таких разных областях, как строительство и разработка программного обеспечения.
Аналогии из строительства помогли глубже понять, что архитектура приложения во многом определяется его конструкцией, которая, в свою очередь, влияет на свойства изделия, будь то здание или программный продукт.
Особое внимание было уделено монолитным решениям. Их сильная сторона — простота, проявляющаяся практически во всех аспектах архитектуры, и в разработке, развёртывании и обеспечении целостности данных. Однако эта простота становится их слабостью, когда система усложняется и сталкивается с ограничениями развиваемости, масштабируемости и отказоустойчивости.
Переход от монолитов к микросервисам — это не просто модный тренд, а закономерный шаг для разрешения архитектурных конфликтов, возникающих при усложнении требований.
При этом важно помнить, что микросервисная архитектура — не панацея. Она приносит свои сложности. Как и в строительстве, ключ к успеху — это баланс между текущими задачами и будущими перспективами. А значит, глубокая экспертиза и гибкость в выборе архитектурных решений становятся важнейшими навыками для каждого инженера.
В следующих статьях мы продолжим обсуждение, погружаясь в детали модульности, эволюции структур данных и перехода от монолитов к более гибким и масштабируемым решениям.
Grikhan
Архитектура чего-л. по определению - это структура, композиция. Об архитектуре вообще можно говорить только при наличии больше одной составляющей. Поэтому "монолитная архитектура" - это оксюморон. Отсюда уже можно заключить, что понятие монолита почти никогда, за исключением каких-то экстремальных случаев, не относится к системе в целом. Вы не можете построить по SOA систему на все времена - как только появляется дополнительная вариативность в бизнесе, у вас тут же появляются монолитные компоненты, которые раньше были вполне себе сервисами (логическими компонентами, решающими определенную бизнес-задачу), а теперь стали монолитами, которые нужно пилить на сервисы дальше (или можно обнести костылями, то есть решениями по обходу ограничений, что уже будет являться этими вашими спагетти, комами грязи и прочими мнемоническими понятиями для описания частных антипаттернов). Вот в этом уже заключается Архитектура, как искусство - соблюдение баланса между ростом энтропии системы и сложностью реализации актуальных задач, реализующаяся со своими историческими стилями в их диалектическом развитии.