Comments 32
Optimistic UI создает куда больше проблем, чем приносит пользы. Я сейчас как раз готовлю доклад на эту тему, где буду активно пинать эту концепцию. На самом деле, эта идея новая только для веба, а в мобайле ей больше 10 лет
Я буду весной выступать, материал пока в процессе разработки.
Основные проблемы:
1) вы не можете использовать Optimistic UI всюду. Очевидно, что у вас будут критичные процессы, где нельзя обманывать пользователя. В итоге это и для вас накладные расходы, и для пользователя: вам надо реализовывать два механизма работы с API/backend и пользователю тоже может быть неочевидно, что случилось "на самом деле", а что нет.
2) При выходе из оффлайна или при обработке очередной порции отложенных действий, у вас может упасть промежуточное действие, и нет решения в общем случае, как это правильно разрулить: rollback всех действий? игнор и выполнение последующих? А если они связаны? Как UI адекватно обновить, если 7 действий случились, а 3 упали? Причем разруливать надо и на сервере, и на клиенте. Самое печальное, что каждый подобный кейс требует обдумывания, а "думать" — это штука, которая плохо поддерживается, масштабируется и реюзается.
В итоге плюсы сомнительны, а минусов выходит много. Я не говорю, что нельзя использовать эту концепию, нет, просто область ее применимости очень узкая и не заслуживает того внимания, которое ей сейчас уделяется. Думаю, что примерно через год сообщество к этому придет
Лол, его я буду пинать больше всех, потому что тот уровень сложности, который он добавит в проекты со 100+ пользователями я даже измерить не могу. Мы с автором немного пообщались недавно и надеюсь, что у нас будет дружественный баттл через некоторое время. Он парень очень умный, поэтому хочу пожелать ему успехов, и надеюсь, что моя критика лишь поможет ему сделать крутое решение.
Если чуть более предметно, то он не решает ни одной из этих проблем: вам не только нужно на сервере реализовывать conflict resolution, но еще и логи где-то хранить, причем непонятно как долго. Хуже того, вы не можете доверять логам, так как by design timestamp "не должен расходиться больше секунды", но если при первом подключении у нас случился delay в 3 секунды, то timestamps уже разошлись, не говоря о том, что никто не мешает клиенту подделать timestamp. Там есть еще пачка проблем, но я о них, пожалуй, умолчу, а то на доклад ничего не останется
Это похоже на асинхронный UI. Собственно и проблемы от этого уже описаны выше.
По факту получается так — по умолчанию всё делает синхронным и только там где это точно никому не навредит делаем оптимистично/асинхронно.
ЗЫ к слову как однозначно определяется к примеру сообщение которое ещё не побывало на сервере? Ей на клиенте придумываем ID? Ведь когда от сервера придёт ответ надо точно понять о каком таске этот ответ.
откуда он взялся? Как его с генерировали? Как избежать коллизий?
В мобильном мире это делается так:
1) на клиенте генерится очень большой временный id, который хранится локально, разумеется, мы умеем отличать временные и полноценные данные
2) При синхронизации сервер обрабатывает запрос и возвращает ответ с тем id, который присвоен в backend.
3) Конфликтов, как правило, избежать нельзя, поэтому бэкенд согласно реализованной бизнес-логике разруливает такие ситуации, как мы хотим.
т.е. пока сервер не ответил мы живём с временным случайно сгенреным ID а после того как сервер ответил уже с нормальным ID с сервера?
В целом ясно.
Частью айди может быть айди отсылающего юзера, тогда никаких коллизий не будет.
Мне кажется, даже если организовано локальное хранение необработанных сервером запросов (чтобы переотправить их позже, если юзер уходит со страницы или рвётся связь), какая-то индикация незавершённости действия должна присутствовать. Многие люди не слишком задумываются о механизмах работы вычислительной техники, вот, например, статья на Geektimes. Увидев элемент UI сразу в финальном состоянии без какой-либо переходной индикации, он посчитают данное изменение Вселенной совершённым, и будут потом озадачены исчезнувшими лайками, комментариями и всем чем угодно, что дизайнеры сочтут второстепенным. Или будут уверены, что отправили срочное сообщение, в то время как оно незаметно зависнет в очереди на отправку ввиду отсутствия связи.
Тут сразу на память приходит фейсбук с крупной подляной в мессенжере — там если тебе написал человек который не в списке друзей, ты просто не увидишь это сообщение потому что оно прячется глубоко в недрах фейсбука за незаметной ссылкой и о приходе таких сообщений тебя никак не уведомляют. А ведь автор письма когда его отправляет, находится в полной уверенности что вы сообщение видели и просто не хотите отвечать. На себе почувствовал это и с той и с другой стороны и очень сильно матерился когда понял в чем причина.
Как вариант конкретно с мессенджером, что мешает отображать неотосланные сообщения другим цветом?? Пока оно оранжевое (что хорошо показывает накал ситуации), оно ещё в очереди. Отослалось — поменялось на зелёный. В этом случае я никогда не пропущу проблему доставки.
В результате, я решил эту проблему так. Все операции выполняются (на сервере) последовательно в порядке их выполнения пользователем. При этом любая операция обязательно будет выполнена — если произошла сетевая ошибка, то пользователь увидит соответствующее блокирующее сообщение, и есть два варианта — или будем пробовать восстановить соединение и продолжить выполнение очереди команд, или закончим сеанс игры. Таким образом, нет необходимости информировать пользователя о неуспешной операции и предлагать повторить её.
При этом часть операций выполняется как неблокирующие, то есть показывается просто прогресс-бар сверху экрана, а часть — полностью блокирующие интерфейс.
Кратко про оптимистичный UI. Оптимистичные интерфейсы в картинках