Vladimir Gordienko 04 апреля 2023

🧱 Модульная архитектура: что, как и почему?

Модульный подход к архитектуре делает написание кода более простым и динамичным и имеет множество преимуществ: от возможности работать над кодом в команде удаленно до высокого уровня безопасности. В статье разберемся, что такое модульная архитектура, как она работает и как модульный подход поможет оптимизировать работу над вашими проектами и даже улучшить их качество.
🧱 Модульная архитектура: что, как и почему?

Модульная архитектура — это подход к разработке программного обеспечения, в котором приложение разбивается на независимые компоненты — модули. Каждый модуль выполняет определенную функцию и имеет свою логику и интерфейс для взаимодействия с другими модулями. Таким образом, разрабатывая проект с помощью этого подхода, вы «строите» свой продукт из отдельных «кирпичиков».

Конечно, модульная архитектура — это термин, который используется не только в разработке программного обеспечения. Продолжая аналогию со строительством: примерами модульных систем могут служить модульные здания, солнечные батареи, ветряные турбины. Модульные конструкции сочетают в себе преимущества стандартизации с преимуществами настройки, так что модульный подход к архитектуре позволяет разрабатывать приложения в более масштабируемом и модульном стиле.

Какие преимущества есть у модульной архитектуры?

1. Возможность разработки в большой команде

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

2. Возможность повторного использования кода

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

3. Усовершенствованная отладка и тестирование

Модули можно тестировать и отлаживать отдельно, вне зависимости друг от друга, что упрощает процесс отладки и позволяет вам не тратить время на тестирование приложения в целом.

4. Лучшая масштабируемость

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

5. Более высокая безопасность

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

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

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека программиста

Как этого добиться?

Вот некоторые из популярных практик, которые используются при реализации модульной архитектуры:

  • Определение границ модуля

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

  • Определение зависимостей

Каждый модуль должен быть зависим только от узкого круга определенных необходимых для работы модулей и независим от всех других.

  • Использование интерфейсов

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

  • Использование инъекции зависимостей

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

  • Использование общего ядра

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

А зачем вообще нужны разные типы модулей?

Одна из главных целей проектирования архитектуры приложения — упростить понимание и поддержку кода за счет наличия четкой цели у каждого отдельного модуля и логичных взаимозависимостей между модулями. В качестве примера в этой статье я приведу следующую классификацию модулей: api, core, utility и implementation — которые описывают общую функциональность каждого отдельного модуля. Каждый тип модуля имеет определенный набор правил: от каких модулей он может зависеть и какую функциональность он содержит. Это позволяет лучше определять назначение каждого модуля и придерживаться нужных взаимосвязей между ними. Благодаря этому и формируется качественная архитектура.

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

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

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

🧱 Модульная архитектура: что, как и почему?

Цель введения разных типов модулей — вывести модульную архитектуру на оптимальный уровень, на котором код легко поддерживать и расширять. Типизация модулей играет большую роль в том, чтобы разные модули были изолированы друг от друга и имели минимальный доступ к информации об их взаимозависимостях. Эта цель достигается с помощью линтеров, которые предотвращают появление зависимостей, которых быть не должно. Например, зависимость модуля api от модуля implementation, модуля implementation от другого модуля implementation или модуля implementation от модуля utility, предназначенного для использования в другой области кода.

🧱 Модульная архитектура: что, как и почему?

А чем, например, модуль utility отличается от модуля implementation?

Давайте более подробно рассмотрим типы модулей, которые я упоминал ранее.

  • API (Application Programming Interface)

Определяет и описывает функциональность и сервисы, которые предоставляет программа (модуль, библиотека), при этом позволяет абстрагироваться от того, как именно эта функциональность и эти сервисы реализованы.

  • Core

Обеспечивает базовую функциональность, которая редко меняется. Как правило, модули core не зависят от конкретного проекта. Поскольку модули core предоставляют базовые абстракции, их можно использовать как часть api.

  • Utility

Обеспечивает целенаправленную, многократно используемую функциональность, которая используется в небольшом количестве связанных модулей implementation . В редких случаях модули utility могут обеспечивать общую функциональность и могут быть использованы во всех модулях implementation. Поскольку модули utility более тесно связаны с implementation и не предоставляют базовых абстракций, они, как правило, меняются чаще, чем модули core, и не могут использоваться в api.

  • Implementation

Содержит классы, необходимые для реализации функций и сервисов, описанных в модулях api. Обычно модули implementation содержат одну или несколько общедоступных точек входа, что позволяет им обеспечивать их реализацию в конечных приложениях с помощью графика области применения. Чтобы предотвратить взаимодействие между функциями и службами, модули implementation не могут зависеть от других модулей implementation.

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

  • Инкапсуляция: модули должны скрывать свою реализацию от внешнего окружения
  • Слабая связность: модули должны взаимодействовать только с помощью заранее оговоренных контрактов
  • Динамичность: модули можно заменять, не останавливая все приложение
***

Модульный подход к архитектуре делает написание кода более простым и динамичным и имеет множество преимуществ: от возможности работать над кодом в команде удаленно до высокого уровня безопасности. Главное — разобраться в том, что такое модульная архитектура и как она работает, и тогда модульный подход сможет оптимизировать работу над вашими проектами и даже улучшить их качество. Надеюсь, эта статья была вам полезна. Удачи!

Как вы применяете модульную архитектуру в своих проектах?

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ