Клиент-серверная архитектура для разработчиков веб-приложений — это примерно как одна из черепах, на которой стоял мир в воззрениях наших предков. Трудно себе представить иное положение вещей. Однако бесчисленное количество веб-приложений сформировало новую потребность — управление данными на фронтенде. Пока нет единого подхода и реализации, есть только отдельные технологии, позволяющие работать с данными на клиенте. Да и с ними никто особо не заморачивается. А между прочим, пора. О том, что уже есть в плане работы с данными на фронтенде и что будет дальше, мы поговорили с Никитой Прокоповым aka tonsky.



— Никита, привет! Расскажи пару слов о себе, чем ты занимаешься?

— Я работаю в компании Cognician, которая занимается веб-платформой для образования и тренингов. Я там занимаюсь фронтендом и частично бекендом.

— В аннотиции к твоему докладу на HolyJS написано, что ты Clojure-хакер...

— Это связано с тем, что я пишу на Clojure уже несколько лет, года четыре, наверное. Все мои последние работы были на Clojure, есть определённая экспертиза.

— Если пройтись по Хабру, то сразу заметно, что Clojure встречается значительно реже, чем другие языки программирования. В то же время он использует JVM, интегрируется с Java в обе стороны, имеет ещё ряд преимуществ. Что на нём можно делать и кому Clojure подойдёт?

— Да, действительно, у Clojure есть небольшие проблемы с популярностью по сравнению, например, с той же Scala, у которой в этом плане всё хорошо. А вот Clojure в тени. Тем не менее, это не какой-то маргинальный язык, он всё же относительно широко распространён. В нём есть несколько классных идей.
Clojure стал пионером иммутабельности «налево и направо», в нём есть классные примитивы для синхронизации многопоточных параллельных программ, он умеет компилироваться в JavaScript. Clojure и ClojureScript для JVM и JavaScript идут нога в ногу, можно писать код, который работает и там, и там. Это язык общего назначения, рекомендуется всем, кому не нужен супер низкий latency или супер предсказуемость, как в системах реального времени. Он постепенно находит своё применение и в корпоративном секторе — в Boeing и Walmart пишут на нём код, то есть довольно серьёзный бизнес принимает решение переходить на Clojure.

— Заявленная тобой тема доклада — «Данные на фронтенде». О каких данных идёт речь и кому это вообще нужно?

— Тут такая история — серьёзно фронтендом я начал заниматься примерно год с небольшим назад, до этого в основном был упор на серверную сторону. Сейчас идёт рост тенденции, что приложения можно писать в браузере и их там действительно можно писать. Но пока фронтенд-культура не доросла до тех подходов, которые давно существуют на сервере. Писать приложения на фронтенде — это большой фронт работ: что и как правильно делать. Какие-то проблемы уже понятно, как решать, какие-то — пока нет. Одна из таких проблем — как хранить данные? На сервере много вариантов: файловая система, база данных, можно в памяти хранить или в кэшах. А на клиенте не очень понятно: есть ad hoc решения (как бог на душу положит, сохранить где-нибудь в local storage или в переменных), можно пытаться применять базы данных, которые для клиента тоже есть, но их гораздо меньше. Приложений становится больше и больше, им нужно работать с данными. Это серьёзная задача, требующая системного ответа, поиска архитектуры. В докладе я как раз хочу рассмотреть, какие подходы уже есть, какие у них плюсы и минусы.

— А что случится с бекендом? Он останется или необходимость в нём отпадёт?

— Конечно, он продолжает своё существование, потому что веб-приложения эфемерны: ты зашёл-ушёл, но хочешь, чтобы данные твои сохранились. Остаётся клиент-серверная архитектура, возможно база данных-сервер-клиент, а может, в будущем когда-то появится и просто база данных-клиент, это тоже один из возможных вариантов. Наличие сервера — это один из самых интересных моментов: когда сервер работает с данными, он находится в тепличных условиях, а клиент находится в условиях диких, плюс на него смотрит пользователь. Как раз из-за этого возникает много проблем, как сделать хорошо. То есть хочется, чтобы приложение быстро грузилось, работало в оффлайне и т.д., а как это сделать — не очень понятно. Если напрячься и делать конкретно для себя, то может что-то и получится большими усилиями. Но рано или поздно, я думаю, появятся какие-то системные решения, которые можно будет взять «с полки» и использовать.

— Мне это сложно представить. Как-то привычно: есть приложение, например, какая-то веб-CRM, клиент передаёт данные на сервер, всё как всегда. А тут раз — и нужно управлять данными на фронтенде. Когда, при разработке приложений какого типа пора задумываться о данных на фронтенде?

— Если речь именно о приложении (графический редактор, что-то жутко интерактивное), то, как только сайт/приложение становится динамическим, сразу возникает необходимость управления данными на фронтенде.

— В связи с разговором об управлении такими данными, расскажи о DataScript. Кажется, это твой проект?

— Ну да, я основной разработчик. Были несколько пул-реквестов, мне помогали люди, но в основном это моя разработка. Его идея в том, что если данные структурированы и их относительно много, их удобно хранить в некоем подобии базы данных. DataScript — один из примеров базы данных, очень лёгкой. Это даже не в полной мере база данных, а скорее in-memory структура данных, по которой можно запускать запросы и в которой есть транзакции. Грубо говоря, это достаточно удобная структура данных (они реляционные, между ними есть связи), внутри всё хранится в плоском виде, индексируется. По такой структуре удобно делать навигацию, как по графу, вперёд-назад и удобно быстро находить нужные данные. Плюс, есть иммутабельность — можно делать архитектуры, которые на React делаются, когда state хранится в одном объекте, он иммутабельный и можно undo/redo делать, есть транзакции — можно создавать реактивные системы. Есть язык запросов Datalog со своим синтаксисом и возможностями. Нет только персистентности, DataScript работает в памяти.

DataScript нужен, когда есть сложное многомерное состояние и хочется на него смотреть с разных сторон, трансформировать. DataScript известнее всего в Clojure-среде (хотя поддерживает Clojure, ClojureScript, JavaScript и JVM) и часто используется в связке с Datomic на сервере. Мы используем DataScript в Cognician, чтобы представлять сессию клиента (вопросы, ответы, комментарии, сценарии), плюс поверх этого синхронизируем лог событий в Datomic (в обе стороны). Ребята из Precursor используют такой же стек для коллаборативного рисования графики (фигуры, объекты, группы), у них тоже решение для синхронизации свое самописное. Есть пара проектов, где в DataScript хранится множество мелких свойств объектов, проекты по инвентаризации. Есть интернет-магазин даже. Это очень удобная основа, когда данные лежат аккуратно в одном месте, чтобы писать поверх нее системное решение для синхронизации, например.

— Сейчас в руках разработчиков находится целый зоопарк баз данных. Что выбрать? Или оно без разницы?

— Документо-ориентированные — самый простой вид базы данных. Если ничего нет лучше, то нужно брать их. Если говорить конкретно о клиенте, то выбор совсем маленький: есть miniMongo, PouchDB, они обе документо-ориентированные. Можно писать на голом local storage. В идеале, нужно брать базу, которая даёт много возможностей — в частности, синхронизацию с сервером. Прозрачная двухсторонняя синхронизация с сервером снимет большую часть головной боли.

— Раз уж пошла речь о синхронизации… Реактивная синхронизация данных, Swarm.js — что это?

— Реактивная синхронизация данных — это когда у сервера есть новая информация и он сам понимает, какому клиенту её отослать. Пока никто нормального это делать не умеет. Есть решение на базе RethinkDB и Meteor — ты явно подписываешься на сервере на определённые объекты или коллекции и они приходят тебе server-push-ем. Это нетривиальная задача и возникает много проблем: во-первых, клиентов много, а сервер один, во-вторых, как поддерживать этот список подписок. Поток изменений на сервере постоянный — клиентов много, через сервер проходят все транзакции и сервер должен распознать транзакции и понять, кого оповещать, а кого — нет. Эти задачи эффективно решаются очень узкими технологиями, если вообще решаются.


Кажется, эта картинка скоро перестанет быть актуальной

И там же возникает вопрос консистентности — хотелось бы ещё, чтобы были какой-то порядок и полнота во всех этих объектах. Это, собственно, реактивная модель — тут и на сервере с этим относительно всё плохо, почти никакие базы данных не умеют нативно оповещать о транзакциях и изменениях. Эта проблема серверными программистами решается с помощью очереди: мы не пишем напрямую в базу, а складываем задачи в очередь, читаем из этой очереди и пишем — тогда все, кому интересно, тоже могут читать из этой очереди. Реактивная модель достаточно новая именно для архитектуры всей системы. То есть внутри языка программирования можно что-нибудь такое нагородить, а вот когда речь идёт о целой системе (данные, база, сервер, интерфейс пользователя), то тут подходы пока только нащупываются. Речь о том, как такую штуку собрать.

Сервер и клиент — распределённая система, в которой клиентов много, а сервер один. Клиенты могут писать и читать с сервера. И здесь возникает модель, когда у клиентов накапливается пул изменений и мы хотим, чтобы они попали на всех остальных клиентов. Чисто теоретически эта задача не решается в общем случае, но она решается красиво для определённых видов достаточно простых структур данных. Swarm.js — это библиотека, которая предоставляет структуры данных, для которых проблема синхронизации решается красиво, и протокол их синхронизации. Грубо говоря, если я зашёл на одну и ту же страницу Amazon с двух браузеров и в одном браузере добавил один товар в корзину, а в другом — другой, эти две корзины можно слить операцией объединения и конфликтов быть не может. Проблемы начинаются, если возможно, например, удаление — тогда сливать нельзя и нужно что-то придумывать. Есть такое новое веяние в распределённых системах — CRDT (Conflict-free Replicated Data Type), это типы данных, которые легко сливаются и Swarm.js — одна из реализаций таких штук. Это всё кусочки паззла, а глобальная цель у нас — сделать полностью реактивную систему, в которой любые изменения, которые происходят, распространяются по всей системе, причём система состоит из базы, сервера и множества клиентов. IT находится в поиске такой системы. Скорее всего, это будет не какое-то готовое решение, а подход, следуя которому можно уже создавать архитектуры.



Послушать Никиту, подискутировать с ним, а также с остальными докладчиками, рассказать о своих находках и мыслях о будущем можно будет на конференции HolyJS, которая пройдёт в Санкт-Петербурге 5 июня 2016 года.
Поделиться с друзьями
-->

Комментарии (37)


  1. 23derevo
    13.05.2016 17:11

    tonsky ты мне как ламеру поясни — правильно ли я тебя понял, что в области хранения данных веб-приложениями много открытых проблем и нет готовых рецептов?


    1. tonsky
      13.05.2016 18:18

      Да :)


  1. MooNDeaR
    13.05.2016 17:21
    +6

    То есть, если я правильно понял посыл, теперь все хотят изобрести десктопные приложения, только более тормозные, потому что в браузере?

    Ведь в сущности, все равно браузеры все равно работают по разному (считай те же проблемы, что и поддержка разных OS). В чем профит? Ведь я могу взять C++Qt или на худой конец Python и не иметь проблем с хранением данных на клиенте и переносимостью + иметь скорость работы в 10 раз выше.


    1. TheSteelRat
      13.05.2016 18:59
      +5

      Я думаю, что тут вся причина в популярности JS. Из-за этого его пытаются втулить везде где только можно: сервер, десктоп, МК…


    1. tonsky
      13.05.2016 19:50
      +4

      О, это очень интересная тема, на самом деле, зачем вообще веб-приложения. Я так понимаю, факторов несколько:
      — кроссплатформенность
      — не нужно устанавливать
      — UI неплохо рисуется
      — среда разработки крутая (dev tools)
      — легко интергировать другие сервисы (intercom, например)
      — спиратить веб-приложение нельзя

      Т.е. если подумать, сделать скажем коллаборативное редактирование можно было бы и десктопном Word-е, и даже каких-то особенных трудностей было бы меньше, возможно (Google Docs, все-таки, в основном занимались тем, что превозмогали платформу, а не пилили код), но почему-то натуральным кажется делать его только в вебе. Наверное, потому что это общее место, где все живут рядом, и логины, и почта, и общение. Ну и понятие «файла» мешается, хочется чтобы все редактировали общий файл, а не у каждого лежал свой, соответственно он должен жить где-то в интернете.


      1. InfiniteCode
        13.05.2016 21:37

        Помоему, как раз перетекание всего на фронтенд и оставить на бекенде только БД, является прямой противоположностью «спиратить нельзя».


        1. AndryX
          14.05.2016 01:24

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


          1. InfiniteCode
            14.05.2016 01:31
            +2

            Нельзя так сделать, если все лежит в одном месте. Именно поэтому RSA, да и в целом все уже давно работают c двумя ключами — публичный и приватный. В противном случае рано или поздно расковыряют и скопируют все что нужно.

            У нас был замечательный прецедент, когда китайцы умудрились спиратить целиком игру на флеше. Они ее декомпилировали, локализировали сами, разобрали АПИ бекенда и полностью новую серверную часть написали. В итоге, через буквально пару месяцев после выхода игры была такая же но на китайском.


            1. tonsky
              14.05.2016 19:59

              Это если бэкенд простой, положи-сохрани. Пиратские клоны Google Docs, например, бывают?


              1. InfiniteCode
                15.05.2016 08:13

                Зачем кому-то пиратить бесплатное приложение? Поэтому и нету.


                1. tonsky
                  15.05.2016 10:03

                  Так оно не бесплатное. $5/user/month. Плюс вопросы приватности, корпорации не хотят хранить данные «у дяди». Гитхаб, например, альтернативный есть, но там он полностью с нуля переписан, и бэкенд, и фронтенд.


                  1. InfiniteCode
                    16.05.2016 19:25

                    docs.google.com, с каких пор стало платное? Там платное только для компаний, но это уже полноценный пакет Google for business, который включает куда больше.


        1. tonsky
          14.05.2016 20:00
          +1

          А вот это, кстати, очень интересный момент. Да, если вместо бэкенда будет стандартная БД, то пиратиться все это будет проще простого.


      1. MooNDeaR
        15.05.2016 00:03
        +1

        — Кроссплатформенности как таковой нет. Все равно приходится поддерживать зоопарк браузеров (причем и десктопных и мобильных), ведь у каждого свои загоны с отображением стилей, расположением элементов и каждый еще себе отдельный JavaScript-движок пилит. В общем, те же проблемы что и поддержкой разных ОС.

        — UI и на десктопе неплохо рисуется. Тем более сейчас есть куча штук позволяющих создавать UI с помощью CSS-стилей и HTML-подобной разметки (XAML, QML и все такое)

        — Как будто для других языков нет крутых IDE? Я уж не говорю о том, что отладка приложений на десктопе в разы проще

        — Обычно у «других сервисов» есть API для различных языков, не только для JavaScript.

        — Про «спиратить» ничего сказать не могу. Но кто мешает написать приложение-клиент на декстопе, которое будет все важные данные получать только с сервера и без этих данных работать не будет? Те же файлы хранить только на сервере и будет вам разделяемые ресурсы.

        Итого имеем, что почти единственный незаменяемый «плюс» — не нужно устанавливать. Вот только с не очень быстрым интернетом задолбаешься каждый раз грузить это приложение. Не говоря уже о том, что приложения эти и так работают оч медленно.


  1. Amareis
    13.05.2016 18:18
    +3

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

    Вообще, мне интересно: возможен ли перенос концепции реактивности на уровень железа? Впрочем, понятно что возможно всё; правильней сказать, имеет ли это практический смысл, ускорит это программы и упростит ли жизнь программистам?


    1. tonsky
      13.05.2016 18:35
      +4

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


      1. Amareis
        13.05.2016 18:59

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


  1. BalinTomsk
    13.05.2016 23:55
    +1

    ----Он постепенно находит своё применение и в корпоративном секторе — в Boeing и Walmart пишут на нём код, то есть довольно серьёзный бизнес принимает решение переходить на Clojure.

    Несколько неубедительный аргумент. Компании больших размеров покупают в среднем 2-3 компании в день. Среди них может оказатся любой зоопарк решений.

    В свое время RIM купил Blackberry Solution for GroupWise написанное на VB, переписав в последствии на С++, но это не мешает сторонникам VB говорить, что на VB даже RIM-e используется.

    Или допустим покупает IBM продукт как Blackberry Enterprise Service, а в качестве хранилиша данных там используется только MSSQL, можно вполне утверждать, что DB/2 настолько плоха, что даже сами айбиэмовцы пользуются услугами конкурента.

    Если бы Walmart заявил что является стратегическим партнером компании, производяшей Clojure, то оригинальному сообшению было больше веры.


    1. tonsky
      14.05.2016 19:58
      +1

      Аргумент действительно неубедительный. Маленькие языки таким вот и перебиваются — кто-то где-то в какой-то компании на нем пишет. Такого, чтобы супергигант поставил на что-то маргинальное, не бывает по определению.


  1. msvn
    14.05.2016 11:56

    Уместным будет обсудить вот эту штуку —  ApolloStack  от разработчиков Meteor. Думаю, она достойна статьи на Хабре.


  1. lavebug
    14.05.2016 13:54

    Странно что www.cognician.com не оптимизирована под малые окна/мобильные?


    1. tonsky
      14.05.2016 19:56
      +1

      Почему странно? Первый раз увидели сайт, не оптимизированный под мобильник?


      1. lavebug
        15.05.2016 07:21

        Нет, уже 2016 к концу подходит почему бы не оптимизировать.


        1. tonsky
          15.05.2016 10:00

          мм, приоритеты?


  1. lanvin07
    14.05.2016 13:54

    Можно писать на голом local storage"
    Увы, далеко не всё.
    Например, есть информация, что iOS в любой момент может освободить Local Storage при нехватке памяти, и Android движется в этом направлении.
    Не хочется в это верить, но вот ссылки:
    Don't Assume localStorage Will Always Work In Your Hybrid App
    Localstorage — is it cleared after app restarts/ periodically in iOS?
    localStorage not being persisted in hybrid app
    Мне в своём мобильном приложении, использующем Local Storage для хранения некоторых данных (настройки и т.д.), с обнулением LS пока не приходилось сталкиваться, но англоязычные товарищи, как видите, беспокоятся.
    Вот и думай теперь, то ли забить, то ли смотреть в сторону PouchDB или чего-то ещё.


    1. lanvin07
      14.05.2016 17:25

      Почему-то ссылки не публикуются…
      Вот они текстом:
      http://gonehybrid.com/dont-assume-localstorage-will-always-work-in-your-hybrid-app «Don't Assume localStorage Will Always Work In Your Hybrid App»
      https://forum.ionicframework.com/t/localstorage-is-it-cleared-after-app-restarts-periodically-in-ios/21819 «Localstorage — is it cleared after app restarts/ periodically in iOS?»
      https://bugs.chromium.org/p/chromium/issues/detail?id=481380 «localStorage not being persisted in hybrid app»


    1. tonsky
      14.05.2016 20:02

      Ну я говорил все-таки не о персистентном хранении, а о том, как хранить состояние приложения в течение одной сессии.


  1. caballero
    14.05.2016 14:35
    -2

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


    1. tonsky
      14.05.2016 20:02

      А что, бывает необлачный веб?


      1. caballero
        14.05.2016 20:53
        -1

        вы правду не понимаете разницу между облачными сервисами и просто веб сервером апач на шаред хостинге?
        В любом случае сути дела не меняет. Нет никаких причин выполнять вычисления на стороне клиента. Это просто нерентабельно.


        1. lair
          14.05.2016 23:37
          +3

          Нет никаких причин выполнять вычисления на стороне клиента. Это просто нерентабельно.

          Раундтрип до сервера всегда быстрее?


        1. tonsky
          15.05.2016 10:00
          +2

          > вы правду не понимаете разницу между облачными сервисами и просто веб сервером апач на шаред хостинге?

          Облако — это просто чей-то чужой сервер.

          > Нет никаких причин выполнять вычисления на стороне клиента

          Какие вычисления-то?


        1. unpete
          15.05.2016 19:10
          +1

          Нет никаких причин выполнять вычисления на стороне клиента. Это просто нерентабельно

          Очень даже есть причины. И автор говорит о них в статье (для интерактивности данные должны быть под рукой).
          А нерентабельно, как раз гонять мегабайты между клиентом и сервером. Данные веб-приложения можно разделить на
          • условно-постоянные (справочники и перечисления)
          • часто изменяемые (документы)
          • служебные (индексы и регистры)

          Справочники логично кешировать в IndexedDB и загружать в память браузера при старте приложения.
          Документы и регистры могут реплицироваться с сервером в зависимости от от задачи в разных пропорциях.
          В metadata.js мы попытались завернуть ссылочную типизацию и репликацию с PouchDB и 1С в некое высокоуровневое API — получилось достаточно эффективно для разработки offline-first браузерных приложений.


          1. caballero
            15.05.2016 20:04

            при нынешних скоростях и копеечной стоимости интернета (про ближайшее будущее даже говорить не приходится — уже 5g сети тестируют) — такие танцы с бубном как реплицирование БД и синхронизация справочников — дикий изврат. Такие проблемы были лет десять назад. Теперь SAAS сервисы и иже с ними очень даже интерактивно работают с обычным тонким клиентом в браузере.


            .


            1. unpete
              15.05.2016 21:08
              +1

              уже 5g сети тестируют

              У моих клиентов реальная потребность в offline-first. Базовая функциональность приложения должна быть доступна offline.
              Станки должны крутиться и машины разгружаться вне зависимости от наличия связи.

              с обычным тонким клиентом в браузере

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


              1. caballero
                16.05.2016 12:12
                +1

                Там, к сожалению, без данных на клиенте не получается.

                Если у вас что то не получается это ваши проблемы — учите матчасть. Нет никаких причин вытаскивать данные на клиента.
                Потому что это не дает никаких преимуществ (если это конечно не браузерная игра какая нибудь). Только создает проблемы. Во первых стоимость разработки — кроме серверной части, которую и так надо делать, нужно делать клиентскую, а стоимость работы программиста гораздо выше нынешней стоимости железа. Во вторых такие решения очень плохо идут на мобильных платформах — а клиенты ща переезжают именно туда (это как пример РЕАЛЬНОЙ жизни).

                У моих клиентов реальная потребность в offline-first. Базовая функциональность приложения должна быть доступна offline.

                По моему мы обсуждаем общий подход а не специфических клиентов в шахте или глухой таежной деревне.
                Но для подобных клиентов пишутся десктопные проги — вам не кажется нелогичным писать приложение в браузере для клиентов у которых нет нормального интернета?..


            1. tonsky
              16.05.2016 11:22

              http://www.uxmatters.com/mt/archives/2016/04/beyond-airplane-mode.php