Этот день всё-таки пришел. Мы выкатили обновленную версию редакторов документов ONLYOFFICE Document Editors 3.6 с быстрым совместным редактированием, как в Google Docs. Его давно просили, требовали, угрожали, но мы были неумолимы. До тех пор, пока не сдались под напором пользователей, желающих редактировать свои секретные материалы, в режиме реального времени наблюдая, что набирает соавтор.

Далее расскажем, почему мы так противились «быстрому» совместному редактированию, чем наш вариант отличается от похожего режима в других онлайн-редакторах и как мы собираемся решать вопрос undo/redo.



Строгий vs быстрый


Когда мы выбирали, как именно будет реализована совместная работа с документами в наших редакторах, у нас не было никаких сомнений в том, что «строгий» режим — лучший вариант. Работая таким образом, пользователь видит правки соавтора только после того, как тот сохранит изменения.

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

Другие аргументы в пользу «строгого» режима редактирования:

  • Отсутствие отвлекающих факторов в виде комментариев коллег относительно внесенных изменений и их собственных правок;
  • Отсутствие конфликтов с undo/redo;
  • И, конечно же, возможность поправить грамматические и пунктуационные ошибки, до того как коллеги разразятся вихрем шуточек по этому поводу.

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

Мы не комплексовали по поводу отсутствия быстрого режима совместного редактирования, однако пользователи хотели его. Как и наш отдел PR, практикующий совместное творчество в режиме real-time. В общем, мы сдались и даже нашли

Плюсы «быстрого» режима:

  • Удобство и скорость при работе с небольшими документами (несколько страниц);
  • Зрелищность;
  • Удобство для совместной разработки идеи, например, мозгового штурма;
  • Возможность оперативно внести и отследить финальные правки при совместной работе над итоговой версией документа.

В новой версии редакторов «быстрый» режим совместного редактирования установлен по умолчанию. Вернуть классический «Строгий» можно, следуя несложной схеме: меню «Файл» — вкладка «Дополнительные параметры» — «Co-editing mode». Переключаться между режимами можно в любое время.

Как всё устроено


При «строгом» редактировании происходит «зажатие» фрагмента документа, над которым работает пользователь. Для его соавторов объект заблокирован до тех пор, пока пользователь не сохранит свои изменения. После сохранения объект разблокируется, пока кто-то вновь не примется неистово его редактировать. При «строгом» редактировании пользователь сохраняет свои правки руками. Кроме того, раз в десять минут происходит автосохранение документа.

При «быстром» редактировании механизм работы, по сути, не меняется. За исключением того, что автосохранение происходит чаще. 25 раз в секунду таймер запрашивает наличие изменений и, если они были внесены, делает save. Сразу после сохранения объект разблокируется. Таким образом, создается ощущение, что редактируемый фрагмент даже не был заблокирован. На самом деле, lock существовал лишь 1/25 секунды и, если в нашем редакторе не набирает текст Флэш, то, в общем, эту маленькую хитрость никто не заметит.

Операциональное преобразование


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

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

Суть алгоритма в следующем:

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



Для алгоритма действия пользователей можно записать как ins(«x», 0) (вставка буквы «x» в нулевую позицию) и del(1) (удаление в позиции 1). Попробуем последовательно выполнить эти преобразования с учетом того, чьи изменения первыми придут на сервер:



Видно, что сложность заключается не только в самих изменениях, но и в том, кто из пользователей успел отправить свои правки первым. Решение данной проблемы в том, что изменения пользователя, которые приходят на сервер вторыми, нужно преобразовывать через изменения, которые пришли первыми. В первом случае, поскольку удаление в позиции 1 не меняет вставку в позиции 0, второе изменение не меняется.

Во втором случае вставка в позицию 0 влияет на последующее удаление в позиции 1, оно преобразуется в удаление в позиции 2. В итоге после преобразования мы получаем следующую схему.



По такому принципу работают все текстовые (и не только текстовые) редакторы, у которых есть совместное редактирование в онлайне. Впрочем, наш вариант несколько отличается от того, как всё устроено в других онлайн-редакторах.

Главное отличие


Разница в том, где происходит преобразование отправленных изменений. У остальных онлайн-редакторов (например, Google Docs) ответственным за процессы преобразования является сервер. Изменения приходят к нему в нетронутом виде: в нашем случае это ins(«x», 0) от Номера Один и del(1) от Номера Два. Далее сервер преобразует полученные правки и отправляет их пользователям. Таким образом, Номер Один получит del(2), а Номер Два - ins(«x», 0).



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



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

Отменить/вернуть


Сразу признаем, у нас пока нет undo в режиме «быстрого» совместного редактирования. К сожалению, такого undo, какой хотели бы пользователи, нет ни у кого.

Например, undo редакторов Google Docs работает частично. Он, скорее, рассчитан на то, что пользователи будут отменять мелкие оплошности, опечатки. Попытки откатить более серьезные изменения могут привести к непредсказуемым последствиям.

Допустим, один человек добавил таблицу, а другой начал её менять, скажем, двигать границы, вводить текст. Затем первый решил сделать undo добавления таблицы. По сути таблица пропадет со всем, что сделал в ней второй пользователь. Если он, например, перетащил в таблицу часть текста из документа, то она канет в небытие вместе с отмененной таблицей. Кроме того, для такого варианта undo невозможно сделать правильное redo с точки зрения внесенных в документ изменений.

Схема undo/redo в Google Docs не возвращает документ в исходный вид, как этого хотел бы пользователь, напротив — может сделать его таким, каким этот документ никогда не был.

Нам больше импонирует вариант, придуманный компанией Microsoft: пользователь вносит свои правки и может откатывать их сколько угодно, но только до тех пор, пока к редактированию не подключится пользователь номер два и не внесет свои правки. Затем undo будет работать у второго пользователя. Пока не появится третий. Этот вариант кажется нам правильным с точки зрения редактирования, поэтому сейчас мы работаем над реализацией этой схемы в наших редакторах.

Впрочем, мы думаем и над добавлением undo, которое работало бы примерно как у Google. В наших планах оно мирно сосуществует с вариантом Microsoft: пока можно делать корректное undo/redo, мы делаем его, затем пробуем делать undo как в Google Docs.

В разных режимах


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

Например, у Номера Один включен «строгий» режим, а у Номера Два — «быстрый».  Первый блокирует объекты и сохраняет свои изменения сам. Второй ничего не блокирует, а сохранение у него происходит автоматически. Если первый редактирует объект или фрагмент текста, второй ничего не может в них делать. При этом первый не видит, что делает второй — пусть будет сюрприз. После сохранения Номер Один отправит свои изменения и примет изменения Номера Второго.

Если подключается Номер Три с «быстрым» режимом, то они с Номером Вторым спокойно работают в режиме быстрого совместного редактирования. При этом они не видят и не могут править то, что заблокировал тот самый интроверт Номер Один. У последнего, кстати, работают и undo, и redo.

Такая схема работы кажется нам логичной и удобной — она позволяет пользователям выбирать способ взаимодействия с соавторами в зависимости от поставленных задач и настроения. Переключение между режимами возможно в любой момент редактирования.

Попробовать быстрое совместное редактирование в действии можно здесь.

P.S. В новой версии редакторов ONLYOFFICE также появился режим рецензирования с отслеживанием изменений, внесенных в ходе проверки документа. Предложенные правки можно принять или отклонить.

P.P.S. Работа над редакторами не прекращается вообще никогда. Мы всё время думаем, что бы такое добавить и улучшить. Поэтому впереди еще много всего.
 

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


  1. DaylightIsBurning
    28.01.2016 17:44

    А почему не рассматривается вариант trans-user redo? То есть у вас же очередь изменений на сервере линейная, почему не разрешить пользователю А отменять изменения пользователя Б? Желательно, конечно при этом показывать, что произойдет и, если изменения не пересекаются, дать пользователю возможность отменять только те изменения, которые он сам внёс.


    1. xkorolx
      28.01.2016 17:57

      С точки зрения документа предложенный вами вариант (trans-user undo/redo) единственно правильный. Но с точки зрения пользователя так делать нельзя, потому что пока первый пользователь набирает что-то, второй захочет сделать Undo, но будет делаться Undo не тем действиям, каким он планировал, а тем, которые сейчас делает первый пользователь.Делать Undo только для непересекающихся действий тоже сомнительный вариант, потому что сделали мы три действия, например, а откатить можем только первое и третье. Это будет странно выглядеть для пользователя, что два раза Undo сработало, а один раз — нет.


      1. DaylightIsBurning
        28.01.2016 18:12

        Я себе представляю это так: Алиса редактирует абзац 1, Боб «одновременно» редактирует абзац 2. Алиса хочет сделать redo — поскольку у она не вносила изменения, которые пересекаются с Бобом — просто предлагаем Алисе откатить изменения в абзаце 1. Далее Алиса переносит предложение из абзаца 1 в абзац 2 и они с Бобом продолжают работать, внося еще изменения — Алиса в абзац 1, Боб — 2. Далее Боб решает откатить изменения и сначала система отменяет изменения которые он внёс в абзац 2, затем, когда черёд доходит до переноса предложения из абзаца 1 в абзац 2, Боб получает уведомление, что вот, мол, дальше откатить необходимо чужое изменение, при этом Бобу показывают, что случится, он соглашается, Алиса тоже получает апдейт.


        1. xkorolx
          28.01.2016 18:18

          Так можно сделать, но тогда быстрое совместное редактирование превратится в пошаговое, потому что чтобы Бобу добраться до изменения, которое он хочет откатить, нужно чтобы никто в этот момент больше в документе ничего не правил. Такое редактирование «быстрым» уже будет сложно назвать.


          1. DaylightIsBurning
            28.01.2016 19:01

            не в документе в целом, но в той его части, над которой работает Боб — да. Ну и блокировка не нужна, просто undo становится не совсем undo, а скорее "-do". В этом смысле лучше даже не как undo это представлять, а как историю изменений, в которой в любой момент можно отменить любое из них. То есть существует как бы две истории:
            1. История версий документа, которая линейная и в которой понятия «undo» может и не быть, с точки зрения истории документа undo — это лишь противоположные действия добавленные в соотв. порядке, назовём их antidiff. В многопользовательской среде при этом могут параллельно добавляться другие изменения и вклиниваться между «undo».
            2. С точки зрения пользователя существует история его действий (diff) «смешанная» с действиями других пользователей, если они вносили изменения в те блоки, где работал пользователь. Пользователь мог бы иметь возможность откатывать эти действия, при этом в истории версий документа действия только лишь добавляются. Во множестве случаев результат такого «undo» будет аналогичен Ворду.
            Блокировка требуется только в том случае, если кто-то решить откатится на старую версию в дереве номер 1. Такую возможно тоже можно добавить, мне кажется. При этом, конечно, желательно отменённые изменения из дерева 1 сохранять как рид-онли ветки.


  1. Aliance
    29.01.2016 02:08
    +3

    Статье не хватает технических подробностей, без них она выглядит как промо-материал «какие мы молодцы, что сделали то, что хотели наши клиенты».
    Например, какая у вас статистика запросов; сколько у вас серверов, чтобы выдерживать обновления каждые 1/25 сек.; какой стек технологий используется для реализации; etc…


    1. xkorolx
      29.01.2016 12:56

      Вот тут мы рассказывали о наших серверах.


  1. siv237
    29.01.2016 04:05

    OpenSource версии редакторов уже поддерживают этот функционал? Можно обновляться?


    1. xkorolx
      29.01.2016 12:57

      К сожалению, пока нет. Новые онлайн-редакторы доступны в SaaS-версии и Enterprise Edition. Версия в open source выйдет чуть позже. Мы обязательно сообщим)


    1. xkorolx
      29.01.2016 12:59

      В ближайшие 10 дней планируем обновить и OpenSource версию, тогда и сможете обновиться.


  1. Smerig
    29.01.2016 10:58

    меню «Файл» — вкладка «Дополнительные параметры» — «Co-editing mode».

    Либо все английским, либо всё по-русски.


    1. xkorolx
      29.01.2016 11:00

      Спасибо. Поправим.