Это глава 46 раздела «SDK и UI-библиотеки» моей книги «API». Второе издание книги будет содержать три новых раздела: «Паттерны API», «HTTP API и REST», «SDK и UI‑библиотеки». Если эта работа была для вас полезна, пожалуйста, оцените книгу на GitHub, Amazon или GoodReads. English version on Substack.
В предыдущей главе мы обсудили, каким образом можно упростить разработку сложных компонентов с использованием паттерна «модель». Другой способ обойти сложность «переброса мостов» между несколькими предметными областями, которые нам приходится сводить в рамках одного UI-компонента — это убрать одну из них. Как правило, речь идёт о бизнес-логике: мы можем разработать компоненты полностью абстрактными, и скрыть все трансляции UI-событий в полезные действия вне контроля разработчика.
В такой парадигме код поиска предложений выглядел бы так:
class SearchBox {
…
search(query) {
const markup = await api.search(query);
this.render(markup);
}
…
}
То есть вместо получения машиночитаемых результатов поиска, мы получаем с сервера их готовое представление в виде кода на HTML либо другого (возможно, разработанного специально для нашего SDK) языка разметки.
Этот подход можно обобщить ещё сильнее:
class SearchBox {
constructor (…) {…}
stateChange (patch) {
// Получаем от сервера
// список действий, которые
// необходимо выполнить при
// запрошенном изменении
let actions = await api
.getActions(
this.model,
patch
);
// Применяем действия
…
}
}
В этом примере подразумевается, что SearchBox
не содержит вообще никакой другой логики, кроме отсылки на сервер событий, с ним произошедших (действий пользователя или разработчика) и показа присланного с сервера контента.
(Примером реализации этой идеи можно считать т.н. «Web 1.0» — сервер присылает готовый контент страницы, а вся интерактивность сводится к переходам по ссылкам.)
Хотя Backend-Driven UI обладает очевидным недостатком в виде требовательности к качеству соединения с сервером, у него есть два очень важных преимущества:
возможность с сервера регулировать поведение клиента, в том числе устранять возможные ошибки в бизнес-логике в реальном времени без необходимости обновлять приложение;
возможность сэкономить на разработке консистентной и читабельной номенклатуры сущностей публичного SDK, ограничившись минимальным набором доступной функциональности.
Тем не менее, мы не можем не отметить: при том, что любая крупная IT-компания проходит через эту фазу — разработки Backend-Driven UI (они же — «тонкие клиенты») для своих приложений или своих публичных SDK — мы не знаем ни одного заметного на рынке продукта, разработанного в этой парадигме (кроме, разве что, протоколов удалённых терминалов), хотя во многих случаях возникающими сетевыми задержками вполне можно было бы пренебречь. Рискнём сказать, что причины сложившегося положения вещей таковы:
разработать серверный код управления UI ничуть не проще, нежели клиентский;
-
современные клиентские устройства предоставляют широкий спектр функциональности, доступной только клиентскому разработчику, от кэшей до анимаций;
гибридный код, который частично получает состояние с сервера, частично обогащает его на клиенте, писать гораздо сложнее, чем чистый клиентский (в силу того, что в Backend-Driven UI содержимое ответа сервера для клиента представляет собой «чёрный ящик», для взаимодействия с которым приходится изобретать дополнительные протоколы);
отказ от гибридного кода, во-первых, сужает возможности приложения и, во-вторых, фактически переводит клиентское устройство в режим «облачного гейминга», что на сегодня очень дорого и не очень удобно для пользователя;
сложившая практика такова, что разработка бэкенда и клиентского кода — разные специализации, требующие разной экспертизы и разных подходов к написанию кода.
NB: следует различать Backend-Driven UI и технологию серверного рендеринга (SSR). Второе подразумевает, что одно и то же состояние UI (как правило, в виде HTML-разметки или аналогичного декларативного описания) может быть сгенерировано как сервером, так и клиентом. В SSR, однако, подразумевается, что клиент может интерпретировать ответ сервера и извлекать из него семантические данные.
С точки зрения предложения SDK сторонним разработчикам, Backend-Driven UI фактически вынуждает разрабатывать гибридный код (поскольку практика предоставления партнёрам возможности встроиться в функции серверного рендеринга на стороне провайдера API выглядит весьма далёкой от жизнеспособности идеей), и, таким образом, будет страдать от той же проблемы непрозрачности — разработчик не может со своей стороны определить, в каком сейчас состоянии находится визуальный компонент. Как ни странно, этот недостаток одновременно является и достоинством, поскольку вендор API сохраняет возможность на своей стороне производить любые манипуляции с контентом без нарушения обратной совместимости (мы обсудим этот вопрос в главе «Линейка сервисов API»). Таких клиентских API в мире существует довольно много (в первую очередь, разнообразные виджеты, рекламные API и т.д.), но их сложно назвать полноценными SDK.
TrueRomanus
Это очень хорошая идея но ровно до того момента когда появится интерактивность внутри этого представления.
Решив проблему с универсальным UI на каждых чих приезжающий с сервера возникнет совсем другой класс проблем. Сетевых проблем, результатом которых будет либо недогруженный UI или несоответствие версий UI, измененные пути ведущие в 404 и т.п.
Тут очень важно понимать что такое "тонкий клиент" по Вашему а то таких технологий может оказаться очень много, например бутстрапер любой MMORPG это тонкий клиент или нет?
А если мы говорим о вебе то нет ни одного заметного продукта потому что фаза эта закончилась провалом для таких технологий как Flash, Silverlight, Java Applet и других.
Вместо этого усилия сообщества были направлены на то чтобы все что было в этих технологиях появилось и в web браузере и не надо было кучу тонких клиентов ставить заходя на рандомный сайт. Сейчас никто этим не занят потому что в этом просто нет никакого смысла. Уже даже десктопные приложения делают на технологиях вроде Electron которые по сути web браузер с щепоткой клиентского кода.
Возможно Вы имели ввиду "разрабатывать клиентское приложение работающее не на клиенте а по факту работающее на сервере сложнее"?
И чем плох вариант с генерация клиентом?
Когда соединение с сервером нестабильно или теряется Во что превратится UI? Одно дело UI "на клиенте" он просто покажет крутилку или что-то в таком духе но сам по себе продолжит быть отзывчивым, весь оффлайн функционал продолжит работу. Но в случае с Backend-Driven UI не получиться поставить даже крутилку потому что связь просто пропадет. Сетевые проблемы также могут сильно подпортить UX пользователю он будет либо часто видеть крутилку, либо нажимать на кнопки и другие интерактивные элементы а интеракции не будут происходить.
forgotten Автор
Нет. GeForce now — скорее да, и то с некоторой натяжкой. MMORPG всё-таки позволяют кнопки в меню нажимать локальным кодом, а не вызовом сервера.
Не вижу особой разницы между этими утверждениями
TrueRomanus
"Нет. GeForce now — скорее да, и то с некоторой натяжкой. MMORPG всё-таки позволяют кнопки в меню нажимать локальным кодом, а не вызовом сервера. "
Т.е. Backend-Driven UI это когда клиент просто "удаленный рабочий
столприложение" который картинку приезжающую с сервера показывает? С клиента только точки где мышка проезжает отсылаются и какие кнопки на ней (мышке) нажимаются? Я все верно понял?forgotten Автор
Я бы не был столь категоричен. Возможны разные варианты. Ключевой момент — клиент получает от сервера представление для рендеринга, а не семантичные данные. В случае MMORPG это, как правило, не так.
TrueRomanus
Объясните пожалуйста отличие "представления для рендеринга" от "семантических данных" пожалуйста.
forgotten Автор
`<div>Hello, TrueRomanus</div>` — представление для рендеринга
{ "user_name": "TrueRomanus" } — семантические данные
TrueRomanus
Спасибо за разъяснение. Я думаю за пределами Web такое проворачивать без изобретения своего HTML аналога крайне затруднительно.
forgotten Автор
Я видел множество попыток. И да, получается аналог HTML