Архитектура между разнообразной логикой и пользовательским интерфейсом Identity в мобильном приложении

Спасибо моим коллегам, WanChing, Samuel Huang, Ansgar за помощь в переработке нашего проекта и подготовке статей для публикации. Они являются старшими инженерами по Android, занимающимися программированием архитектуры и алгоритмами, поэтому мы перенесли устаревшие коды в лучшую сторону. архитектура, как мы здесь делились.

Представьте

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

Ранее в приложении "Покупки" страница товара имела три стиля: отдельный товар, товар со скидкой по времени и продукт со скидкой со скидкой. Все три вида продуктов имеют схожий пользовательский интерфейс, но продукт со скидкой с ограниченным сроком действия и продукт со скидкой с ограниченным сроком действия имеют идентичную модель пользовательского интерфейса обратного отсчета. Более того, один продукт и продукт с ограниченной по времени продажей используют один и тот же сервер API, но продукт со сверхограниченной продажей использует другой сервер.

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

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

Архитектура

Просмотр

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

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

Кроме того, для этих сложных компонентов пользовательского интерфейса мы расширяем возможности MVVM в меньшем объеме. Например, ползунок изображения страницы элемента принимает массив URL-адресов изображений и видео, генерирует разные ячейки каждого типа, обрабатывает частичное обновление различий и другую неявную логику рендеринга. В этом случае мы упаковываем ползунки этого изображения с его MVP: массив URL - это его logModel, а докладчик вычисляет сценарии обновления diff и обновляет ползунок.

Модель пользовательского интерфейса

Модель пользовательского интерфейса разработана в соответствии с требованиями компонента пользовательского интерфейса, поэтому она не должна и не должна использовать структуру данных из удаленных API. Модель пользовательского интерфейса - это переходник между моделями данных из API-интерфейсов и компонентом пользовательского интерфейса.

ViewModel

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

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

Вариант использования

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

Преимущество

  • Чтобы добавить новый тип страницы элемента, мы реализуем только новую модель представления, она может запрашивать из новых API-интерфейсов, а затем преобразовывать эти новые структуры данных в соответствующие модели пользовательского интерфейса, а затем исходная страница элемента правильно отображает компоненты пользовательского интерфейса.
  • Чтобы добавить новый компонент пользовательского интерфейса, мы реализуем этот компонент пользовательского интерфейса и его парную модель пользовательского интерфейса, нам не нужно изменять какие-либо исходные коды или структуру, и это не повлияет на предыдущий тип страницы элемента. Таким образом, с этой архитектурой легко провести A / B-тест пользовательского интерфейса; мы заставляем ViewModel отправлять разные модели пользовательского интерфейса, а затем страница отображает другой пользовательский интерфейс.
  • Уметь реализовывать модульные тесты для всех ViewModel и даже UseCase. Это означает, что мы можем реализовать преобразование бизнес-логики и преобразование модели данных в модель пользовательского интерфейса.
  • Для этих сложных компонентов пользовательского интерфейса мы упаковываем их в меньшую архитектуру MVVM. Таким образом, поскольку этот небольшой MVVM не зависит от жизненного цикла страницы и платформы Android / iOS, мы можем быстро протестировать эти компоненты пользовательского интерфейса с помощью дополнительных модульных тестов.

Заключение

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

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