Перейти к содержимому

Как работает мобильное приложение

  • автор:

Что такое мобильное приложение, и зачем оно вашему проекту

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

Что такое мобильное приложение и как работает?

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

Плюсы мобильного приложения

  1. Упрощенное взаимодействие с пользователем. Приложение может отправлять push-уведомления и находится на устройстве, что упрощает коммуникацию с пользователем.
  2. Возможность более точной персонализации. Так как приложение уже установлено на устройство, при необходимости возможна более точная аналитика действий пользователя, сохранение вводимых им данных и др.
  3. Использование уникальных функций устройства. Мобильное приложение может задействовать уникальный функционал смартфона или планшета, повышая удобство и комфорт пользователя.

Виды мобильных приложений

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

Нативное приложение — это тип мобильного приложения, которое разработано строго под конкретную операционную систему. Такая разработка стоит дороже, но она позволяет максимально персонализировать приложение, сделав его комфортным для пользователя. Подробнее о нативной и кроссплатформенной разработке вы можете узнать в нашей статье «Стоимость разработки мобильного приложения в 2022 году».

Нужно мобильное приложение?

Разработаем для Android, iOS. Поможем определить MVP.

Процесс разработки приложения

Расскажем подробно о каждом этапе разработки приложения для мобильного телефона:

  1. Продуктовая аналитика. Здесь запрашивается описание и видение проекта от заказчика, конкретизируется запрос и проводится анализ рынка. Этот этап включает в себя анализ целевой аудитории, конкурентов, изучение портрета потребителя и т.д. Это нужно для создания продукта, который не только будет стабильно функционировать, но и станет востребованным для выбранной аудитории.
  2. Спецификация и графический прототип. Данный этап проводится для определения технических требований к разработке, которые смогут после реализовать разработчики. Сюда включены требования к логике системы, работа функционала и т.д. Это нужно для подбора наиболее выгодной стратегии разработки, которая будет оптимальной.
  3. Оценка и планирование. Здесь готовится итоговый план работ, стоимость, а также срок реализации приложения. Также учитываются возможные нюансы и принцип работы мобильного приложения, определяются основные действия. Далее подписывается договор, где оговорены все детали, включая стоимость и сроки разработки. А подробнее про стоимость разработки мобильного приложения вы можете узнать здесь.
  4. Дизайн приложения. На этом этапе начинается непосредственная работа над приложением. Разрабатываются дизайн-концепции на выбор. К тому же может добавиться анимацию интерфейса для того, чтобы сделать сервис более «живым». Цель этапа — разработать не только красивый, но и функциональный дизайн.
  5. Программирование. После утверждения дизайна команда приступает к разработке функционала мобильного приложения. Заказчик имеет право ознакомиться с ходом работы. По согласованию с проджект-менеджером проводятся встречи, с помощью которых отслеживается работа над проектом.
  6. Тестирование. Перед запуском проекта нужно убедиться в отсутствии багов в приложении. Для этого проводится тестирование функций мобильного приложения в несколько этапов для корректной работы без ошибок. Тестирование проводится как вручную, так и с помощью специальных сервисов.
  7. Запуск приложения. Это итоговый этап реализации проекта. Приложение готовится к запуску и модерируется в магазине приложений. Затем оно публикуется и может быть доступно пользователям!

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

Зачем нужны мобильные приложения?

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

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

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

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

Итоги

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

Нужно мобильное приложение?

Разработаем для Android, iOS. Поможем определить MVP.

Архитектура мобильного клиент-серверного приложения

К добавлению внешнего сервера рано или поздно приходит любой сложный проект. Причины, при этом, бывают совершенно различные. Одни, загружают дополнительные сведения из сети, другие, синхронизируют данные между клиентскими устройствами, третьи- переносят логику выполнения приложения на сторону сервера. Как правило, к последним относятся большинство «деловых» приложений. По мере отхода от парадигмы «песочницы», в которой все действия выполняются только в рамках исходной системы, логика выполнения процессов переплетается, сплетается, завязывается узлами настолько, что становится трудно понять, что является исходной точкой входа в процесс приложения. В этом момент, на первое место выходит уже не функциональные свойства самого приложения, а его архитектура, и, как следствие, возможности к масштабированию.
Заложенный фундамент позволяет либо создать величественный архитектурный ансамбль, либо «накурнож» — избушку на куриных ножках, которая рассыпается от одного толчка «доброго молодца» коих, за время своего существования повидала видимо — невидимо, потому что, глядя на множественные строительные дефекты заказчик склонен менять не исходный проект, а команду строителей.
Планирование — ключ к успеху проекта, но, именно на него выделяется заказчиком минимальный объем времени. Строительные паттерны — туз в рукаве разработчика, который покрывает неблагоприятные комбинации где время — оказывается решающим фактором. Взятые за основу работающие решения позволяют сделать быстрый старт, чтоб перейти к задачам, кажущиеся заказчику наиболее актуальными (как-то покраска дымоходной трубы, на еще не возведенной крыше).
В этой статье я постараюсь изложить принцип построение масштабируемой системы для мобильных устройств, покрывающей 90-95% клиент-серверных приложений, и обеспечивающей максимальное отдаление от сакраментального «накурножа».

Пока занимался доработкой данной статьи, на хабре вышла аналогичная статья (http://habrahabr.ru/company/redmadrobot/blog/246551/). Не со всеми акцентами автора я согласен, но в целом, мое видение не противоречит и не пересекается с материалом изложенным там. Читатель же, сможет определить, какой из подходов более гибкий, и более актуальный.

  1. Может быть множество клиентов, использующих один аккаунт для общения с севером.
  2. Каждый клиент, как правило, имеет свое собственное локальное хранилище. *

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

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

Общая структура приложения

  1. Ядро приложения, которое включает в себя компоненты системы, не доступные для взаимодействия с пользователем.
  2. Графический пользователь интерфейс
  3. Компоненты повторного использования: библиотеки, визуальные компоненты и другое.
  4. Файлы окружения: AppDelegate, .plist и т. д.
  5. Ресурсы приложения: графические файлы, звуки, необходимые бинарные файлы.

  1. (Start layer) Стартовый слой, определяющий рабочий процесс, начала исполнения программы.
  2. (Network layer) Сетевой слой, обеспечивающий механизм транспортного взаимодействия.
  3. (API layer) Слой API, обеспечивающий единую систему команд взаимодействия между клиентом и сервером.
  4. (Network Cache Layer) Слой сетевого кэширования, обеспечивающий ускорения сетевого взаимодействия клиента и сервера.
  5. (Validation Items Layer) Слой валидации данных полученных из сети
  6. (Network Items Layer) Слой сущности данных передаваемых по сети
  7. (Data Model) Модель данных, обеспечивающая взаимодействие сущностей данных.
  8. (Local cache layer) Слой локального кеширования, обеспечивающий локальный доступ к уже полученным сетевым ресурсам.
  9. (Workflow layer) Слой рабочих процессов, включающий классы и алгоритмы специфичные для данного приложения.
  10. (Local storage) Локальное хранилище
  1. Форма для математических операций (сложение, вычитание)
  2. Форма для отображения графика
  3. Дополнительные формы: сплеш-скрин, about.

Насколько работоспособное данное приложение? Думаю, что ни у кого нет сомнения, что используя Delphi или Visual Studio можно в момент решить эту задачу. Используя Xcode сделать это несколько сложнее, но тоже можно не сильно напрягаясь. Однако, вслед за появлением прототипа, начинают появляться вопросы масштабируемости. Становится очевидным, что для отображения графика необходимо хранить данные за предыдущий период. Не проблема, можно добавить хранилище данных внутрь формы графиков. Однако, данные могут приходить от разных провайдеров и в разных форматах. Кроме того, арифметические операции могут осуществляться с разными валютам, а значит, необходимо обеспечить их выбор. Делать такой выбор на форме графиков — несколько нелогично, хотя и возможно, однако, от таких настроек зависит что именно мы будем отображать на графике. Это означает, что если мы выносим дополнительные параметры в окно настроек, то нам придется как-то их передавать через главную форму в окно графиков. В этом случае логично будет сделать локальную переменную, в которой и хранить передаваемые параметры, и обеспечить доступ из одной форме к другой форме через главную форму. Ну и так далее. Цепочку рассуждений можно строить весьма долго, и сложность взаимодействий будет возрастать.

  1. Проверка полученных данных
  2. Сохранение данных в постоянном хранилище.
  3. Вычисление данных.
  4. операция сложения
  5. операция вычитания
  6. Фильтрация данных по указанным критериям (настройки приложения)
  7. Класс старта приложения.
  1. Главный контроллер (может быть невидимым)
  2. Форма вычисления
  3. Форма графиков
  4. Сплеш и About
  5. Опционально форма настроек.

Конечно, данный подход требует больше усилий по программированию, и соотвественно, изначально предполагает больше времени. Однако, исходя из подзадач ясно, что во-первых, работу над ним легко распараллелить — в то время как один разработчик занят формированием ядра — другой, создает и отлаживает UI. Ядро может благополучно работать в рамках консоли, UI прощелкиваться в девайсе и, ко всему прочему, к обеим частям можно прикрутить независимые юнит-тесты. Другим несомненным достоинством является то, что второй подход значительно более масштабируем. В случае пересмотра функциональности проекта, любые изменения будут вносится многократно быстрее, потому что попросту не существует ограничительных рамок визуальных представлений. Сами визуальные формы (GUI) отображают необходимый минимум основанный на существующих в ядре задачах.

  1. Настройка и обслуживание сессий Facebook
  2. Настройка менеджера вкладок если приложение поддерживает UITabbarController.
  3. Очистка CoreData и сохранение данных при входе в Background.
  4. Проверка и инициализация обновлений
  5. Уведомление внешних серверов статистики
  6. Синхронизация Модели данных
  • Socket — наиболее низкоуровневый подход, включающий в себя синхронные и асинхронные запросы, и имеющий возможность работать как с TCP так и с UDP подключениями. Позволяет делать практически все что угодно, но требует высокой степени концентрации на задаче, не дюжей усидчивости, и большого объема кода.
  • WebSocket — подход опирающийся на использование заголовков поверх TCP. Подробности можно прочесть здесь: habrahabr.ru/post/79038 При мобильной разработке применяется не часто, так как недостаточно гибок, и по прежнему требует довольно большого количества кода для своей поддержки.
  • WCF — наверное самый совершенный механизм, но имеющий столь серьезный минус, который перевешивает все плюсы. Подход изобретенный в недрах Microsoft опирается на создании прокси-класса, который опосредует взаимоотношение между логикой приложения, и удаленным севером. Работает «на ура» в том случае, если удается сгенерировать прокси класс на основе WSDL схем ( en.wikipedia.org/wiki/Web_Services_Description_Language ), что, является задачей, мягко говоря, не тривиальной. К тому же этот класс необходимо перегенерировать после каждого обновления серверного API. И если для разработчиков Visual Studio это делается с легкостью Зефира, то для разработчиков iOS — задача совершенно неподъемная, даже тех кто использует MonoTouch в разработке.
  • REST — надежный, проверенный временем компромис всех перечисленных выше подходов ( ru.wikipedia.org/wiki/REST). Конечно, от части возможностей каждого из подхода приходится отказываться, зато делается это быстро, и чрезвычайно эффективно с минимумом усилий.

GitHub содержит множество библиотек, позволяющих использовать REST соединения, для iOS, наиболее востребованной является AFNetworking.

REST опирается на использование GET, POST, PUT, HEAD, PATCH и DELETE запросов. Такой зоопарк называют RESTFul ( habrahabr.ru/post/144011 ) и, как правило, он применяется только тогда, когда пишется универсальный API для работы мобильных приложений, веб-сайтов, десктопов и космических станций в одной связке.
Подавляющее большинство приложений ограничивает систему команд двумя типами, GET и POST, хотя, достаточно только одного — POST.
GET запрос передается в виде строки, которую Вы используете в браузере, а параметры для запроса передаются разделенные знаками ‘&’. POST запрос так же использует «браузерную строку» но, параметры скрывает внутри невидимого тела сообщения. Последние два утверждения повергают в уныние тех, кто с запросами ранее не сталкивался, в действительности же, технология отработана настолько, что она совершенно прозрачна для разработчика, и не приходится вникать в такие нюансы.
Выше, было описано что отправляется серверу. А вот то, что приходит от сервера — куда интересней. Если Вы используете AFNetworking, то со стороны сервера Вы получите Как правило, iOS разработчики называют JSON- оном сериализированный словарь, но это не совсем так. Истинный JSON имеет чуть более сложный формат, но в чистом виде им практически никогда пользоваться не приходится. Однако, о том, что имеется отличие знать нужно — бывают нюансы.
Если Вы работаете с сервисом, установленным на Microsoft Windows Server, то вероятнее всего, там будет использован WCF. Однако, начиная с Windows Framework 4, имеется возможность для клиентов поддерживающих только REST протокол, сделать доступ совершенно прозрачно, декларативным образом. Вы даже сможете не тратить время на получении пояснений об API — документация о системе команд генерируется автоматически IIS (майкрософтовским веб-сервером).

Ниже приводится минимальный код, для реализации Network Layer при помощи AFNetworking 2 на Objective-C.

Листинг 1

#import "AFHTTPRequestOperationManager.h" NS_ENUM(NSInteger, REQUEST_METHOD) < GET, HEAD, POST, PUT, PATCH, DELETE >; @interface ClientBase : AFHTTPRequestOperationManager @property (nonatomic, strong) NSString *shortEndpoint; - (void)request:(NSDictionary *)data andEndpoint:(NSString *)endpoint andMethod:(enum REQUEST_METHOD)method success:(void(^)(id response))success fail:(void(^)(id response))fail; @end 
#import "ClientBase.h" @implementation ClientBase - (void)request:(NSDictionary *)data andEndpoint:(NSString *)endpoint andMethod:(enum REQUEST_METHOD)method success:(void(^)(id response))success fail:(void(^)(id response))fail < self.requestSerializer = [AFJSONRequestSerializer serializer]; if(data == nil) data = @<>; AFHTTPRequestOperation *operation = [self requestWithMethod:method path:endpoint parameters:data success:success fail:fail]; [operation start]; > - (AFHTTPRequestOperation *)requestWithMethod:(enum REQUEST_METHOD)method path:endpoint parameters:data success:(void(^)(id response))success fail:(void(^)(id response))fail < switch (method) < case GET: return [self requestGETMethod:data andEndpoint:endpoint success:success fail:fail]; case POST: return [self requestPOSTMethod:data andEndpoint:endpoint success:success fail:fail]; default: return nil; >> - (AFHTTPRequestOperation *)requestGETMethod:(NSDictionary *)data andEndpoint:(NSString *)endpoint success:(void(^)(id response))success fail:(void(^)(id response))fail < return [self GET:endpoint parameters:data success:^(AFHTTPRequestOperation *operation, id responseObject) < [self callingSuccesses:GET withResponse:responseObject endpoint:endpoint data:data success:success fail:fail]; [KNZHttpCache cacheResponse:responseObject httpResponse:operation.response]; >failure:^(AFHTTPRequestOperation *operation, NSError *error) < NSLog(@"\n\n--- ERROR: %@", operation); NSLog(@"\n--- DATA: %@", data); [self callingFail:fail error:error]; >]; > - (AFHTTPRequestOperation *)requestPOSTMethod:(NSDictionary *)data andEndpoint:(NSString *)endpoint success:(void(^)(id response))success fail:(void(^)(id response))fail < return [self POST:endpoint parameters:data success:^(AFHTTPRequestOperation *operation, id responseObject) < [self callingSuccesses:POST withResponse:responseObject endpoint:endpoint data:data success:success fail:fail]; >failure:^(AFHTTPRequestOperation *operation, NSError *error) < NSLog(@"\n\n--- ERROR: %@", operation); NSLog(@"\n--- DATA: %@", data); [self callingFail:fail error:error]; >]; > - (void)callingSuccesses:(enum REQUEST_METHOD)requestMethod withResponse:(id)responseObject endpoint:(NSString *)endpoint data:(NSDictionary *)data success:(void(^)(id response))success fail:(void(^)(id response))fail < if(success!=nil) success(responseObject); >- (void)callingFail:(void(^)(id response))fail error:(NSError *)error < if(fail!=nil) fail(error); >@end 

Этого вполне достаточно чтоб передавать сетевые GET и POST сообщения. В большинстве своем, Вам не потребуется больше корректировать эти файлы.

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

Класс унаследован от ClientBase. Код класса настолько просто, что нет необходимость даже приводить его целиком — он состоит их единообразного описания API:

Листинг 2

#define LOGIN_FACEBOOK_ENDPOINT @"/api/v1/member/login/facebook/" #define LOGIN_EMAIL_ENDPOINT @"/api/v1/member/login/email/" - (void)loginFacebook:(NSDictionary *)data success:(void(^)(id response))success fail:(void(^)(id response))fail < [self request:data andEndpoint:LOGIN_FACEBOOK_ENDPOINT andMethod:POST success:success fail:fail]; >- (void)loginEmail:(NSDictionary *)data success:(void(^)(id response))success fail:(void(^)(id response))fail

Как говорится: «Ничего лишнего».

Network Cache Layer:
Данный слой кеширования задействуется для ускорения сетевого обмена между клиентом и сервером на уровне iOS SDK. Выбор ответов осуществляется стороной лежащей за пределами контроля системы, и не гарантирует снижение сетевого трафика, но ускоряет его. Доступа к данным или механизмам реализации нет ни со стороны приложения, ни со стороны системы. При этом используется SQLite хранилище.

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

Листинг 3

 #define memoCache 4 * 1024 * 1024 #define diskCache 20 * 1024 * 1024 #define DISK_CACHES_FILEPATH @"%@/Library/Caches/httpCache" - (void)start

Вызвать нужно из любого места приложения однократно. Например из стартового слоя.

  • Для какого аккаунта произошла ошибка.
  • Какая команда вызвала ошибку.
  • Какие данные были переданы серверу.
  • Какой ответ был получен от сервера.
  • Время UTC*
  • Статус код команды. Для ошибок валидации он всегда 200.
  • Схема, которой не удовлетворяет ответ сервера.

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

Каждая схема, как и каждая команда, обязана удовлетворять определенным оговоренным ранее критериям. В приведенном примере ответ сервера должен содержать два основных и одно опциональное поле.
«status» обязательное. Содержит идентификатор OK или ERROR (или код HTTP типа «200»).
«reason» обязательное Содержит текстовое описание причины ошибки, если она возникла. В противном случае — это поле пустое.
«data» опциональное. Содержит результат выполнения команды. В случае ошибки отсутствует.
Пример схемы:

Листинг 4

< "title": "updateconfig", "description": "/api/v1/member/updateconfig/", "type":"object", "properties": < "reason": < "type":"string", "required": true >, "status": < "type":"string", "required": true >, "data": < "type":"object" >>, "required": ["reason", "status"] > 

Благодаря библиотеке разработанной Максимом Луниным сделать это стало очень просто. ( habrahabr.ru/post/180923 )

Код класса валидации приводится ниже

Листинг 5
ResponseValidator.h

 #import "ResponseValidator.h" #import "SVJsonSchema.h" @implementation ResponseValidator + (instancetype)sharedInstance < static ResponseValidator *sharedInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^< sharedInstance = [[ResponseValidator alloc] init]; >); return sharedInstance; > #pragma mark - Methods of class + (void)validate:(id)response endpoint:(NSString *)endpoint success:(void(^)())success fail:(void(^)(NSString *error))fail < [[м sharedInstance] validate:response endpoint:endpoint success:success fail:fail]; >+ (NSDictionary *)schemeForEndpoint:(NSString *)endpoint < NSString *cmd = [[ResponseValidator sharedInstance] extractCommand:endpoint]; return [[ResponseValidator sharedInstance] validatorByName:cmd]; >#pragma mark - Methods of instance - (void)validate:(id)response endpoint:(NSString *)endpoint success:(void(^)())success fail:(void(^)(NSString *error))fail < NSString *cmd = [self extractCommand:endpoint]; NSDictionary *schema = [self validatorByName:cmd]; SVType *validator = [SVType schemaWithDictionary:schema]; NSError *error; [validator validateJson:response error:&error]; if(error==nil) < if(success!=nil) success(); >else < NSString *result = [NSString stringWithFormat:@"%@ : %@", cmd, error.description]; if(fail!=nil) fail(result); >> - (NSString *)extractCommand:(NSString *)endpoint < NSString *cmd = [endpoint.stringByDeletingLastPathComponent lastPathComponent]; return cmd; >- (NSDictionary *)validatorByName:(NSString *)name < static NSString *ext = @"json"; NSString *filePath = [[NSBundle mainBundle] pathForResource:name ofType:ext]; NSString *schema = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; if(schema == nil) return nil; NSData *data = [schema dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; return result; >@end 

Вызов валидации довольно прост:
Листинг 6

 [ResponseValidator validate:responseObject endpoint:endpoint success:^ < /* Валидация прошла успешно, вызываем конвейер обработки команды */ >fail:^(NSString *error) < /* Валидация провалена. Можем что-то сделать, а можем просто игнорировать результат. Зависит от религиозных предпочтений. */ >]; 

Network Items layer:
Именно на этот слое лежит ответственность за маппинг данных из JSON в десериализированное представление. Данный слой используется для описания классов, осуществляющих объектное или объектно-реляционное преобразование. В сети существует большое количество библиотек, осуществляющих объектно-релационные преобразования. Например JSON Model ( github.com/icanzilb/JSONModel ) или все та же библиотека Максима Лунина. Однако, не все так радужно. От проблем маппинга они не избавляют.

  1. Десериализированный объект данных в Objective-C не может иметь поля «id» при использовании CoreData
  2. Сериализированные данные в поле «id» и «ident» могут содержать как строку, так и NSNumber. При выводе их на консоль, разницы между двумя числами не будет, но. хешкод у них будет разный, и словарь будет по разному воспринимать значение этих полей.
  3. Отличия между именами полей являются ответственностью сервера, и серверные разработчики могут просто не идти на контакт, в том, чтоб заменить их имена на единообразные, удобные клиентским разработчикам.

Local cache layer:

  1. Кеширование загружаемых из сети изображений.
  2. Кеширование запросов / ответов сервера
  3. Формирование очереди запросов в случае отсутствия сети и работы пользователя оффлан.
  4. Мониторинг кешированных данных и очистка данных, срок жизни которых истек.
  5. Уведомление приложения о невозможности получить информацию о заданном объекте из сети.

Листинг 7

- (void)request:(NSDictionary *)data andEndpoint:(NSString *)endpoint andMethod:(enum REQUEST_METHOD)method success:(void(^)(id response))success fail:(void(^)(id response))fail queueAvailable:(BOOL)queueAvailable < self.requestSerializer = [AFJSONRequestSerializer serializer]; if(data == nil) data = @<>; // Returning cache response. NSDictionary *cachedResponse = [HttpCache request:endpoint]; if(cachedResponse !=nil) < [self callingSuccesses:method withResponse:cachedResponse endpoint:endpoint data:data success:success fail:fail]; return; >AFHTTPRequestOperation *operation = [self requestWithMethod:method path:endpoint parameters:data success:success fail:fail]; [self consoleLogRequest:data operation:operation]; [operation start]; > - (AFHTTPRequestOperation *)requestPOSTMethod:(NSDictionary *)data andEndpoint:(NSString *)endpoint success:(void(^)(id response))success fail:(void(^)(id response))fail < return [self POST:endpoint parameters:data success:^(AFHTTPRequestOperation *operation, id responseObject) < [self callingSuccesses:POST withResponse:responseObject endpoint:endpoint data:data success:success fail:fail]; [HttpCache cacheResponse:responseObject httpResponse:operation.response]; >failure:^(AFHTTPRequestOperation *operation, NSError *error) < NSLog(@"\n\n--- ERROR: %@", operation); NSLog(@"\n--- DATA: %@", data); [self callingFail:fail error:error]; >]; > 

В классе HttpCache по-мимо методов сохранения результатов запроса имеется еще один, интересный метод:

Листинг 8

#define CacheControlParam @"Cache-Control" #define kMaxAge @"max-age spoiler">Листинг 9
- (void)request:(NSDictionary *)data andEndpoint:(NSString *)endpoint andMethod:(enum REQUEST_METHOD)method success:(void(^)(id response))success fail:(void(^)(id response))fail queueAvailable:(BOOL)queueAvailable < self.requestSerializer = [AFJSONRequestSerializer serializer]; if(data == nil) data = @<>; if(queueAvailable) < [HttpQueue request:data endpoint:endpoint method:method]; >AFHTTPRequestOperation *operation = [self requestWithMethod:method path:endpoint parameters:data success:success fail:fail]; [operation start]; > 

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

Проверка подключения к сети осуществляется с помощью классов AFNetworkReachabilityManager или Reachability от Apple ( developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html ) совместно с паттерном наблюдатель. Его устройство слишком примитивно, чтоб описывать в рамках статьи.
Однако, не все запросы должны быть отправлены в очередь. Некоторые из них могут не быть актуальными к моменту появления сети. Решить какие из команд дожны быть записаны в кеш очереди, а каки быть актуальны толко в момент вызова можно как на уровне слоя кеширования, так и на уровне слоя API.

В первом случае, в листинг 9, вместо вызова метода сохранения в очередь, необходимо вставить виртуальный метод, и унаследовать от класса ApiLayer унаследовать классы LocalCacheLayerWithQueue и LocalCacheLayerWithoutQueue. После чего в заданном виртуальном методе класса LocalCacheLayerWithQueue сделать вызов [HttpQueue request: endpoint: method:]

Во втором случае немного изменится вызов запроса из класса ApiLayer

Листинг 10

- (void)trackNotification:(NSDictionary *)data success:(void(^)(id response))success fail:(void(^)(id response))fail

В листинге 9 именно для такого случая предусмотрено условие if(queueAvailable).

Так же, отдельным вопросом является вопрос кеширования изображений. В общем-то, вопрос не сложный, и оттого, имеющий бесконечное количество реализаций. К примеру, библиотека SDWebImage делает это весьма успешно: ( github.com/rs/SDWebImage ).

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

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

Листинг 11

#define LOCAL_CACHES_IMAGES_FILEPATH @"%@/Library/Caches/picture%ld.jpg" - (void)loadImage:(NSString*)link success:(void(^)(UIImage *image))success fail:(void(^)(NSError *error))fail < UIImage *image = [ImagesCache imageFromCache:link.hash]; if(image == nil) < dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^< __block NSData *data; __block UIImage *remoteImage; __block NSData *dataImage; __block NSString *imgFilePath = [NSString stringWithFormat:LOCAL_CACHES_IMAGES_FILEPATH, NSHomeDirectory(), (unsigned long)link.hash]; data = [NSData dataWithContentsOfURL: [NSURL URLWithString:link]]; // Reading DATA if(data.length >0) < remoteImage = [[UIImage alloc] initWithData: data]; // TRANSFORM DATA TO IMAGE if(remoteImage!=nil) < dataImage = [NSData dataWithData:UIImageJPEGRepresentation(remoteImage, 1.0)]; // TRANSFORM IMAGE TO JPEG DATA if(dataImage!=nil && dataImage.length >0) [dataImage writeToFile:imgFilePath atomically:YES]; // Writing JPEG file > else // try to fix BINARY image type (first method) < [dataImage writeToFile:imgFilePath atomically:YES]; remoteImage = [UIImage imageWithContentsOfFile:imgFilePath]; >> else // try to fix BINARY image type (second method) < NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:link]]; NSURLResponse *response = nil; NSError *error = nil; data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error]; if (error == nil) < remoteImage = [[UIImage alloc] initWithData: data]; // TRANSFORM DATA TO IMAGE if(remoteImage!=nil) < dataImage = [NSData dataWithData:UIImageJPEGRepresentation(remoteImage, 1.0)]; // TRANSFORM IMAGE TO JPEG DATA if(dataImage!=nil && dataImage.length >0) [dataImage writeToFile:imgFilePath atomically:YES]; // Writing JPEG file > NSLog(@"USED SECONDARY METHOD FOR LOAD OF IMAGE"); > else NSLog(@"DATA WASN'T LOAD %@\nLINK %@", error, link); > dispatch_async(dispatch_get_main_queue(), ^ < if(remoteImage!=nil && success!=nil) < success(remoteImage); [ImagesCache update:link.hash]; >else < if(data.length == 0) NSLog(@"%@", @"\n============================\nDETECTED ERRROR OF DOWNLOAD IMAGE\nFILE CAN'T LOAD\nUSED PLACEHOLDER\n============================\n"); else NSLog(@"%@", @"\n============================\nDETECTED ERRROR OF DOWNLOAD IMAGE\nUSED PLACEHOLDER\n============================\n"); NSLog(@"LINK %@", link); UIImage *placeholder = [LoadImage userPlaceholder]; if (success) success(placeholder); // if(fail!=nil) // fail([NSError errorWithDomain:[NSString stringWithFormat:@"%@ not accessible", link] code:-1 userInfo:nil]); >>); >); > else < success(image); >> 

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

Когда речи идет о чтении файла из бандла приложения, имеется нюанс, который забывают разработчики: iOS SDK предоставляет нам такие методы как [UIImage imageNamed:] и [UIImage imageWithContentsOfFile:]. Использовать первый проще, но он существенно влияет на загруженность памяти — дело в том, что файл загруженный при помощи него, остается в памяти устройства, до тех пор, пока приложение не будет завершено. Если это файл, который имеет большой объем, то это может стать проблемой. Рекомендуется использовать второй метод, как можно чаще. Кроме того, полезно сделать небольшое усовершенствование в метод загрузки:

Листинг 12

+ (UIImage *)fromBundlePng:(NSString *)name < return [[LoadImage sharedInstance] fromBundlePng:name]; >- (UIImage *)fromBundle:(NSString *)name < return [self downloadFromBundle:name.stringByDeletingPathExtension ext:name.pathExtension]; >- (UIImage *)downloadFromBundle:(NSString *)name ext:(NSString *)ext < NSString *filePath = [[NSBundle mainBundle] pathForResource:name ofType:ext]; if(filePath == nil) < NSString *filename = [NSString stringWithFormat:@"%@@2x", name]; filePath = [[NSBundle mainBundle] pathForResource:filename ofType:ext]; >return [UIImage imageWithContentsOfFile:filePath]; > 

Теперь Вам не придется задаваться вопросом, в какой резолюции присутствует файл.

Workflows layer:
Все реализованные алгоритмы, которые не относятся к слоям ядра, и не представляют собой GUI должны быть вынесены в классы специфических последовательностей рабочих процессов. Каждый из этих процессов оформляется в своем стиле, и подключается к основной части приложения путем добавления ссылок на экземпляр соответствующего класса в GUI. В подавляющем большинстве случаев, все эти процессы являются не визуальными. Однако имеются некоторые исключения, например, когда необходимо осуществить длинную последовательность предопределенных кадров анимации, с заданными алгоритмами отображения
Вызывающий код должен иметь минимальные знания об этой функциональности. Все настройки flow должны быть инакапсулированы. Google в качестве примера приводит код для уведомления из сервера аналитики, и предлагает включить его в место, где событие возникает.

Листинг 13

 // Analytics [Analytics passedEvent:ANALYTICS_EVENT_PEOPLE_SELECT ForCategory:ANALYTICS_CATEGORY_PEOPLE WithProperties:nil]; 

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

Существуют довольно развитые рабочие процессы, логика функционирования которых зависит от внутренного состояния. Такие процессы должны быть реализованы при помощи паттернов «Стратегия» или «Машина состояний». Как правило, совместно с паттерном «стратегия» используется паттерн «медиатор» который опосредует обращение к тому или иному алгоритму.
Один из часто используемых процессов — процесс авторизации пользователя — очевидный претендент на рефаторинг с использованием паттерна «машины состояний». При этом, именно на этом flow должна лежать ответственность за «автоматическую» авторизацию пользователя, а не рекурсивным образом вызываться из абстрактных слоев (Network Layer, или Validation Items).

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

Local storage:
Желание разработчиков находится в тренде новых технологий, порой, сталкивается со здравым смыслом, и, последний часто проигрывает. Одно из веяний моды было использование локального хранилища на основе CoreData. Некоторые разработчики настаивали, что его нужно использовать в как можно большем количестве проектов, не смотря на то, что даже сама Apple признавала, что есть определенные трудности.
Существует большое количество способов сохранение временных данных в постоянном хранилище устройства. Использование CoreData оправдано в том случае, когда нам необходимо хранить большое количество редко обновляемых данных. Однако, если в приложении имеется несколько сот записей, и ни постоянно обновляются скопом использование CoreData в этих целях неоправданно дорого. Таким образом, получается, что большую часть времени ресурсов устройство тратит на синхронизацию данных полученных из сети, с теми данными которые уже есть на устройстве, несмотря на то, что весь массив данных, будет обновлён во время следущей сессии.

Использование CoreData ( habrahabr.ru/post/191334 ), кроме того, требует также соблюдение определённых процедур, алгоритмов и архитектурных решений, что ограничивает нас в выборе стратегии разработки, а так же существенно осложняет механизмы отладки нашего приложения.

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

Локальное хранилище на основе файловой системы

  1. данные в массивах могут быть представлены точно в той последовательности, в которой они были получены от сервера.
  2. данные однозначно соответствуют используемому запросу к серверу, с точностью до передаваемых параметров в POST запросе (т. е. легко было отличить объекты полученный от определенной команды, от объекта полученного от той же команды, но с другими данными, переданными в качестве параметров POST пост запроса).
  3. Атомарность записи объекта данных в постоянное хранилище.
  4. Мгновенность и атомарность чтение данных из постоянного хранилища.
  5. Полное соответствие ACID транзактности: en.wikipedia.org/wiki/ACID
  6. Отсутствие необходимости в нормализации данных.
  7. Независимость в интерпретации данных.
  8. Все данные всегда актуальны.
  9. Объем кода поддержки минимален (1 строка).

Средства чтения / записи iOS SDK делает NSDictionary идеальным форматом сохранения относительно небольших короткоживущих данных, поскольку для этого применяются однопроходные алгоритмы.

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

Отрицательной стороной такого подхода считается, что это плохо влияет на производительность устройства, однако, изучение вопроса показывает, что объем таких данных не превышает 5Кбайт, данные загружаются в память мгновенно, единым блоком, и таким же образом освобождаются из памяти, сразу же после того, как в них отпадает необходимость, например, когда ViewController перестает существовать. В то же время чтение данных блоками (построчно) из базы данных SQL порождает большое количество объектов (на уровне выходящем за рамки контроля приложения), которые суммарно превышают указанный объем, к тому же, создают дополнительную нагрузку на процессор. Использование центрального хранилище оправдано тогда, когда данные должны сохраняться долгое время, на протяжении многих сессий работы приложения. При этом, данные из сети загружаются частично.

Локальное хранилище на основе CoreData.

CoreData не предоставляет возможности для использование сериализированных данных. Все данные должны быть подвергнуты объектно-реляционным преобразованиям, до их использования слоем локального хранилища. После получения данных от команды API profile, происходит передача данных в метод категории copyDataFromRemoteJSON, где из словаря извлекаются данные, а затем уже сохраняются в соответствующем управляемом объекте (потомокк класса NSManagedObject).
Вот пример того, как это происходит:

Листинг 14

 [[Client client] profile:@<> success:^(id response) < [[Member getCurrentMember] copyDataFromRemoteJSON:[response valueForKey:@"data"]]; >fail:^(id response) < >]; 

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

  1. Пользователю отображаются данные которые присутствуют в системе сразу после запуска приложения.
  2. Производится запрос на получение тех же данных с удаленного сервера, так как сервер должен подтвердить их актуальность. Этот запрос подтверждает авторизацию приложения.
  3. Если данные с сервера получены, то авторизация осуществлена успешно, и производится циклическая загрузка остальных данных.
  4. Если сервер не подтверждает авторизацию (срок жизни токена истек) все данные локальной системы удаляются. Пользовательский интерфейс обновляется.
  5. Полученные данные синхронизируются с содержимым локального хранилища. (Т. е. каждый объект частично вычитывается из локального хранилища, проверяется, есть ли идентификатор такого объекта, если такой идентификатор уже есть, данные игнорируются/обновляются, если его нет, данные добавляются).
  6. После того, как процесс записи осуществлен полностью интерфейс пользователя обновляется

Преимущества данного подхода:
Гипотетически считается, что ленивая загрузка при помощи NSFetchController позволяет существенно ускорить отображение данных из базы данных, когда их количество составляет несколько тысяч записей. Так же, добавление данных в базу уменьшает количество передаваемой информации по сети. Данные добавляются. Те что есть- показываются пользователю. Пользователь может удалить данные которые ему не нужны. Данные добавляются в те, объекты, которые уже существуют, как элементы их массива.

  1. В первую очередь к надостаткам подхода необходимо отнести все те преимущества, которые были рассмотрены выше (подход на основе файловой системы):
  2. Последовательность отображения данных на экране не гарантируется, поскольку, данные извлекаются из SQLite базы данных, а там они лежат в «натуральном» порядке. Для создания последовательного отображения требуется вводить атоинкрементный номер, или какой-либо другой механизм, которые не предоставляется, ни CoreData ни SQLite.
  3. Данные никак не связаны с сетевыми запросами, что сильно осложняет их отладку.
  4. Сохранение данных в локальном хранилище происходит атомарно для всего контекста. Но, между вызовами записи данные могут быть потеряны, или перезатерты. Кроме того, процедура сохранения в базе может быть не вызвана.
  5. Большие объемы данных извлекаются из Database с существенно большей скоростью чем чтение плоского файла, однако, для сравнительно небольших файлов, скорость все равно будет выше.
  6. ACID не применим к SQLite в реализации с CoreData. Одновременная запись разных контекстов из разных потоков легко приводит к крешам приложения. Частично проблема решается путем использования библиотеки MagicRecords.
  7. Для нормализации данных необходимо применять специальные процедуры. Если некоторые поля заполняются по определенному условию, а объем данных возрастает, то либо данные необходимо дробить на большое количество объектов, либо извлекать из них абстрактные сущности, либо применять специальные процедуры для удаления устаревающих данных.
  8. Данные в CoreData всегда реляционны. Поэтому этому вопрос независимости рассматриваться может только в том случае, если схема CoreData не содержит связей между элементами.
  9. Поскольку актуальность данных определяется сервером, а не приложением, то данные которые не были получены из сети, все равно приходится удалять. Таким образом, использование CoreData никак не влияет на сетевой трафик в данной схеме.
  10. Объем кода многократно превышает тот, который необходим для обслуживания хранилища на основе файловой системы. Так же, использование CoreData налагает определенные ограничения и на пользовательский интерфейс.
  1. CoreData требует определенной дисциплины для работы из различных потоков приложения, и выборе актуального контекста.
  2. Синхронизация данных может настолько снижать производительность устройства, что вопрос об использовании 4S аппаратов будет весьма актуальным.
  3. Сильно осложнена отладка приложений. Некоторые операции неочевидные, и для поиска ошибочного поведения приходится изучать библиотеку MagicalRecords (https://github.com/magicalpanda/MagicalRecord) или дописывать свои классы и категории.

При использовании библиотеки MagicalRecords возникает ситуация, когда для правильного функционирования приложения табличное представление должно быть частью UITableViewController, иначе становится затруднительным использование NSFetchController лежащий в основе загрузки данных CoreData. Таким образом, существует зависимость в использовании пользовательского интерфейса, от локального хранилища. Т. е. имплементация CoreData ограничивает в разработке UI.

Альтернативный взгляд

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

Альтернатива 1
Произвести нормализацию данных API сервера. Сервер должен возвращать не полный иерархический объект, с множеством вложенных сущностей, а множество мелких объектов, которые легко добавляются в базу данных.
В этом случае:
Загружаться будут небольшие порции свежих данных, что уменьши сетевой трафик.
Приложение сможет сделать запрос к серверу с идентификаторами объектов, чтоб сервер вернул список того, что необходимо удалить.
Отпадает необходимость в синхронизации получаемых данных для каждой загружаемой записи.

  1. Сериализировать данные «на лету» в двоичные объекты на основе JSON схемы.
  2. Обеспечить функционирования этого механизма на уровне Слоя Ядра, т. е. прозрачно для разработчика.
  3. Мгновенно переключаться между контекстами пользователей.
  4. Удалять неактуальные записи по мере их устаревания, на основе информации заданной сервером в заголовке ответа.
  5. Не смотря на использование SQLite сервера данные не потребуют нормализации.
  6. Существенно сократить количество используемого кода.

Заключение:
Статья получилась довольно длинной, и, сомневаюсь, что большинство читателей осилят ее до конца. По этой причине, часть, связанную с GUI я решил отсюда выкинуть. Во-первых, она относилась к построению пользовательского интерфейса через UITabbar, а во-вторых, в одной из скайп групп, состоялась весьма интересная дискуссия относительно использования широко известных паттернов MVC и MVVM. Излагать принципы построения интерфейса не имеет смысл без скурпулезного изложения существущих практик и подходов, которые заводят разработчиков в тупик. Но это тема большой еще одной многостраничной статьи. Здесь же, я постарался рассмотреть лишь вопросы, связанные с функционированием ядра приложения.
Если читатели проявят достаточный интерес к этой тематике, то в ближайшее время постараюсь выложить исходные классы, для использование в качестве шаблона приложения.

  • архитектура приложений
  • ios development
  • ios разработка
  • Программирование
  • Совершенный код
  • Разработка под iOS
  • Разработка мобильных приложений
  • Проектирование и рефакторинг

Архитектура мобильного приложения

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

Что такое архитектура веб-приложений?

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

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

Хорошо построенная архитектура должна соответствовать следующим критериям:

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

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

Как работает архитектура мобильного приложения

Как работает архитектура мобильного приложения

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

Как это работает: например, вы вводите в поисковой строке адрес веб-приложения. Запрос идет на сервер, получает ответ и перед вами открывается страница. В ней есть поле, куда можно ввести свои данные. Вы визуально видите его, потому что это внешний интерфейс и клиентская часть. Вы вводите туда свои данные, нажимаете на кнопку «Отправить» и в это время начинает работать серверная часть. Информация заносится в базу данных, происходит цепочка событий, и вы получаете ответ. Например, производится авторизация в приложении. Архитектура приложения нужна для того, чтобы подобные процессы корректно работали и каждая функция реализовывалась.

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

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

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

Модели архитектуры приложений

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

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

MPA или многостраничные приложения. Несмотря на уменьшенную скорость загрузки, MPA архитектуру используют крупные компании, такие как eBay или Amazon. Загрузить всю информацию на одной странице просто не получится, слишком много серверных процессов и компонентов. Для крупных компаний – это хорошее решение.

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

PWA приложения. Это решения, которые дают возможность лучше взаимодействовать с пользователем. На устройство ставится приложение, выглядит, как нативное, но при этом оно работает через веб-ресурсы. Пример такого приложения – Pinterest.

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

Из чего состоит архитектура мобильных приложений

Из чего состоит архитектура мобильных приложений

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

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

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

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

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

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

Как происходит проектирование приложения

Как происходит проектирование приложения

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

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

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

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

Проектирование имеет несколько способов реализации:

Монолитный подход. Считается одним из «древних», но при этом работает безотказно. Его принцип работы простой: вся логика приложения хранится на сервере, а в базе данных – информация для этого сервера. Такой подход позволяет быстро разработать мобильное приложение, но имеет недостаток. В дальнейшем, когда необходимо поменять интерфейс или обновить функционал, чтобы соответствовать новым платформам, монолитность создает сложности.

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

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

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

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

Приложение

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

«IT-специалист с нуля» — наш лучший курс для старта в IT

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

Вот несколько примеров мобильных приложений:

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

А веб-приложения — это в основном сложные сервисы, например образовательные платформы, браузерные игры и социальные сети.

16 месяцев
Android-разработчик

Запускайте приложения и игры для Android

Group 1321314280 (3)

Кто создает приложения

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

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

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

Сколько стоит разработка мобильного приложения. Источник

Для чего нужны приложения

Часто приложение — это более удобный способ выполнять какие-то действия. Например, банковское приложение. Человек может обойтись без него: пойти в банк, сделать перевод через банкомат или кассу. Но это долго и неудобно, тогда как через приложение все можно сделать автоматически в несколько кликов. И кстати, онлайн-банк — тоже приложение, только веб.

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

Примеры вещей, которые мы обычно делаем с помощью приложений:

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

13 месяцев
iOS-разработчик

Создавайте приложения, которые выйдут в топ App Store

Какими бывают приложения

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

Клиентскими. Это программы для широкого круга пользователей: например, приложение для просмотра картинок, клиент социальной сети или мессенджера, календарь и будильник. Обычно такие приложения можно скачать через специальные магазины вроде Google Play или App Store или они поставляются предустановленными вместе с устройством. Второй случай обычно касается базовых программ: браузера, калькулятора и так далее.

Профессиональными. Частный случай клиентских программ: приложения «не для всех», а только для узкого круга людей. Например, приложение для курьеров, работающих в какой-то компании. Или приложение внутренней системы, через которую в компании работает документооборот. Таких программ может даже не быть в магазинах, но даже если они там есть — функциями можно пользоваться только после того, как работодатель даст доступ.

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

Не нужно путать служебные приложения с предустановленными клиентскими. Есть системные программы, например приложение для обновления компонентов, но ими может пользоваться человек. А служебными — нет.

Станьте iOS-разработчиком — работайте
в штате, на фрилансе или запускайте собственные приложения

Что такое магазин мобильных приложений

Мобильные приложения можно скачать через специальные магазины. Для каждой операционной системы магазин свой. Для Android это Google Play, для iOS — App Store. Это официальные магазины. Еще есть неофициальные, обычно от производителей смартфонов, например от Xiaomi и Huawei.

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

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

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

Как устроено приложение внутри

И мобильное, и веб-приложение состоит из двух основных частей: клиентской и серверной.

  • Клиентская часть — та, с которой взаимодействует пользователь. Это интерфейс, дизайн, функциональные объекты и логика их работы, то есть все, что видит пользователь. Например, если вы нажимаете на кнопку и экран меняет цвет — это скорее всего реализовано в клиентской части. В web-приложениях это называется фронтендом.
  • Серверная часть — то, что не видит пользователь. Сервер принимает запросы, которые пришли с клиента, например «подгрузи такие-то данные», и выполняет их. Он связывается с базой данных, отправляет туда запрос, получает информацию и отправляет на клиент. Это внутренняя, невидимая часть работы приложения. В вебе это называют бэкендом.

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

Мобильные приложения с технической точки зрения

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

Нативные. Такие приложения написаны на языке, «родном» для операционной системы. Для iOS это Swift, для Android — Java и Kotlin. Программы созданы специально для архитектуры конкретной ОС, могут глубоко интегрироваться в систему и пользоваться ее возможностями. Поэтому нативные приложения работают быстрее и часто функциональнее. Но их можно запустить только на одной ОС. Написанное на Swift приложение для iOS не получится быстро перенести на Android. Его понадобится переписывать чуть ли не с нуля на другом языке и с учетом другой архитектуры системы.

Ненативные. Их еще называют кроссплатформенными. Такие приложения пишут с помощью отдельных технологий, не «родных» ни для iOS, ни для Android. Например, есть React Native, с помощью которого можно писать программы для мобильных на React JS и даже пользоваться возможностями системы. Есть Electron — оболочка в виде браузера, которая позволяет писать приложения с помощью веб-технологий. Ненативные приложения легко портировать на другую ОС, но они часто медленнее и более требовательны к ресурсам, а еще лишены части возможностей нативных.

Станьте Android-разработчиком — работайте в штате, на фрилансе или запускайте собственные приложения

Чем различаются приложения для iOS и Android

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

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

Но это не значит, что можно скачать ненативное приложение для Android и запустить его на iOS. Для разных систем такие программы собирают по-разному, просто это быстрее, чем переписывать все приложение с нативным подходом. А в магазины поступают уже собранные версии под конкретную систему.

Чем веб-приложения отличаются от сайтов

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

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

Как выглядит разработка приложения

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

  1. Описание идеи и проектирование. Тут задействованы аналитики, менеджеры и архитекторы. Они решают, как будет выглядеть приложение, с помощью каких технологий его написать, что оно будет уметь.
  2. Создание макетов интерфейса. Дизайнеры продумывают интерфейс, например список экранов и форм, цветовую гамму и дизайн. Они рисуют макеты, на которые программисты будут ориентироваться при разработке.
  3. Разработка и верстка. Обычно серверную и клиентскую часть разрабатывают разные люди, которые тем не менее общаются между собой. Разработчиками управляет проектный менеджер, еще они могут консультироваться с дизайнерами, архитекторами и другими специалистами.
  4. Тестирование. Тестировщики проверяют приложение на наличие ошибок, если находят недочеты — программу дорабатывают.
  5. Публикация. Готовое мобильное приложение отправляют в магазин, веб-приложение загружают на сервер и запускают — деплоят. С этого момента оно становится доступным для пользователей.

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

IT-специалист с нуля

Наш лучший курс для старта в IT. За 2 месяца вы пробуете себя в девяти разных профессиях: мобильной и веб-разработке, тестировании, аналитике и даже Data Science — выберите подходящую и сразу освойте ее.

картинка (75)

Статьи по теме:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *