Проектирование границы приложения
Поговорим про архитектурные границы и как их проводить
Введение
Одна из основных задач архитектуры - обеспечение совместной работы программистов и возможности роста приложения. Инструмент, который позволяет достичь нужного результата, - декомпозиция задачи на составные части так чтобы каждая часть могла существовать ничего не зная о других частях. Такого поведения добиваются с помощью проведения "архитектурных границы", в отличии от реальных границ, архитектурные не столь очевидны. Иногда, чтобы увидеть границу нужно построить схему, установить связи и направления взаимодействия всех компонентов системы.
В этом стриме я хочу поговорить про то как формируются архитектурные границы и какие задачи стоят перед архитектором, когда он использует границы в работе. Так же хочу рассмотреть варианты описания требований к системе, которые можно использовать
Важность границ
На уровне кода границы выделяются через файловую структуру, на уровне системы через независимые пакеты развертывания.
Границы необходимы для нескольких целей:
- организационные (каждый должен иметь свою зону ответственности, определенную границей)
- черный ящик (чем меньше деталей мы знаем, тем лучше)
- отделение значимого, от незначимого (в один момент времени мы можем сосредоточиться только на чем-то одном)
- разделение постоянных частей и временных (постоянные - ядро, бизнес-логика, 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.