Проектирование границы приложения

preview

Поговорим про архитектурные границы и как их проводить

Введение

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

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

Важность границ

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

Границы необходимы для нескольких целей:

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

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

Задачи архитектурных границ

Duration: 10

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

Разработка

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

Развертыване

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

Сопровождение

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

Модернизация

Изоляция позволяет полностью переписать один компонент, заменив его новой версией.

Неполные границы

Duration: 7

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

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

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

В книге "Чистая архитектура" Роберт Мартин предлагает сделать все работы по созданию границ на уровне кода:

  • создать абстракции (интерфейсы)
  • разделить задачи на классы
  • создать различия на уровне файловой системы

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

Уровни и границы

Duration: 7

В любой программе есть поток данных, которых как минимум два:

  • поток данных от пользователя;
  • поток данных от устройств хранения данны;

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

Такое разделение называют "уровнями" и наиболее популярный шаблон архитектуры, соответствующий этому разделению, называют трехуровневый.

Сервисная организация приложения

Durtion: 5

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

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

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

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

В целом все рассуждение о службах и сервсиах упирается в одну ошибку - он забыл про "версии". Если научиться пользоваться версионированием данных и протоколов, то проблема независимости просто не стоит.

Проектирование от интерфейса

Duration: 10

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

Но даже при небольшом количестве требований, проектирование от границ требует существенной дополнительной нагрузки, которая требует:

  • собрать данные от пользователя
  • проанализировать данные
  • выработать сущности
  • выработать векторы развития
  • сделать несколько вариантов декомпозиции

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

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

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

Проектирование от интерфейса позволяет быстро делать небольшие монолиты. Точность такого проектирования не очень высокая, но позволяет быстро сделать MVP.

Проектирование от API

Duration: 10

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

Для такого подхода необходимо:

  • получить сущности бизнес-задача
  • описать сущности в виде структур данных
  • построить API основанный на REST подходе, или вызове удаленных процедур
  • построить решение в соответствии с вызовами, которые должны делать в API

Такой вариант очень прост, так по пусти мы сначала определяем как хотим получать и обрабатывать данные, потом реализуем в варианте "один к одному". Разработчикам проще размышлять категориями запроса, бизенс-задачи максимально близко отражаются в API.