code-interview
Описание
Языки
- TypeScript93,4%
- JavaScript6,1%
- HTML0,3%
- CSS0,2%
PoC: Модульная MVVM архитектура фронтового приложения
Установка и запуск
Для установки зависимостей проекта выполните или в корне проекта.
Для старта разработки используйте: .
Запуск тестов приложения: .
Запуск проверки синтаксиса: .
Запуск сборки приложения: .
Запуск тестов подключаемой библиотеки: .
Сборка подключаемой библиотеки core: .
*После внесения изменений в библиотеку, требуется сборка.
Архитектурная концепция
Концепция предусматривает разделения приложения на модули, где каждый модуль отвечает за отдельную функциональность и
представляет собой архитектурный подход на основе MVVM --. Межмодульные связи же реализуются с
помощью IoC и внедрением зависимостей непосредственно в сущность модели(), модельного представления()
или
иной требуемой сущности.
Модель (Model):
предоставляет данные и бизнес-логику и должна быть быть наблюдаемой при помощи методов mobx, так как по своей сути модель выполняет роль стора приложения. Модель так же может иметь набор методов для взаимодействия с набором данными хранимыми в ней. Для декомпозицииModel, набор данных можно выносить вmodel, а для манипулирования данными - использовать различные паттерны проектирования (к примеру - Repository).entity
Модель представления (ViewModel):
по своей сути является связующим звеном междуViewModelиmodelи так же, должно быть наблюдаемым при помощи методов mobx, для обеспечения реакции на изменения набора данныхviewвоmodel.viewОсновные характеристики
:viewmodel
- Предоставляет геттеры, сеттеры и методы для взаимодействия с
;model- К внедрению доступны только
;model- Не может хранить состояния;
Представление (View):
отвечает за отображение данных и взаимодействие с пользователем. В рамках данной концепции, view реализован при помощи React, а наблюдение за состнояниями стора приложения осуществляется с помощью компонентов и методов mobx.View
Каждый модуль является конфигурируемым и инкапсулирет в себе весь функционал за который он отвечает. Так к примеру, модуль core является основным и инкапсулирует в себе основную логику приложения, такую как пользовательские настройки, базовый лейаут, компонент отрисовки страницы поставлямой модулем, отрисовку основного меню и т.д.
Стоит заметить, что переиспользование ui компонентов между модулями крайне не желательно, так как это может привнести
проблемы
в будущем, к примеру при внедрении микрофронтовой архитектуры. Лучше перемещать общие компоненты в общее хранилище,
таким
образом их менее проблемно можно будет вынести в общую библиотеку компонентов, а также вы будете избавлены от
рефакторинга
модулей в случае необходимости удаления.
Преимущества:
- Стандартизация;
- Простая компонентная заменяемость;
- Устойчивость к изменениям и рефакторингу;
- Низкий time-to-market для функционала;
- Тестирование;
- Ориентированность на потребности бизнеса и пользователей;
- Возможность загружать пользователю только тот функционал, который ему требуется;
Структура приложения
Пример реализован с учетом использования монорепозитория и имеет следующую структуру:
root/
├─ libs/
│ ├─ core # Подключаемая библиотека с API клиентом и мидлварами для роутера.
├─ packages/
│ ├─ todo.app/
│ │ ├─ bootstrap # Загрузочный слой для инициализации.
│ │ ├─ config # Конфигурация основных параметров приложения.
│ │ ├─ modules # Модули приложения.
│ │ ├─ ui # Общие react компоненты.
Загрузочный слой определяет основные сервисы приложения и содержит все обработчики, сервисы и инициализаторы
для запуска приложения.
Асинхронная функция запускает весь процесс инициализации приложения и определяет последовательность
выполнения
обработчиков(). Изменяя порядок обработчиков, можно изменить порядок инициализации приложения.
Функция принимает в себя набор модулей приложения определенных в файле и конфигурацию, возращая
промис проинициализированного класса .
Набор обработчиков() для инициализации приложения. Каждый обработчик отвечает за одну функциональность и имеет
доступ
к основному конфигу приложения из папки , а также к основному классу .
Класс содержит методы для запуска процесса инициализации функциональности для вызова из
обработчиков ,
а также геттры для получения инстансов проинициализированных функциональностей.
В реализованном примере, приложение имеет обработчики для инициализации API клинта, IoC контейнера, обработчика HTTP ошибок, подключения библиотеки интернационализации i18next, запуска сервиса маршрутизации и мок сервиса для возможности локальной разработки.
Архитектура и организация модулей
Каждый модуль отвечает за отдельную функциональность и может поставлять необходимые
сущности(, , ) как отдельно, так и вместе.
К примеру у вас могут быть модули которые отвечают как за пользовательскую функциональность, так и за функциональность
приложения:
- Модуль ролевой модели: Отвечает за функциональность ролевой модели и поставляет сущности
иmodelс которыми взаимодействуют другие модули внедряя необходимые зависимости воviewmodelилиviewиз IoC контейнера.viewmodel - Модуль обработки ошибок: Отвечает за обработку ошибок и так же поставляет сущности
иmodelв общий IoC.viewmodel - Функциональный модуль: Отвечает за функциональность приложения и реализовывает свою логику
,viewиviewmodelкак вместе, таки и отдельно, обращаясь к необходимым частям, поставляемыми другими модулями.model
состав модулей обычно определяется потребностями проекта.
Конфигурация модуля:
Каждый модуль поставляет свою конфигурацию, которая интерпретируется на старте приложения в :
При этом колличество обработчиков можно расширять дорабатывая метод инициализации модулей в
классе .
Конфигурация роутинга:
Роутинг является важной частью приложения и определяется каждым модулем. Состав конфигурации роутинга можно расширять
необходимыми
параметрами, в примере же реализована базовая конфигурация c интерфейсом который дополняет интерфейс
параметрами и мидлвар
функциями конфигурации роутинга .
Вы так же можете расширять состав конфигурации роутинга, добавляя новые параметры и мидлвары.
Пример схемы работы
- Пользователь переходит по роутингу http://my.app/route
- При переходе по роуту происходит вызов события
определенного в конфигурации роутинга модуля.onEnter - Из события
, вызывается инициализационный методonEnter.viewmodel.InitMethod() - Метод
вызывает методviewmodel.InitMethod().model.getDataFromRepository() - Метод модели
вызывает методmodel.getDataFromRepository()который осуществляет запрос к эндпоинту, и обрабатывает полученные данные, возвращая их методуrepository.getData().model.getDataFromRepository() - Метод
устанавливает значения вmodel.getDataFromRepository().model - При изменении наблюдаемых параметров, компонент
обновляется.view
Таким образом, модель может иметь свойство loading, через которое можно отслеживать состояние загрузки данный и
отображать
его во для пользователя.
для более детального изучения данного процесса, рассмотрите модуль .
Стек проекта
Любой компонент стека может быть заменен на аналогичный.
| Библиотека | Описание |
|---|---|
| IoC используется для управления зависимостями и организации создания и разрешения объектов. |
| Библиотека управлением состояния. |
| Библиотека для создания пользовательских интерфейсов. |
| Агностик роутер для управления маршрутизацией приложения. |
| Библиотека пользовательского интерфейса для React. |
| Библиотека предоставляет инструменты и методы для управления переводами и локализацией в веб-приложениях. |
| Библиотека для создания и управления мок-сервером во время разработки веб-приложений. |