Как стать автором
Обновить
39
0
Юрий Дымов @yury-dymov

Full Stack And Mobile Senior Developer

Отправить сообщение

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

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

Вот именно для мессенджера, особенно если очередность сообщений не важна, Optimistic UI хорошо подходит. Но это как раз то исключение, которое подтверждает правило

Безусловно, но быстрые бэкенды бессильны перед плохим или медленным интернетом.

Хороший текст, я даже для себя немного нового узнал. Правда я плюсанул :)

Давайте я вам расскажу. Приложение на клиенте выполняется все время: там всякие таймеры, бэкграунд события, работа со стейтом и тд.


Сервер сайд рендеринг конвертит HTTP запрос в HTML и отдает его клиенту. Все! Поэтому он и тянет 1000 клиентов и утечек там не происходит. Задержка для обычных SPA происходит, потому что надо выкачать JS, обработать его и запустить. Здесь и проходят потеря времени. Изоморфные приложения дают контент юзеру раньше, чем обработается JS, что улучшает UX и делает ваш ресурс SEO-friendly.


Дебажать также просто — у вас код общий на клиенте и на сервере на 90+%. Так что разницы между SPA и изоморфной частью нет особенно. Тут более подробно — https://habrahabr.ru/post/309958/

JSON API — это формат представления данных, настройка над JSON. Именно поэтому я отказался от redux-json-api и написал свое решение — я сам хочу управлять стейтом, как мне удобно для своего проекта, а не городить костыли и redux middleware, чтобы реализовывать бизнес-логику.


GraphQL — это решение "под ключ", их, наверное, не очень корректно сравнивать. Я пробовал использовать GraphQL в рамках Proof of Concept и для нужд моего проекта он подошел плохо, по крайней мере, он создавал больше проблем, чем их решал. Я бы мог поспорить с каждым из ваших аргументов, которые вы описали, как плюсы, кроме вебморды, чтобы тестить запросы. Количество кода он не уменьшает — вы его просто переносите на клиент в виде Query, объем трафика вы ощутимо снижаете только при работе с огромными объектами с 200 полями, и, если вы не фейсбук, то у вас их скорее всего не будет. При этом вы ломаете транзакционность, так как тащите объект в store по частям и не факт, что полученный объект будет соответствовать тому, что у вас в бекенде. Хотите сохранить транзакционность? Ломаете кеш. Главный плюс GraphQL следующий — вы стандартизируете разработку API и взаимодействие с ним, если у вас большая команда, то вы снижаете свои издержки на коммуникации и "подумать". Но это не killer feature.

Убрал в спойлеры

Да, справедливо


Для работы с normalizr необходимо явно указать Scheme ваших данных, что излишне для работы с JSON API (я имею в виду именно стандарт http://jsonapi.org, а не произвольный API в формате JSON), так как сам документ содержит в себе все необходимые метаданные. Normalizr просто не подходит для работы с JSON API. Вероятно, их можно интегрировать, но трудозатраты на это едва ли оправданы. Также normalizr заточен на работу с данными, в то время, как JSON API функционально богаче и может содержать мета-данные и ссылки для pagination, sorting, filtering.

Спасибо за комментарий, этот код я скопи-пастил с real-world-example Дэна Абрамова.


Мне нужно было проиллюстрировать, что json-api-normalizer позволяет интегрировать JSON API и redux одной строкой, что я и сделал :) Так что вполне допускаю, что именно этот кусок можно было написать лучше

Спасибо за теплые слова!


Я не уверен, что на 100% правильно понял вопрос, но постараюсь ответить. JSON API не является "движком", на котором вы реализуете API. Это лишь набор правил, которые описывают:


  • как конвертировать данные в формат JSON API
  • как должны выглядеть URI веб-сервисов и формат CRUD запросов
  • формат предоставления URL, чтобы клиент мог автоматически распознать pagination объекты и знать, как запросить следующую порцию.

То есть, мы имеем дело исключительно с форматом представления данных и форматом методов работы с ними, — некоторая надстройка над традиционным JSON'ом, которая ничего не знает и не должна знать о вашей бизнес-логике, но содержит мета-информацию (типы объектов, ссылки для pagination и т.п.).


Конвертацию из JSON API в объекты на стороне клиента делает моя библиотека (тут валидация, вероятно, не нужна), на стороне сервера делает какая-нибудь другая библиотека, которая будет у каждого стека своя. Далее уже вы валидируете объекты после конвертации как обычно. Если вам прислали "кривой" запрос, то ловите исключение парсера в контроллере и возвращаете ту ошибку, которая вам кажется логичнее.

А если модифицируют один и тот же объект, при этом из-за оффлайна/медленного интернета более старый запрос приходит вторым?

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

там решение — просить timestamp у юзера в момент первого запроса, а потом вычислять дельту с учетом server timestamp. Если timestamp юзера шел больше секунду, то у вас расхождение больше секунды. Также со стороны клиента я могу подменять timestamp как хочу и сервер ничего не сможет с этим сделать.

Лол, его я буду пинать больше всех, потому что тот уровень сложности, который он добавит в проекты со 100+ пользователями я даже измерить не могу. Мы с автором немного пообщались недавно и надеюсь, что у нас будет дружественный баттл через некоторое время. Он парень очень умный, поэтому хочу пожелать ему успехов, и надеюсь, что моя критика лишь поможет ему сделать крутое решение.


Если чуть более предметно, то он не решает ни одной из этих проблем: вам не только нужно на сервере реализовывать conflict resolution, но еще и логи где-то хранить, причем непонятно как долго. Хуже того, вы не можете доверять логам, так как by design timestamp "не должен расходиться больше секунды", но если при первом подключении у нас случился delay в 3 секунды, то timestamps уже разошлись, не говоря о том, что никто не мешает клиенту подделать timestamp. Там есть еще пачка проблем, но я о них, пожалуй, умолчу, а то на доклад ничего не останется

В мобильном мире это делается так:


1) на клиенте генерится очень большой временный id, который хранится локально, разумеется, мы умеем отличать временные и полноценные данные
2) При синхронизации сервер обрабатывает запрос и возвращает ответ с тем id, который присвоен в backend.
3) Конфликтов, как правило, избежать нельзя, поэтому бэкенд согласно реализованной бизнес-логике разруливает такие ситуации, как мы хотим.

Я буду весной выступать, материал пока в процессе разработки.


Основные проблемы:
1) вы не можете использовать Optimistic UI всюду. Очевидно, что у вас будут критичные процессы, где нельзя обманывать пользователя. В итоге это и для вас накладные расходы, и для пользователя: вам надо реализовывать два механизма работы с API/backend и пользователю тоже может быть неочевидно, что случилось "на самом деле", а что нет.
2) При выходе из оффлайна или при обработке очередной порции отложенных действий, у вас может упасть промежуточное действие, и нет решения в общем случае, как это правильно разрулить: rollback всех действий? игнор и выполнение последующих? А если они связаны? Как UI адекватно обновить, если 7 действий случились, а 3 упали? Причем разруливать надо и на сервере, и на клиенте. Самое печальное, что каждый подобный кейс требует обдумывания, а "думать" — это штука, которая плохо поддерживается, масштабируется и реюзается.


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

Optimistic UI создает куда больше проблем, чем приносит пользы. Я сейчас как раз готовлю доклад на эту тему, где буду активно пинать эту концепцию. На самом деле, эта идея новая только для веба, а в мобайле ей больше 10 лет

Мм, тогда зачем вам jss? Вы же хотите избавиться от фишки, которая лежит в его фундаменте. Можно сделать форк, взять build-time, выкинуть все ненужное и получить какой-нить новый *ss :)

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность