Архитектура программного обеспечения - это совсем не просто

Однажды я проснулся от невыносимых звуков бурения. Это начались строительные работы по прокладке новой трамвайной линии. “Насколько все будет плохо?” — подумал я.

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

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

На самом деле такие планы — в порядке вещей и в других отраслях инженерии/архитектуры. Чертежи жилых, электротехнических и машиностроительных объектов составляются с учетом определенных единых требований, чтобы каждый отраслевой инженер смог их прочесть.

Однако в программной инженерии дело обстоит иначе. Хотя в области ПО легко создавать архитектурные схемы (с помощью квадратиков и стрелочек), читать и понимать их не так просто.

Отличительные особенности программной инженерии

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

Проекты программного обеспечения отличаются:

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

Такие коммуникационные разрывы часто встречаются даже в одной команде, не говоря уже о разных командах, организациях и компаниях. Отличия проявляются, например, в схемах архитектуры: либо они сопровождаются объемными формулировками (вспомните 10-страничный дизайн-документ), либо для их объяснения требуется много времени.

Схемы архитектуры ПО на виртуальной доске. Источник: c4model.com

Наметившаяся тенденция в области программной инженерии сделала эти коммуникационные разрывы еще более ощутимыми.

Децентрализация роли архитектора

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

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

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

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

Плата за успех в новых условиях

Описанные выше изменения имеют множество преимуществ: 

  • расширение возможностей и профессиональный рост инженеров всех уровней;
  • повышение чувства ответственности и вовлеченности;
  • устранение единой точки отказа;
  • более эффективное распространение знаний среди команд.

Однако за это приходится платить:

  • Качеством. Архитектор обычно квалифицируется как опытный инженер с практическими навыками создания и поддержки программных систем. Распространение этих задач на всех членов команды означает отсутствие дополнительной квалификации, помимо навыков командной работы. Чтобы поддерживать высокую планку качества, командам необходимо инвестировать в подготовку, обучение и наставничество, выстраивать эффективный процесс проектирования и внедрять культуру открытой обратной связи.
  • Накладными расходами. Наличие надежного процесса проектирования в организации помогает повысить планку качества, но влечет за собой значительные накладные расходы. Обычно такие процессы включают в себя создание проектного документа, системных диаграмм, блок-схем и предполагают процесс обратной связи, который может потребовать непрерывного анализа результатов проекта и корректировки последующих этапов его разработки.

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

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

Практический урок: модель C4

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

Визуализации — ключевая часть проектирования программного обеспечения. Как уже говорилось выше, инженеры описывают ПО очень по-разному, особенно когда дело касается диаграмм.

Диаграммирование → Моделирование

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

Источник: c4model.com. Полный пример представлен на сайте

Модель C4 включает 4 слоя абстракций (отсюда и название).

  1. Контекст системы. Это самый высокий уровень абстракции. Он включает внутренние системы, внешние системы, пользователей (если есть несколько типов пользователей, их следует указать) и отношения между ними.
  1. Контейнер. Определившись с системами, можно сосредоточиться на каждой из них. Система состоит из одного или нескольких контейнеров. Контейнер представляет собой приложение или хранилище данных, например внутренний сервис, внешнее приложение, мобильное приложение, реляционная БД, хранилище ключевых значений, шина сообщений, объектное хранилище и т. д.

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

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

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

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

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

Однако при написании кода бывает полезно подумать: “В какой компонент вписывается мой код?”. Если ответ не ясен, то нужно либо создать новый компонент, либо изменить установленные ранее границы компонентов.

Несколько замечаний по поводу модели C4:

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

Заключение

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

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

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

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Oz Anani: Software Architecture is Hard

Предыдущая статьяNode.js быстрее, чем Go
Следующая статьяОптимизация кода Python с помощью конечных запятых: мощная техника