Найти тему

View State Machine для сетевых вызовов на Android

Как однажды сказал Бен Франклин: "В этом мире нет ничего определенного, кроме смерти и налогов [и того, что спецификации программных продуктов всегда меняются]".

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

MVP

MVP (Model View Presenter) - это популярный архитектурный стиль для разработки Android. И хотя у него есть много хороших сторон - простота тестирования, хорошее разделение между views и model - есть и некоторые отрицательные стороны. Одно из особых разочарований, с которым я столкнулся, - необходимость обновлять view interface каждый раз, когда вы хотите обновить другой элемент пользовательского интерфейса. Например, если вы создаете страницу профиля, у вас может быть следующий view interface:

-2

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

-3

Это обновление view interface вызывает разочарование и является нарушением Open-Closed Principle.

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

Но хватит зрелого прагматизма, вернемся к плохому... Еще одна причина, по которой я нахожу подобные обновления разочаровывающими, заключается в том, что они могут отвлекать от общей картины происходящего в данном представлении и слишком много внимания уделять мельчайшим деталям визуальной реализации. Теперь я знаю, что вы думаете: "Но это же интерфейс представления! Он должен быть сфокусирован на визуальных эффектах!". И вы будете правы, но прежде чем у вас появится пчела 🐝 в капоте 👒 подумайте, что у нас еще нет полной картины. Пока что в нашем примере мы сосредоточились только на методах, которые работают с отображением User. Давайте посмотрим на Presenter, чтобы увидеть, как он получает User, чтобы лучше понять остальное, что происходит с этим представлением.

-4

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

-5

Наш view interface начинает выглядеть немного иначе. Теперь это не только детали User, но и некоторые сетевые состояния представления. Как вы можете себе представить, все view interfaces, работающие с presenter, который делает сетевые запросы, также должны добавить эти методы представления, связанные с сетью. Это означает много дублирования во всех наших интерфейсах представления, а это никому не нужно 🙅.

Networking View State

Поприветствуйте NetworkingViewState 👋. sealed class, который абстрагирует все различные состояния, в которых может находиться представление в результате сетевого запроса, в один тип.

-6

Теперь давайте обновим наш view interface с этим новым типом.

-7

И наш presenter...

-8

Теперь, если UI изменится, наш view interface, наш presenter и наши тесты не нужно будет менять, потому что поведение в общей картине останется прежним 💪.

Но мы еще не закончили... Хотя мы сделали наш код более SOLID, мы также потеряли некоторое тестовое покрытие. До внедрения NetworkingViewState наш presenter отвечал за преобразование объекта User, который мы получали в ответе от API, в соответствующие типы для отображения view interface. И поскольку эти отформатированные значения передавались через view interface, мы могли утверждать, что это правильные значения в наших тестах.

Вот так:

-9

Но с нашим обновленным презентером наши тесты теперь выглядят следующим образом:

-10

В случае успеха нет проверки объекта User, который передается. Как же нам вернуть эти тесты форматирования?

Правильно, view models! Когда мы устанавливаем NetworkingViewState на Success в нашем презентeре, вместо того, чтобы передавать объект User, мы можем передать UserViewModel. И мы можем добавить тесты для нашей UserViewModel в отдельном классе, чтобы убедиться, что все значения отформатированы правильно.

Что-то вроде этого:

-11

Ура 💪 ! Покрытие тестами восстановлено! Перевод статьи A View State Machine for Network Calls on Android