image

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

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

Мы решили очень хорошо разделять слои редактора и сразу же использовать клиент-серверную архитектуру.

Если многие другие офисные пакеты исторически шли по пути добавления в какой-то момент совместимости с онлайном ещё через один редактор, то у нас он один. И онлайн-редактирование, и редактирование в десктопном приложении будут выполняться абсолютно одинаково. Но в десктопном приложении уже будет содержаться свой собственный встроенный сервер. Это, кстати, автоматически означает, что мы не можем открывать запароленные документы на веб-версии: это означало бы передачу пароля в открытом виде на сервер, что небезопасно. Сейчас решаем это за счёт возможности работать с ЭЦП внутри локальных компонентов браузеров.

Причём необходимо сразу продумать, как российские компании это будут применять в 2020–30-х годах, и получить ещё кучу преимуществ интеграции. Следствие — то же управление правами доступа: на текущий момент мы единственный пакет, который «из коробки» умеет устанавливать в документе права на редактирование, только чтение, только комментирование, запрещать печать и копирование, встроить водяной знак хоть для какой-то защиты от фотографирования и так далее.

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

Наш документ-сервер состоит из двух основных частей: клиентской и серверной, как я описал выше.

image

Рендер на принтер выглядит точно так же, как рендер на экран, но с другими настройками.

То есть каждый слой редактора заизолирован и представляет собой архитектурно отдельную единицу. Условно шрифтовой движок подключается ко второму модулю. Связь между интерфейсом пользователя и API-редактора делает Message Manager, который отвечает за взаимодействие. Например, если пользователь ввёл слово «сабака», то оно через сообщение ушло на сервер. Там сервер его проверил на орфографию и принял решение подчеркнуть в интерфейсе. Ушло сообщение на GUI пользователя, что нужно его подчеркнуть. Через эти же сообщения идут запросы прав на документ. Эти же сообщения помогают синхронизировать совместное редактирование: всё, что делает второй-третий пользователи, отправляется первому в сообщениях с сервера (для этого используется ещё один изолированный модуль — Collaboration). При выходе из редактора отправляется команда «Собрать документ», и он собирается, а затем ложится в модуль хранения. Чаще всего это Document Storage на сервере, который сразу же отдаёт ссылку на этот самый документ.

Простым изменением GUI можно получить мобильный редактор, онлайновый редактор или десктопный редактор. Такие уровни абстракции дают нам возможность добавлять новые фичи очень просто и легко сразу везде. Например, мы уже сделали сводные таблицы. Мы пишем один раз их логику и пару раз их GUI: для мобильной версии нужно сделать элементы настроек удобнее для пальцев, крупнее. Дальше, если мы вдруг найдём баг, то он будет надёжно лежать в своём слое: или на уровне принятия команды, или на уровне презентации, например. И править его будет очень легко.

Документ-сервер


Документ-сервер представляет собой набор сервисов и набор устройств. Сюда приходят команды на подготовку поля работы для редактора. Например, если пользователь хочет совместить DOX, DOCX, RTF и что-то на базе OOXML, то всё это встанет в очередь на преобразования, которая будет дёргать сервис конвертации. Документ-сервер содержит временное хранилище: когда пользователь, например, в совместном редактировании начинает создавать новый параграф, в это хранилище падает новый объект с ним, и пользователь уже фокусирует сессию на этом объекте. Сессии хранятся ещё в одном отдельном хранилище сессий — там всё оптимизировано так, чтобы блокировки применялись и отпускались очень быстро.

В конце сессий документ идёт на сборку. Это даёт ещё одну интересную особенность: при редактировании DOCX мы не конвертируем весь файл при сохранении, а только добавляем-убираем-редактируем те отдельные XML-объекты, которые трогал пользователь. То есть если он поправил там пару абзацев, то в DOCX изменятся только они. Учитывая количество разных вариантов интерпретаций этого открытого формата и тот факт, что у MS — своё видение на то, как оно должно работать, это наиболее щадящий и совместимый режим. То, что не было изменено, будет ровно таким, как в исходном документе. Обычный подход других офисных пакетов — сконвертировать всё в свой формат, а потом сконвертировать из своего формата в новый DOCX и перезаписать всё.

Важно это вот почему: например, в DOCX рамка вокруг картинки задаётся как флаг true/false. Если она есть, то она есть. А в OOXML рамка состоит из четырёх элементов, и внизу картинки её может не быть, например. Теперь, если вы хотите положить в DOCX картинку, у которой нет правой границы, а нижняя красная, то сконвертировать впрямую это не выйдет: нет взаимооднозначного соответствия между всеми свойствами.

image

image

Что это всё дало


  1. Мы не заморачиваемся на поддержку, совместимость и апдейты предыдущих версий, поскольку нам достаточно просто обновить серверную часть. Да, мы дистрибутируем пакеты под самые разные OС, включая Win и CentOS, а также RedHat-системы. Но организация будущего для крупной компании — это общее корпоративное хранилище документов (виртуализованное, кластеризованное и катастрофоустойчивое) и сервисы-обработчики вокруг него, связанные по API с GUI конечных пользователей. То есть сейчас в десктопные версии мы встраиваем этот сервер и хранилища, что выглядит некоторым оверхедом, но это всё равно в разы удобнее и современнее, чем держать несколько версий редактора и всей обвязки для разных сред.
  2. У нас проще поддержка: мы можем добавлять фичу или править баг в одном изолированном месте, а не искать 9-12 вхождений в разных версиях для разных платформ.
  3. Компоненты можно запускать распределённо, что точно нужно и для геокластеров крупных компаний, и для катастрофоустойчивости хранилищ (речь идёт про документ-сервера). Одна из особенностей работы на российском рынке для госкомпаний — готовность к тому, что один из ЦОДов внезапно нагреется до 30–40 тысяч градусов и уйдёт в офлайн вместе с населённым пунктом. Мы к этому готовы. В пакет, кстати, сразу входят и балансировщик нагрузки, и RabbitMQ, и всё остальное необходимое.
  4. Данные уже хранятся в Облаке (или корпоративном хранилище on premise). Их можно защищать паролем.
  5. Есть две типовые реализации DOCX: стандартная на базе DOC от MS и остальная, то есть чаще всего — конвертация в OOXML, который лежит в основе структуры документов большинства доступных русских офисных пакетов, включая наш. Но, как я писал выше, мы не ломаем DOCX ни на рендере, ни на сохранении.
  6. Наша архитектура не предполагает различий между редакторами на десктопе и вебе. Казалось бы, если у вас есть десктопное приложение, то достаточно запустить его на сервер и сделать тонкий клиент. Ну вот MS пробовали когда-то, и результат им не понравился настолько, что они сделали вообще отдельный редактор для веб-версии. И дело не только в самом редакторе, но и в управлении сессиями, правильном обмене данными с сервером, отзывчивости документов, скорости обновления, взаимоблокировках и так далее.
  7. При этом наш документ отрисовывается не в браузере нативно, а в браузерном компоненте, то есть не зависит от рендера браузера. В Google Docs, например, документ будет по-разному выглядеть в разных браузерах, и первая же разница будет в разном рендере шрифтов.
  8. Правильная архитектура разбиения на объекты означает, что мы можем спокойно отдавать в коллаборационный модуль большие документы. Когда открывается какой-нибудь отчёт на 100 страниц, один пользователь редактирует в начале, второй — на 50-й странице, а третий — ближе к концу: это конец Штирлица. Потому что при неправильном обмене и неправильном рендере у человека на 50-й странице всё будет скакать, а у человека на сотой — не только скакать, но и тормозить из-за постоянного пересчёта документа. У нас тоже есть некоторые сложности на файлы больше 1 000 страниц – тот же MS Word для таких ситуаций оптимизирован лучше.
  9. Нам не надо писать отдельный язык (типа Visal Basic) для поддержки макросов и плагинов. JS, дёргающего API, достаточно. Макрос от плагина в этой архитектуре отличается только тем, что макрос хранится прямо внутри документа. Объектная модель документа очень сильно облегчает работу и с макросами в том числе.

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

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

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


  1. dvserg
    03.08.2021 11:14

    Нам не надо писать отдельный язык (типа Visal Basic) для поддержки макросов и плагинов. JS, дёргающего API, достаточно. Макрос от плагина в этой архитектуре отличается только тем, что макрос хранится прямо внутри документа. Объектная модель документа очень сильно облегчает работу и с макросами в том числе.

    А что у Вас с безопасностью плагинов и макросов? Какие потенциальные уязвимости Вы видите и как с ними работаете?


    1. sschadnyh_r7 Автор
      03.08.2021 14:22

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

      По требованиям ИБ не могу рассказать больше про организационные и технические средства.


  1. fransua
    03.08.2021 11:32

    При этом наш документ отрисовывается не в браузере нативно, а в браузерном компоненте, то есть не зависит от рендера браузера.

    Под браузерным компонентом Вы имеете ввиду canvas? Но под ним ведь тоже скрывается библиотека вроде libvips, отвечающая за рендеринг шрифтов, и она может быть разная в разных браузерах. Кстати, получилось побороть проблему с font-variant в канвасе хромиумов?


  1. zanac
    03.08.2021 12:35

    Жаль не для простых смертных. Хотел потыкать в частном порядке, но увы, не даёт скачать.


    1. ASGAlex
      03.08.2021 15:35
      +1

      Судя по скриншотам с сайта, там просто клон (форк?) OnlyOffice и Thunderbird. Так что с тем же успехом можете поставить их и потыкать...


    1. SlavaHU
      03.08.2021 19:03

      Куда-то Вы не туда тыкали. Все скачивается и инсталлируется.

      Вопрос у меня такой - к ТС - масшатабирование интерфейса возможно? А то у меня на большом экране и высоком разрешении размер букв миллиметра полтора, я такой с лупой не прочту...


      1. sschadnyh_r7 Автор
        03.08.2021 19:11

        Да, есть возможность масштабирования 150% и 200%, в следующей версии добавится 125 и 175%.


        1. SlavaHU
          03.08.2021 19:34

          Сорри, проглядел.

          Совместимость с МС Офисом, прямо скажем, так себе. Открыл относительно несложный Эксель файл, без макросов, только с формулами. Никакие ДропЛисты с проверкой данных не работают (хотя ссылки на именованые диапазоны показываются правильно), название таблиц не видно (возможно, проглядел), НИЧЕГО в файле не менял (просто покликал по всяким формулам и т.п.), сохранил, попробовал открыть в Экселе - файл поврежден, причем ВСЕ странички, куда я даже не заходил... Мдя...


          1. kompilainenn2
            03.08.2021 20:02

            Ради интереса, откройте этот же файл в LibreOffice 7.1.5, какой результат?


            1. SlavaHU
              03.08.2021 21:15

              Специально скачал последний LibreOffice, открыл.

              Не идеально, ну существенно лучше. ДропЛисты выборки из списка выдавали ошибку (#NAME), но после того, как я зашел в Validation и нажал OK (ничего не поменяв) - заработали. Название таблиц есть, но просто как Named Range. Не знаю, никогда не работал в LibreOffice, есть ли у них таблицы в понятии MS Office? Но самое главное, что сохранение ничего не порушило, ни просто, ни после изменения пары формул. Эксель при открытии измененного файла ни на что не ругается и все работает, как работало.


              1. kompilainenn2
                03.08.2021 22:04

                Если речь про "Форматировать, как таблицу", то такого в ЛО нет. Спасибо за эксперимент


                1. SlavaHU
                  03.08.2021 22:16

                  Ну, я больше про внутренний об'ект Таблица (ListObject), у которого есть свойства (типа DataBodyRange, Headers, Totals, с присущими им(а не Worksheet!) Rows, Columns, и пр.) и методами.


                  1. kompilainenn2
                    04.08.2021 13:26

                    Да, это оно и есть. И такого в ЛО нет, RFE ждёт своего героя давно уже


          1. sschadnyh_r7 Автор
            03.08.2021 23:08

            Спасибо за обратную связь! Можете прислать файл нам в тех поддержку для анализа по адресу support@r7-office.ru?


            1. SlavaHU
              03.08.2021 23:45

              Ммм... Попробую, но не обещаю. Файл по сути простой, но информация в нем непубличная. Если получится сделать похожую пустышку, и ошибки сохранятся, - пришлю.