Лекция 5. Общие аспекты проектирования архитектуры клиент-серверного приложения
Общая структура клиент-серверного взаимодействия со стороны сервера описана ранее.
Однако, нас больше интересует этот же взгляд со стороны клиента, и в этой связи, нет никакой разницы между двухзвенной и трехзвенной архитектурой:
Здесь важно понимание двух вещей:
– Может быть множество клиентов, использующих один аккаунт для общения с севером.
– Каждый клиент, как правило, имеет свое собственное локальное хранилище.
Следует отметить, что поскольку, некоторые разработчики стремятся избавится от «серверной части» некоторые приложения построены вокруг синхронизации их хранилищ в «облаке». Т. е. фактически, имеют так же, двухзвенную систему, но с переносом архитектуры её развертывания на уровень операционной системы. В некоторых случаях такая структура оправдана, но такая система не так легко масштабируется, и её возможности весьма ограничены.
Общая структура приложения
На самом примитивном уровне абстракции приложение, ориентированное на работу с сервером, состоит из следующих архитектурных слоев:
Ядро приложения, которое включает в себя компоненты системы, не доступные для взаимодействия с пользователем.
Графический пользовательский интерфейс.
Компоненты повторного использования: библиотеки, визуальные компоненты и другое.
Файлы окружения: синглтоны, делегаты приложения и т.д.
Ресурсы приложения: графические файлы, звуки, необходимые бинарные файлы.
Наиважнейшим условием построение стрессоустойчивой архитектуры является отделение ядра системы от GUI, настолько, что б одно, могло успешно функционировать без другого. Между тем, большинство RAD систем исходят из противоположного посыла – формы приложения образуют скелет системы, а функции наращивают ей мышцы. Как правило, это оборачивается тем, что не приложение становится ограниченным своим интерфейсом. И, интерфейс приобретает однозначное толкование как с точки зрения пользователя, так и с точки зрения иерархии классов.
Ядро
Ядро приложения, состоит из следующих слоев:
(Start layer) Стартовый слой, определяющий рабочий процесс, начала исполнения программы.
(Network layer) Сетевой слой, обеспечивающий механизм транспортного взаимодействия.
(API layer) Слой API, обеспечивающий единую систему команд взаимодействия между клиентом и сервером.
(Network Cache Layer) Слой сетевого кэширования, обеспечивающий ускорения сетевого взаимодействия клиента и сервера.
(Validation Items Layer) Слой валидации данных полученных из сети
(Network Items Layer) Слой сущности данных передаваемых по сети
(Data Model) Модель данных, обеспечивающая взаимодействие сущностей данных.
(Local cache layer) Слой локального кеширования, обеспечивающий локальный доступ к уже полученным сетевым ресурсам.
(Workflow layer) Слой рабочих процессов, включающий классы и алгоритмы специфичные для данного приложения.
(Local storage) Локальное хранилище
Одна из основных задач стоящие перед разработчиками системы заключается в том, чтобы обеспечить взаимно независимое функционирование указанных слоев. Каждый слой должным обеспечивать только выполнение возложенных на него функций. Как правило, слой находящийся на более высоком уровне иерархии не должен иметь представление о специфике реализации других слоев.
Постановка задачи позволяет выделить несколько подзадач, которые могут быть описаны отдельными классами:
1) Загрузка данных из сети.
Проверка полученных данных.
Сохранение данных в постоянном хранилище.
Вычисление данных.
Фильтрация данных по указанным критериям (настройки приложения)
Класс старта приложения.
2) Обеспечить связанную работу интерфейса, который состоит форм:
3) После запуска приложения на выполнение, производится создание (инстанциирование) объекта, отвечающего за загрузку данных (в подавляющем большинстве случае асинхронную) и начинает процесс. Главный контроллер приложения отображает сплеш-скрин, и в это время, формирует форму, которая займет его место по сокрытию сплэш-формы.
4) По окончании загрузки данных, создается объект-валидатор и объект-провайдер локального хранилища. В случае если данные прошли необходимую валидацию, они могут быть переданы провайдеру локального хранилища.
5) Для отображения данных, создается объект локального хранилища и объект настроек данных. Настройки данных передаются в провайдер локального хранилища для извлечения данных с установленными фильтрами.
6) Для проведения вычислений создаются соответствующие объекты. В объекты передаются данные полученные с форм.
Конечно, данный подход требует больше усилий по программированию, и соответственно, изначально предполагает больше времени. Однако, исходя из подзадач ясно, что, во-первых, работу над ним легко распараллелить – в то время как один разработчик занят формированием ядра – другой, создает и отлаживает UI. Ядро может благополучно работать в рамках консоли, UI прощелкиваться на устройстве (ПК, девайс) и, ко всему прочему, к обеим частям можно прикрутить независимые юнит-тесты. Другим несомненным достоинством является то, что второй подход значительно более масштабируем. В случае пересмотра функциональности проекта, любые изменения будут вносится многократно быстрее, потому что попросту не существует ограничительных рамок визуальных представлений. Сами визуальные формы (GUI) отображают необходимый минимум основанный на существующих в ядре задачах.
Рисунок 1 – Слои ядра приложения
