Разработка платформы краткосрочной аренды повседневной одежды
Анализ аудитории и предпочтений на основе качественного и количественного анализов. Разработка MVP-версии продукта с созданием реляционной базы данных, frontend и backend приложений. Создание функциональных требований к системе, включая BPMN-схему.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 10.12.2019 |
Размер файла | 4,5 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Чтобы зарегистрировать части конфига в DI контейнере, используется специальный метод, в который передается секция конфига (рисунок №28). Метод сам типизирует настройки под нужный объект. Секция конфига в данном случае - просто строка, которая является названием объекта в json файле.
Рисунок 28 - Добавление конфигурации
Рисунок 29 - Файлы конфигурации
Рисунок 30 - Пример данных в файле конфигурации
Для обращения к конфигу в конструктор нужно указать ссылку на специальный интерфейс IOptionsSnapshot, расширяемым типом той части конфигурации, которую нужно добавить (рисунок №31). В таком случае при каждом обращении в класс будет импортирована самая новая версия конфига не нужно перезапускать приложения для применения настроек. Нужно, однако, помнить, что это не будет работать в Singleton сервисах (так как они создаются единожды). В них можно импортировать IOptions, также расширяемых желаемой частью конфига.
Рисунок 31 - Пример получение конфигурации в коде
В данном методе также создаются CORS политики, которые определяют какие ресурсы имею право обращаться в API (рисунок №32).
Рисунок 32 - Пример CORS политики
В данном случае в конфиг вынесены те URL, которые имеют доступ к приложению. Сейчас это только frontend приложение, но в будущем может быть расширено для внешних API чтобы обеспечить работу Webhooks.
Метод Configure используется для внесения настроек во различные модули, которые уже были добавлены в DI контейнер. Тут можно включить консоль для вывода логов, включить свой middleware или настроить использование стороннего пакета.
Следующим было настроено подключение к базе данных и миграции.
Для EF нужно настроить контексты использования - области обращений к базе данных, которые содержат объекты нужных таблиц [39]. Рамки контекста в данном случае очень размыты: разработчик сам решает сколько контекстов и какие таблицы в них входят. Одна таблица может быть во многих контекстах одновременно, причем так как для каждого из них может быть указано уникальная реализации этой таблицы, то контекст также может разграничивать и свойства сущности: например, один контекст может видеть только первые три колонки из таблицы, а второй все. Данный функционал очень сильно помогает на поздних этапах разработки, когда в базе накапливается много таблиц. Если держать все в одном месте, то код очень быстро превратится в нечитаемый. Логично было бы делить законченные по смыслу части на свои контексты (один контекст под заказы, один под пользователей и так далее).
Каждый контекст должен наследоваться от класса DbContext. Свойства, которые связываются с таблицей, создаются как объекты DbSet, расширяемый типом нужного класса.
При считывании или отправки данных EF открывает соединение в БД, в рамках которого совершает заданную операцию. Очень важно эти соединения своевременно закрывались, поэтому хорошей практикой считается создавать контексты внутри директивы using: у объекта, созданного с помощью этой директивы, будет автоматически вызван метод IDisposable при закрытии блока using. Так как C# является языком с автоматической сборкой мусора, то чаще всего думать об этом не надо. Однако в случае с БД сборщик не в состоянии сам определить пора ли освобождать подключение или же оно просто в режиме ожидания. IDisposable контекста, наследуемый от DbContext, безопасно закрывает подключение и указывает сборщику, что владение управляемыми ресурсами закончено и память можно высвобождать.
Хоть EF и предоставляет общую реализацию IDisposable, он не дает единого механизма создания контекста: у каждого контекста свои настройки, своя строка подключения, свои уровни трассировки логов и так далее, поэтому был разработан единый механизм создания контекстов при помощи встроенного в C# механизма динамического создания объектов по типу (рисунок №33).
disableChangeTracking - настройка, которая включает или выключает автоматический трекинг изменений. Если настройка включена, то если о модели, полученной из базы внутри контекста, будет изменено какой-то свойство, то при сохранении изменений EF автоматически применит UPDATE скрипт у этой записи.
Рисунок 33 - Динамическое создание контекста
Наиважнейшая часть работы в EF - то, как именно SQL-таблицы будут преобразоваться в объекты и обратно. Для этого был выбран вариант миграций - автоматической генерации файлов, которые преобразуют классы в SQL-запросы. В этом и заключается вся суть code-first подхода - база генерируется из сущностей в коде. Это накладывает ряд ограничений (в частности, урезает функционал деления на контексты), однако сильно повышает скорость разработки.
Так как именно проект Core отвечает за подключение к базе и именно в нем находится контекст, то было принято решение хранить миграции в нем. Однако появляется важная проблема: Core является библиотекой классов, а не точкой доступа к API, поэтому appsetting.json к конфигурацией строк подключения на находится не в нем. Стандартная реализация EF Core CLI (команд для консоли операционной системы) не поддерживает такое разбиение, считая, что миграции, контекст и конфиг должны быть в одном проекте.
Поэтому была переопределена стандартная команда EF Core CLI, создающая подключение к базе при применении миграции (рисунок №34).
Рисунок 34 - Решение для удобного применения команд миграций
Данный метод выполняется переопределяет оригинальный и выполняется консолью при создании миграций. Метод ищет проект API, берет его конфигурацию, достает оттуда строку подключения к БД и использует ее.
Это решение не очень красивое, однако позволяет, находясь в проекте Core, за одну простую команду генерировать файл миграции, который будет храниться там, где должен (рисунок №35).
Рисунок 35
Пример создаваемой миграции (рисунок №36).
Рисунок 36 - Пример миграции
Миграция обладает двумя методами: Up для добавления, Down для удаления. После создания миграции ее надо применить. В каждый из автоматически сгенерированных файлов можно внести любые желаемые правки. EF создает в базе таблицу, в которой ведет историю миграций: как видно из рисунка, то каждая миграция имеет временную метку, уникальную для нее. Это позволяет удобно синхронизировать изменения, если несколько разработчиков, работающие с системой контроля версий, имеют собственные dev базы.
Также надо отметить, что хоть миграции и удобны, они все же не могут закрыть всех потребностей в преобразовании данных. Для этого часто используются специальный файлы конфигураторы, в который вручную описываются преобразования данных из SQL в C# и обратно (рисунок №37).
Рисунок 37 - Пример кастомного преобразования данных
В них можно, например, написать свой преобразователь значений, который не поддерживается EF [38].
Для использования данные конфигурации отдельно указываются в контексте.
Контекст также обладает гибкой настройкой всех своих методов: абсолютно каждая стандартная реализация может быть переписана или дополнена. Удобно это для обеспечения изначальных данных в таблице: метод OnModelCreating может быть переписан (через override C#) [42] и в него могут быть добавлены первые пользователи, роли, тестовые данные, справочники и любая другая информация.
Следующим был встроен Identity Core. Это решение является готовым механизмом авторизации, которое встраивается в EF Core. Для его имплементации в первую очередь нужно заменить наследование контекста от DbContext на IdentityDbContext, который можно по желанию расширить собственными классами пользователи и роли. Нужно это за тем, чтобы добавить собственный поля в таблицу AspNetUsers, что отражено в диаграмме базы данных. Также можно переопределить стандартный тип для первичного ключа. В рамках всего проекта было принято решение использовать Guid для этих целей.
Рисунок 38 - Расширение пользователя в Identity Core
Объекты пользователей и ролей при этом также должны наследоваться от сущностей, предусмотренных в Identity Core (рисунок №38).
IdentityDbContext наследуется от DbContext, так что вся функциональность по кастомизации контекста остается на месте.
Рисунок 39 - Настройка встроенных сервисов управления пользователями
Далее можно переопределить политику паролей, если это требуется, и настроить IdentityBuilder для работы с новыми классами пользователей и ролей. Нужно это для того, чтобы появилась возможность использовать встроенные сервисы UserManager и RoleManager. Данные сервисы уже имеют весь необходимый функционал по управлению записями пользователей: создание, добавление в роль и многое другое (рисунок №39).
Дальнейший шаг - разработка авторизации, однако перед этим была произведена работа над контроллерами, а точнее их ответами.
Каждая конечная точка запроса в ASP.Core является методом в специальным класса - контроллере, наследующимся от Controller. Контроллеры обычно делятся по сущностям. С помощью атрибутов как для методов, так и для всего контроллера можно задавать параметры пути, по которому логика будет доступна, нужна роль авторизации, тип HTTP запроса.
Рисунок 40 - Пример запроса
На примере видно, что метод регистрации будет доступен типа POST и доступен по пути /api/User/Register. Данный метод (также принимает на вход модель данных, нужных для регистрации (логин, пароль, ответ от reCaptcha). Чтобы получить ее, на вход методу была указан параметр с атрибутом FromBody, который указывает фреймворку искать данные в теле запроса. Также существуют аналогичные методы: FromQuery, FromUri. ASP.Core автоматически пытается преобразовать JSON данные в объект. В случае ошибки входной параметр будет равен null.
Проблема в том, что тип выходных данных может быть любым: текст, JSON, файл и так далее. Однако хотелось бы, чтобы ответ сервера всегда имел один формат. Даже в случае ошибки (пароль не верный или валидация не пройдена) сервер не должен возвращать BadRequest, а стандартизированную модель, в которой есть текст ошибки и ее внутренний код.
Для этого быв введен абстрактный класс BaseController, также наследующийся от Controller, который содержит методы для положительного ответа и отрицательного. В обоих случая возвращается одна модель, меняется внутренний код и модель ошибки, если есть. Каждый метод каждого контроллера теперь возвращает JSON с базовой моделью (Response), где есть объект data, расширяемый запрашиваемой информацией (кроме тех методов, что возвращают файлы, так как было бы плохой идеей возвращать их не байтами, а base64 строчкой внутри JSON). Тип Response является generic (или общим), что означает, что одно и тоже его свойство в разных применениях может быть разного типа, который подставляется компилятором автоматически при сборке проекта (рисунок №41).
Рисунок 41 - Пример унифицированного ответа
Из рисунка №41 видно, что в случае положительного результата возвращается ответ с запрашиваемыми данными и без ошибки, в ином - результат с ошибкой, но с кодом ошибки.
В качестве технологии авторизации, отвечающей функциональным требованиями (использование пары access-refresh токенов) были выбраны JWToken'ы. Этот открытый стандарт, основанный на формате JSON, позволяет быстро встроить необходимый функционал в систему [43].
Суть авторизации таков:
1. Пользователь по защищенному HTTPS каналу передает серверу логин и пароль для авторизации.
2. Используя ранее сконфигурированный UserManager, серверная часть проверяет есть ли такой пользователь в системе.
3. Если запись найдена, то для пользователя генерируется два токена: JWT access токен с коротким сроком жизни, который и является ключом для авторизованного доступа к системе, а также refresh токен, который нужен для восстановления первого.
4. Refresh токен сохраняется в базу данных. В БД сохраняются все старые токены пользователя, так как возможен случай, при котором пользователь вошел на одном девайсе, сохранил на нем токен восстановления, потом вошел на втором, на котором также сохранил уже новый, а затем решил вернуться к работе обратно на первый. В этом случае у него сохранен устаревший токен, однако у пользователя все равно должна остаться возможность войти. Для всех refresh токенов ведется статистика использования (сколько раз был применен). Пока было принято решение ввести ограничение на 5 раз использование (то есть 5 разных девайсов у одного пользователя), однако данная цифра может измениться. Нужна такая мера для ограничения попыток входа злоумышленника.
5. Клиентская часть получает токены. Access используется для продолжения работы, а refresh надежно сохраняется. В случае истечения времени жизни токена доступа или перезагрузки страницы токен восстановления используется запроса новой пары токенов, но уже без логина и пароля.
6. Сервер проверяет наличие refresh токена в базе и количество его использований. В случае, если оба условия выполнены, то выполняется шаг №3.
Рисунок 42 - Создание access токена
Так как Identity Core использует claims-based авторизацию, то и данными access токена также должны быть заявления о пользователи (claims). В токен в итоге попал уникальный идентификатор пользователя и его роль. При необходимости этот список можно всего расширить (рисунок №42).
Также надо отметить, что внутри токена также указывается срок жизни, указанный в конфиге (15 минут), а так захешированный ключи, который подписан токен. Нужно это для последующей валидации токена фреймворком.
Рисунок 43 - Пример валидации токена
Отдельно нужно переопределить механизм аутентификации на JWT и указать фильтры проверки, по которым ASP.Core будет проверять подлинность токена (рисунок №43).
Генерация и валидация refresh токена сделаны аналогичным образом.
Далее было сконфигурировано и настроено использование websocket канала. Сделано это было при помощи библиотеки SignalR, позволяющей снять в разработчика задачи по установлению соединения, поддержании, отлову и прочему [44].
SignlarR использует систему Hub'ов - отдельных подключений, отделенных по смыслу. Проблема данного подхода, что с ростом приложение в этом случае также возрастет количество хабов, а так как каждый хаб представляет собой одно подключение, то у одной клиентской части может 5 и более одновременных неразрывных подключений, что создает очень большую нагрузку на сервер [45]. Решение стал бы partial класс, то есть один класс в разных файлах. Такой подход сохранил бы разбиение хабов на смысловые части и свел количество подключений до одного.
Каждый хаб должен наследовать класс Hub, расширенный уникальным интерфейсом, созданным специально под конфигурируемых хаб. Все методы, которые клиентская часть может вызывать на сервере и которые, соответственно, на сервере и выполняются, прописываются в классе, а методы, которые, наоборот, вызывает сервер у клиентской части, имеют только сигнатуру и указываются в интерфейсе (рисунок №44).
Рисунок 44 - Пример настройки Hub'а
Метод SaveConnection нужен для установления связи между соединением и идентификатором пользователя. Так как установить связь с сервером по websocket каналу может любое устройство, то SignalR выдает ему уникальный код, являющийся последовательностью букв. Из-за того, что библиотека использует отдельный протокол передачи данных, то заголовки и cookies у нее свои и, соответственно, свои токены и claims'ы, поэтому на серверной стороне нельзя достоверно определить того пользователя, который подключился. Клиент же, наоборот, знает и идентификатор своего подключения, и, после авторизации, идентификатор себя в базе данных, так что может передать последний серверу, чтобы тот сохранил это соотношение.
Связи подключений и пользователей нужны, чтобы точно знать каким конечным точкам слать данные: если у определенного заказа поменялся статус, то именно клиент, создавший его, должен быть оповещен. У каждого пользователя может быть несколько одновременный подключений. Связи подключений и пользователей хранятся в статическом классе в потокобезопасном словаре.
Рисунок 45 - Потокобезопансный словарь для работы с подключениями
Подключения хранятся в памяти, а не персистентно, так как при перезагрузки приложение все активные подключения в любом случае упадут, поэтому нет смысла хранить их базе. Потокобезопасность нужно из-за того, что пользователь может одновременно подключаться на одном устройстве и отключаться на другом: данная операция могла бы привести к взаимной блокировке (deadlock) ресурсов.
Рисунок 46 - Конфигурация точек подключения к хабам
Также необходимо настроить точки, по которым клиентская часть подключаться к каналу (рисунок №46).
Самой сложной серверной задачей с большим отрывом оказалась задача генерации документов. Проблема в том, что документы должны быть как в формате PDF, так и DOCX, хотя даже каждый из них по-отдельности представляет серьезную трудность.
После длительного исследования было принято решение хранить шаблоны документов в виде HTML-файлов. Такой вариант позволяет в легкости генерировать нужную итоговую разметку, подставляя данные на искомые места. Затем бы сгенерированные файлы с версткой можно было бы превратить в искомые файлы, используя подходящие конвертеры.
В ASP.Core уже есть механизм отрисовки шаблонов - Razor Core, однако он сконфигурирован так, чтобы работать с отрисовкой готовых страниц по URL, а не динамически обрабатывать любые файлы [45].
Чтобы решить данную проблему, был написан небольшой метод (рисунок №47), который динамически в процессе выполнения создает рабочий вариант механизма отрисовки. Razor умеет работать только с готовыми файлами в формате CSHTML, представляющими собой сочетания базового языка разметки и языка C#. Метод подставляет в механизм нужный файл, модель, которая несет в себе данные, и на выходе получает строку - уже сгенерированный HTML файл, в который были подставлены все нужные значения.
Рисунок 47 - Динамический вызов движка генерации шаблонов
После успешной генерации HTML версии документов нужно каким-то образом сконвертировать их в заданные форматы файлов. Если говорить про PDF, то тут все крайне просто: существует программа с открытым исходным кодом wkhtmltopdf, которая предоставляет команды для операционной системы для конвертации HTML в PDF любой сложности [46]. Это решение содержит в себе механизм генерации документов из WebKit - движка для генерации веб-страниц, на котором основываются практически все существующие браузеры кроме Firefox. Таким образом генерация документов этого типа может быть проведена через тот же механизм, что и при печати страницы в Google Chrome [47].
Так как DOCX является частью Open XML (ряд открытых форматов для хранения электронных документов) [48], то существует множество библиотек для конвертации HTML в него, включая нативные [48]. Проблема в том, что все они обладают низкой точностью и не могут идеально перенести сложные конструкции (многоярусные таблицы с кастомными стилями границ), сильно портя итоговые файлы. Даже платные решение, которые стоят многие тысячи долларов, не могут провести идеальную конвертацию. Такого не случается, если в файле есть текст с форматированием, пара обычных таблиц, картинок и заголовком, но анкеты курьерских служб чаще всего имеют куда более замысловатый формат, так как предполагается, что подобные файлы будет заполняться человеком руками в приложении.
После данного исследования в начале было принято решение отказаться от данного функционала, однако потом была замечена одна важная особенность: если в приложении Microsoft Word открыть DOCX документ, потом сохранить его в формате HTML, поменять некий текст, а потом опять сконвертировать в оригинальный формат, то файл будет выглядит в точности как в начале, разве что изменится этот самый текст. То есть Microsoft Word имеет уже встроенную возможность преобразования файлов этих типов, и, как всем известно, Word имеет Interop API [49], позволяющую .NET решением взаимодействовать с COM объектами, на котором построено множество программ, разрабатываемых компанией Microsoft: можно с легкостью открыть нужный файл и сохранить его в желаемом формате без потери качества, передав управление этими задачами в Word и, соответственно, использовав нативную реализацию.
Единственная проблема - объекты COM доступны только для ASP.NET приложений, а не ASP.NET Core, так как первый является фреймворком только для операционной системы Windows (где и применяются COM объекты), а второй кроссплатформенный. Поэтому было принято решение перенести приложение по конвертации документов в отдельный проект, уже на фреймворке ASP.NET, представляющий собой закрытый API (рисунок №48).
Конвертация в PDF для удобства также вынесена в данное приложение. Над конфигурацией этого решения не проводилась особая работа, так как в формате MVP версии продукта дополнительная оптимизация не требовалась. Процесс генерации документа таков: в приложение передается HTML файл в виде текста, а также параметр желаемого выходного файла. Приложение возвращает желаемый файл. Итоговые файлы можно или вернуть по-отдельности, или как архив (рисунок №49).
Рисунок 48 - Конвертация документов через Interop
Рисунок 49 - Генерация архивов
С использованием вышеописанных практик и принципов удалось у короткие сроки завершить работу нас серверной часть и выпустить первую MVP версию приложения.
3.3 Frontend
Следующим этапом разработки стало создания клиентского приложения, написанного с использованием фреймворка Angular, который отлично масштабируется и идеально подходит для приложений уровнем выше среднего.
Для создания нового приложения достаточно глобально установить npm пакет @angular/cli и в нужной папке выполнить команду ng new ProjectName. Angular самостоятельно предложит выбрать используемый компилятор css (scss или less), дополнительные настройки и скомпилирует готовую структуру и готовыми автоматическими тестами [34].
Angular имеет модульную структуру (рисунок №50) [34], то есть каждая отдельная логически-обособленная часть проекта может быть вынесена в отдельный модуль, ссылаясь при этом на другие модули, которые ей нужны.
Рисунок 50 - Стандартная структура проекта Angular
Это позволяет очень удобно разграничить проект, а также вводит функциональность ленивых модулей, то есть модулей загрузка которых будет произведена только в момент непосредственного обращения, что крайне важно в рамках клиентского приложения: отдельный модуль, который, например, несет в себе страницы работы с заказами, может «весить» очень много [34]. Если таких модулей много, и они все разом грузятся на старте, то общий пользовательский опыт будет негативным из-за большого времени начального ожидания. Если же каждый из модулей грузится последовательно в рамках надобности, то данная проблема явно не возникнет (рисунок №51).
Рисунок 51 - Инициализация ленивых модулей
К каждом проекте при этом в любом случае должен быть головной модуль, являющийся прямым или последовательным родителем для остальных. В любой модуль могут быть вставлены свои сервисы, однако сервисы родительского наследуются также и дочерним. Сервисы, добавленные в головной модуль, будут, соответственно, доступны во всех.
Механизм получения зависимостей сильно отличается от аналогичного в ASP.Core. Тут нет понятия времени жизни проекта, но есть своеобразное «место» жизни: так как все сервисы привязаны к модулям и один и тот же сервис может быть зарегистрирован как у дочернего, так и родительского модуля, место, откуда Angular'у нужно брать искомый сервис может варьироваться. По умолчанию фреймворк идет от заданного модуля вверх и ищет ближайший сервис запрашиваемого типа, но данное изменение можно поменять, наложив разные фильтры, например, используя декораторы @Optional (зависимость опциональна), @Self (взять из собственных ссылок) и другие (рисунок №52) [50].
Рисунок 52
Важной часть клиентского приложения является авторизация. Для этого в Angular предусмотрен специальный объект - Guard. Guard «приставляется» к модулю и решает есть ли у пользователя право доступа.
Логика выдача прав может быть абсолютно любая, но чаще всего проверяется наличие токена и текущая роль (рисунок №53).
Рисунок 53 - Пример guard'а
Для подтверждения состояния авторизации пользователя используются interceptor'ы - специальные методы, который «вклиниваются» в каждый запрос к серверной стороне [34]. В данном методе можно всячески изменить текущий запрос: поменять конечную точку, заголовки, провести дополнительный запрос и так далее. В частности, клиентское приложение проверяет перед каждым запросом есть ли access токен и не истек ли его срок жизни. Если он есть, то добавляет Bearer заголовок, нужный для принятия токена на серверной стороне. В противном случае при наличии refresh токена access запрашивается заново. Если же и refresh токен не найден, то пользователя выбрасывает на страницу авторизации. Данная схема не применятся к методам, помеченным флагом анонимности (рисунок №54).
Рисунок 54 - Пример interceptor'а.
Характерным отличием Angular является повсеместное использование библиотеки RxJS [34]. Так как фреймворк работает на языке TypeScript, то эти два параметра вкупе позволяют использовать типизированное реактивное программирования для решение практически любой задачи, вобрав только лучшее из обоих подходов [35].
Из-за использования zone.js, практически все внутренние функции фреймворка работают на RxJS: формы, запросы, навигация, callback-функции [35]. Это делает абсолютно необходимым глубокое знание языка и библиотек фреймворка для написания по-настоящему мощного функционала. Angular обладает очень богатой внутренней API, которая довольно скудно описывается в документации и редко разбирается в инструкциях по обучению. Так, мало где можно найти информацию по внутреннему движку генерации шаблонов и что этот движок можно с легкостью использовать в собственных целях для динамического создания компонентов (рисунок №55).
Рисунок 55. Пример расширения внутреннего API запросов путем добавления поддержки единой модели ответа серверной части (Response)
Для конфигурации проекта используются файлы environment.ts. Каждый из файлов содержит в названии название своей среды (environment.prod.ts) и применяется соответственно. При написании достаточно импортировать только файл конфигурации по умолчанию - при компиляции фреймворк сам подставит на его место нужный. Также существует более детальный уровень настройки, позволяющий настроить такие параметры как хешинг скомпилированной программы или детали работы механизма генерации.
Для работы с SignalR для фреймворка существует одноименный пакет, содержащий все необходимые функции: достаточно прописать путь к нужному Hub и к обмену данными (рисунок №56).
Рисунок 56 - Пример работы с SignalR
При работе с Angular актинов применялись компоненты - часть HTML верстки с собственной логикой, которые можно использовать. Вообще практически любое графическое представление в этом фреймворке является компонентном, но полезнее они всего для создания виджетов. Например, можно один раз написать код виджета ввода данных, присвоить ему HTML-тег, а затем добавлять его во все прочие компоненты, в модули которых импортирован модуль виджета. Это позволяет разительно сократить кодовую базу и ввести полную унификацию: если нужно поменять стиль окна выбора даты, то не нужно менять его во всех инстансах, достаточно внести изменения один раз в компонент и желаемый результат будет достигнут.
Компоненты имеют множество полезных особенностей. Так, компоненты могут реализовать специальные интерфейсы, методы который привязаны к жизненным циклам компонента: на его создание, уничтожение, проверку, внесение изменений и прочее. Это крайне важно, например, при работе с реактивными сущностями: если в компоненте есть подписка на какое-то событие, то эта подписка обязательна должна быть удалена перед уничтожением компонента, иначе RxJS попытается вызвать подписанта, которого уже не существует, и выдаст ошибку.
Также компоненты поддерживают вложенность, то есть компонент можно вставить внутрь компонента (рисунок №57). Это вводит отношение «родительский-дочерний» (как и у модулей) и позволяет удобно передавать данные из одного компонента в другой (рисунок №58).
Рисунок 57
Рисунок 58
Компоненты также поддерживают реализацию двухстороннего связывания: паттерна, при котором при любом изменении данных (из модели или из интерфейса) все стороны оповещаются и обновляются автоматически. Это позволяет удобно внедрять в код любые валидаторы или преобразователи значений, не заботясь о настройке получения изменений.
Из всех задач по выполнению клиентской части, одна выделялась особенно - подписания документов ЭЦП. Данный процесс жестко регулируем и может быть проведен только с использованием всего нескольких разных провайдеров. В данном проекте был выбран провайдер КриптоПро, он предоставляет открытое и хорошо задокументированное решение [51].
Для работы провайдера на компьютер необходимо установить программу КриптоПро CSP и специальный плагин для браузера.
В итоге получаются функции, вызов которых активирует методы программы, установленной на компьютер, которая и выполняет выгрузку списка сертификатов и саму подпись (рисунок №59).
Рисунок 59 - Пример создания подписи через API КриптоПро
Ключевая задача frontend части - непосредственная разработка веб-страниц (рисунок №60).
Рисунок 60 - Диаграмма веб-страниц
Лендинг является первой продающей страницей, встречающей первого пользователя (рисунок №62). На ней описана ключевая информация, которая может завлечь клиента - статистика, цены, варианты услуг и прочее. На этой странице также отображаются контакты, активно используется parallax.
Страницы регистрации, авторизации и восстановления пароля являются модальными окнами лендинга.
Dashboard - стартовая страница зарегистрированного пользователя. Обычный клиент видит здесь новые предложения, скидки, свои промо. Для администратора отображается статистика работы в графиках.
Ветка «Найти одежду» описывает страница поиска позиций. Для них характерен полноразмерный фильтр и страница быстрого просмотра одной вещи, где можно выбрать срок доставки, добавить нужную вещь в корзину или написать комментарий.
Корзина всегда видна всем клиентам в верхней части страницы. Переход внутрь позволят перепроверить заказ и перейти к оформлению. Страница оформления требует от клиента ввод личных данных и выбор адреса доставки. После успешного создания пользователь попадете на страницу одного заказа, которая также доступна из личного кабинета, где может наблюдать статус (рисунок №63). В случае успеха туда также выставляется счет на оплату.
Для администратора страница одного заказа также отображает документы для генерации, если те нужны. После генерации каждый документ можно подписать ЭЦП для дальнейшей отправки во внешние системы.
«Мой профиль» позволяет пользователю редактировать информацию о себе, добавлять адреса, менять пароль, просматривать заказы, уведомления и достижения (рисунок №61). Активный заказ всегда подсвечивается в верхней части сайта.
Администратору также доступны страницы редактирования и создания позиций. Тут можно добавить одежду, сформировать сеты, изменить цену и настроить даты доступности определенной вещи или всего заказа.
Рисунок 61 - Пример страницы достижений
Рисунок 62 - Пример лендинга
Рисунок 63 - Пример страницы статуса заказа
Таким образом, в рамках данной главы было произведено самое важное исследования работы - а именно непосредственная разработка MVP версии программного продукта. Данная версия является сырой для незамедлительного полного вывода на рынок, однако уже достаточной для проведения дальнейшего развития проекта.
ГЛАВА 4. ДАЛЬНЕЙШЕЕ РАЗВИТИЕ ПРОДУКТА
Дальнеший путь развития продукта должен быть соспряжен со стандартным циклом MVP - сбором отзывов и улучшении продукта согласно им. Для этого стоит начать искать каналы продвижения сервиса и начитать инкрементальную маркетингувую компанию, то есть привлекать небольшой количество клиентов, тщательно следить за их действиями и отношением к продукту, а затем улучшать сервис для следующего раунда клиентов. В этом случае важно не афишировать бренд, который будет принято решение использовать в итоговом продукте: если клиент начнет ассоциировать сырую версию с брендом, то будет сложно изменить эту предубеждение. Также в этом случае пропадет wow эффект от сервиса: при продолжительной рекламе люди привыкают к товару и с каждым разом обращают на него все меньше и меньше внимания. Так небольшие маркетинговые компания стоят совсем не дорого и могут быть выполнены собсвтенными силами.
После получения положительных результатов практического тестирования сервиса имеет смысл переходить на следующий этап разработки и вывовода продукта: разработка интеграций и привличение инвестиций. Оба процесса предполагают наличие гораздо более жествих рамок планирования и постановление задач. В этом случае, например, хорошей идеей будет создание карты продукта - диаграммы, отображающей этапы ввода нового функционала, разбитые на короткие отрезки: одна - две недели.
Для разработки интеграции и общего улучшения системы понадобится найм команды, состоящий как-минимум из верстальщика, frontend разработчка, backend разработчика, тестироващика и продуктолога. Такой небольшой размер команды опрадывается скоромными размерами всей платформы как продукта, однако даже в таком случае понадобится надежный инструмент управления командой и задачи.
В качестве такого может послужить программное обеспечение Atlassian Jira, предстовляющее собой крайне гибкую систему, в которой с легкостью можно настроить любой необходимый гибкий подход к разработке: scrum, agile. ПО также позволяет вести статистику, разграничивать роли и политику безопасности, интегрировать достку с беклогом в другие сервисы (автоматическое изменение статусов задачи при целевых действиях).
Важным этапом для любого сервиса аренды является составление договора об оказании услуг. Так как велика вероятность потери одежды или ее порчи, каждый клиент должен в обязательном порядке подписавать юридичскую документ, обязаующий его в случае форс-мажора возместить ущерб. Для прорабатывания данного документа можно привлечь юриста через любой из сервисов краткосрочного найма персонала.
Также нельзя забывать о поиске парнеров. Наиважнейшим в данном случае яляется цех химчистки, который должен обладать API для интеграции. Некоторые современные химчистки уже облдают функционалом отслеживания заказа, так что данная задача может быть решена без дополнительных проблем.
Хорошей идеей было бы встроить сервис массовых рассылок в продукт, так как данный функционал позволил бы оповестить всех учавствоваших в тестировании клиентов о начале реальной работы.
Так как шеринг экономика Росии переживает этап бурного роста, продукт мог бы привлечь инвестирование частных лиц, в том числе и основанное на эффекте тренда. Для этого необходимо будет подготовить полноценный бизнес-план с множеством всевозможных анализов: SWOT, PEST, силы Портера, детальный анализ результатов опросов и так далее.
Также стоит подумать над стратегией вывода на рынок: аналогичное решение уже существует и именно оно было первым. Необходимо найти слабые стороны продукта-конкурента и разумно на них сыграть. Например, в глаза бросается неприметный дизайн и отсутвие SEO-анализа [9], соответвенно, именно это может стать преимуществами разрабатываемой платформы.
Важнм аспектом является цена услуги. Так как услуга на рынке новая и потребители к ней еще не привыкли, то стоит вводит промо-акции на скидки и бесплатные первые заказы с целью наращивая базы покупателей. Только затем имеет смысл повышать цену и выходить на стадию самоокупаемости.
С целью продвижения сервиса можно использовать социальные сети контекстную рекламу: такой подход поможет наиболее точно попасть с нужные целевые аудитории. В этом случае также можно с легкостью настроить целевые действия с целью просчета конверсий. Также помогут всевозможное, обеспечивающее всесторонний анализ траффика платформы. Подобные решения помогут точнее настроить контент, определить границы аудиторий, а также таргетировать рекламу.
ЗАКЛЮЧЕНИЕ
В рамках данного исследования рассматривалась разработка платформы краткосрочного шеринга одежды. В начале был произведен customer development анализ, результатом которого стал набор гипотез о требуемой функциональности платформы. Затем данный ряд был проверен путем опроса целевых групп. Количественный анализ окончательно установил перечень требуемого функционала, который был более детально расписан во второго главе. Также на ряду с функциональными требованиями была сформирована схема бизнес-процесса, описывающего платформу. Затем, используя написанные требования, была совершена полноразмерная разработка продукта: была создана база данных, отвечающая всем критериям требуемых сущностей; была написана и сконфигурирована клиентская часть, включая механизм генерации документов; было подготовлено SPA-приложение клиентской части, включая верстку страниц и подписание ЭЦП. В последней главе был приведены примеры дальнейшего развития продукта и его вывода на рынок. Таким образом, были выполнены все поставленные в начале работы задачи: анализ предпочтений аудитории, вынесение требований, разработка и план дальнейшего развития.
СПИСОК ЛИТЕРАТУРЫ
1. Ranjbari M., Carrasco-Gallego R., Morales G. Conceptualizing the Sharing Economy through Presenting a Comprehensive Framework // Sustainability. - 2018.
2. Yaraghi, Niam; Ravi, Shamika The Current and Future State of the Sharing Economy // Brookings India IMPACT Series. - 2017. - №032017.
3. Gerald Kotonya, Ian Sommerville Requirements Engineering: Processes and Techniques. Wiley Publishing, 1998.
4. Anh Nguyen DucEmail, Pekka Abrahamsson Minimum Viable Product or Multiple Facet Product? The Role of MVP in Software Startups. Springer, Cham, 2016.
5. Роб Фитцпатрик Спроси маму: Как общаться с клиентами и подтвердить правоту своей бизнес-идеи, если все кругом врут? Издательские решения, 2015.
6. Garm Lucassen, Slinger Jansen Gami?cation in Consumer Marketing - Future or Fallacy? // Procedia - Social and Behavioral Sciences. - 2014. - Т. 148, вып. 25. - С. 194-202.
7. Charles F. Hofacker, Ko de Ruyter, Nicholas H. Luriec, Puneet Manchanda, Jeff Donaldson Gamification and Mobile Marketing Effectiveness // Journal of Interactive Marketing. - 2016. - Вып. 34. - С. 25-36.
8. Josef Spillner Practical Tooling for Serverless Computing // UCC '17 Proceedings of the10th International Conference on Utility and Cloud Computing. 2017. - С. 185-186.
9. Luis von Ahn, Benjamin Maurer, Colin McMillen, David Abraham, Manuel Blum reCAPTCHA: Human-Based Character Recognition via Web Security Measures // Science. - 2008. - №Т. 321, вып. 5895. - С. 1465-1468.
Размещено на Allbest.ru
Подобные документы
Описание предметной области, определение функциональных требований к системе и построение диаграммы потока данных. Построение модели "сущность-связь", описание сущностей и атрибутов модели. Построение реляционной базы данных и описание ее таблицы.
курсовая работа [624,5 K], добавлен 30.05.2019Анализ реквизитного состава налоговой инспекции и установление функциональных зависимостей между реквизитами. Образование информационных объектов. Создание даталогической модели реляционной базы данных. Разработка структур таблиц, обеспечение целостности.
курсовая работа [919,0 K], добавлен 16.09.2012Обзор проектирования реляционной базы данных "Спортивные соревнования". Расчет экономического эффекта от использования программного продукта за период внедрения. Анализ входных и выходных форм, требований к техническому обеспечению, технологии доступа.
курсовая работа [1,4 M], добавлен 12.12.2011Разработка реляционной базы данных информационной системы для учета доходов потребительского общества средствами программного продукта СУБД MS SQL Server 2012. Преобразование концептуальной модели данных к реляционной. Набор предварительных таблиц.
курсовая работа [11,9 M], добавлен 06.10.2014Анализ предметной области и введение ограничений. Выделение базовых сущностей. Концептуальная модель данных. Построение схемы реляционной модели базы данных магазина одежды в третьей нормальной форме. Описание физической БД. Проектирование интерфейса.
курсовая работа [2,6 M], добавлен 20.11.2013Особенности разработки инфологической модели и создание структуры реляционной базы данных. Основы проектирования базы данных. Разработка таблиц, форм, запросов для вывода информации о соответствующей модели. Работа с базами данных и их объектами.
курсовая работа [981,4 K], добавлен 05.11.2011Анализ предметной области на примере сервисов Google Maps, MazeMap и GateGuru. Разработка списка основных требований к платформе "Навигация в здании". Создание реляционной схемы базы данных. Формулирование запросов на языке реляцинной алгебры и SQL.
курсовая работа [720,9 K], добавлен 03.04.2014Анализ баз данных и систем управления ими. Проектирование и создание реляционной базы данных в среде MS Access для ресторана "Дельфин": построение информационно логической модели, разработка структур таблиц базы данных и схемы данных, создание Web-узла.
курсовая работа [3,7 M], добавлен 15.11.2010Анализ предметной области с использованием моделей методологии ARIS и разработка ER-диаграммы. Описание входной и выходной информации для проектирования реляционной базы данных. Разработка управляющих запросов и связей между ними с помощью языка SQL.
курсовая работа [975,2 K], добавлен 30.01.2014Основные свойства времени и способы его представления. Временная логика предикатов А. Тейза. Учет временного фактора при разработке баз данных. Разработка концепции базы данных на основе реляционной системы управления. Требования к программному продукту.
дипломная работа [2,8 M], добавлен 02.10.2016