1С corporate blog
C++
System Analysis and Design
Website development
October 2015 27

Платформа «1С: Предприятие» — что под капотом?

Привет, Хабр!
В этой статье мы начнем рассказ о том, как устроена внутри платформа «1С:Предприятие 8» и какие технологии используются при ее разработке.

image

Почему мы считаем, что это интересно? Во-первых, потому что платформа «1С:Предприятие 8» — это большое (более 10 миллионов строк кода) приложение на C++ (клиент, сервер и т.д.), JavaScript (веб-клиент), и, с недавних пор еще и Java. Большие проекты бывают интересны хотя бы в силу масштаба, ведь вопросы, незаметные в маленькой кодовой базе, в таких проектах встают в полный рост. Во-вторых, «1С:Предприятие» — это тиражируемый, «коробочный» продукт, а статей про такие разработки на Хабре совсем немного. А еще всегда интересно узнать, как там живут в других командах и фирмах.

Итак, приступим. В этой статье мы дадим обзор некоторых технологий, которые применяются в платформе, обрисуем ландшафт, без глубокого погружения в реализацию. Ведь для многих механизмов подробный рассказ потянет на отдельную статью, а для некоторых — на целую книгу!
Для начала стоит определиться с базовыми вещами — что такое платформа «1С:Предприятие» и из каких компонентов она состоит. Ответ на этот вопрос не так прост, ведь под термином «Платформа» (для краткости будем называть ее именно так) понимают и средство разработки бизнес-приложений, и среду исполнения, и средства администрирования. Условно можно выделить следующие составляющие:
  • кластер серверов
  • «тонкий» клиент, способный подключаться к серверу по http и собственному бинарному протоколу
  • клиент для работы в двухзвенной архитектуре с БД, размещенной на жестком диске или сетевой папке
  • веб-клиент
  • средства администрирования сервера приложений
  • среда разработки (известная как Конфигуратор)
  • среда исполнения для iOS, Android и Windows Phone (мобильная платформа 1С)

Все эти части, за исключением веб-клиента, написаны на C++. Кроме того, существует недавно анонсированный Конфигуратор нового поколения, написанный на Java.

Нативные приложения


Для разработки нативных приложений используется C++03. Под Windows в качестве компилятора используется Microsoft Visual C++ 12 (профиль совместимый с Windows XP), а под Linux и Android — gcc 4.8, для iOS — clang 5.0. Стандартная библиотека используется единая для всех ОС и компиляторов — STLPort. Это решение позволяет снизить вероятность ошибок, специфичных для реализации STL. Сейчас мы планируем переход на реализацию STL, поставляемую с CLang, так как STLPort прекратил свое развитие и несовместим с включенным режимом поддержки C++11 в gcc.
Кодовая база сервера при этом общая на 99%, клиента — процентов на 95%. Более того, даже мобильная платформа использует тот же C++ код, что и «большая», хотя там процент унификации несколько ниже.
Как большинство пользователей С++ мы не претендуем на использование 100% возможностей языка и его библиотек. Так, у нас практически не используется Boost, а из возможностей языка — динамическое приведение типов. При этом мы активно применяем:
  • STL (в частности, строки, контейнеры и алгоритмы)
  • множественное наследование, в т.ч. множественное наследование реализации
  • шаблоны
  • исключения
  • умные указатели (собственная реализация)

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

Компоненты


Для обеспечения модульности весь функционал разделен на компоненты, представляющие из себя динамические библиотеки (*.dll под Windows, *.so — под Linux). Всего компонентов более полутора сотен, приведем описания некоторых из них:
backend Содержит «движок» метаданных платформы
accnt Объекты, которые прикладные разработчики используют для построения бухгалтерского учета (планы счетов и регистры бухгалтерии)
bsl Движок исполнения встроенного языка
nuke Собственная реализация аллокатора памяти
dbeng8 Движок файловой базы. Простая файл-серверная машина баз данных, основанная на ISAM, включающая также простой SQL-процессор
wbase Содержит базовые классы и функции для реализации пользовательского интерфейса Windows — оконные классы, доступ к GDI и т. п.

Разделение на множество компонент полезно с нескольких точек зрения:
  • Разделение способствует лучшему проектированию, в частности лучшей изоляции кода
  • Из набора компонентов можно гибко собирать разные варианты поставки:
    • Например, инсталляция тонкого клиента будет содержать wbase, но не будет backend
    • а на сервере wbase, наоборот, не будет
    • оба варианта будут, конечно, содержать nuke и bsl

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

SCOM


Для декомпозиции на более низком уровне используется система SCOM — схожая по идеологии с ATL библиотека. Для тех, кто с ATL не работал, кратко перечисли основные возможности и особенности.
Для специально оформленного класса SCOM:
  • Предоставляет фабричные методы, позволяющие создать класс из другой компоненты зная только его название (без раскрытия реализации)
  • Предоставляет инфраструктуру умных указателей с подсчетом ссылок. За временем жизни SCOM-класса не нужно следить вручную
  • Позволяет узнать реализует ли объект конкретный интерфейс и автоматически привести указатель на объект к указателю на интерфейс
  • Создать объект-сервис, всегда доступный через метод get_service и т.д.

Например, можно описать в компоненте json.dll класс для чтения JSON (например, JSONStreamReader).
Классы, экземпляры можно создавать из других компонент нужно зарегистрировать в SCOM-машине:
SCOM_CLASS_ENTRY(JSONStreamReader)

Этот макрос опишет специальный статический класс-регистратор, конструктор которого будет вызван при загрузке компоненты в память.
После это можно создать его экземпляр в другой компоненте:
IJSONStreamReaderPtr jsonReader = create_instance<IJSONStreamReader>(SCOM_CLSIDOF(JSONStreamReader));

Для поддержки сервисов SCOM предлагает дополнительную, достаточно сложную инфраструктуру. Центральным в ней является понятие SCOM-процесса, который служит контейнером для запущенных сервисов (т.е. выполняет роль Service Locator), а также содержит привязку к локализуемым ресурсами. SCOM процесс привязывается к потоку ОС. Благодаря этому внутри приложения можно вот так получать сервисы:
SCOM_Process* process = core::current_process();
if (process)
         return get_service<IMyService>(process);

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

На основе компонентной модели SCOM реализована и бизнес-логика и интерфейсная часть 1С: Предприятия.

Пользовательский интерфейс


Кстати, об интерфейсах. Мы не используем стандартные контролы Windows, наши элементы управления реализованы напрямую на Windows API. Для Linux-версии сделана прослойка, работающая через библиотеку wxWidgets.
Библиотека элементов управления не зависит от других частей «1С:Предприятия» и используется нами еще в нескольких небольших внутренних утилитах.

За годы развития 1С:Предприятие внешний вид контролов менялся, но серьезное изменение принципов произошло только один раз, в 2009 году, с выходом версии 8.2 и появлением «управляемых форм». Помимо изменения внешнего вида, фундаментально изменился принцип компоновки формы — произошел отказ от попиксельного позиционирования элементов в пользу flow-компоновки элементов. Кроме того, в новой модели элементы управления работают не напрямую с доменными объектами, а со специальными DTO (Data Transfer Objects).
Эти изменения позволили создать веб-клиент «1С:Предприятия», повторяющий С++ логику контролов на JavaScript. Мы стараемся поддерживать функциональную эквивалентность между тонким и веб клиентами. В том случае, когда это невозможно, например, из-за ограничений доступных из JavaScript API (например, возможности работы с файлами очень ограничены), мы часто реализуем нужную функциональность при помощи расширений браузеров, написанных на C++. На данный момент мы поддерживаем Internet Explorer и Microsoft Edge (Windows), Google Chrome(Windows), Firefox (Windows и Linux) и Safari (MacOS).

Кроме того, технология управляемых форм используется для создания интерфейса мобильных приложений на платформе 1С. На мобильных устройствах отрисовка контролов реализована с использованием «родных» для операционной системы технологий, но уже для логики компоновки формы и реакции интерфейса используется тот же код, что и в «большой» платформе «1С:Предприятие».

image
Интерфейс 1С на ОС Linux

image
Интерфейс 1С на мобильном устройстве

Интерфейс 1С на других платформах
image
Интерфейс 1С на ОС Windows

image
Интерфейс 1С — веб-клиент


Open source


Хотя мы и не используем стандартные для С++ разработчика библиотеки под Windows (MFC, контролы из WinAPI), не все компоненты мы пишем сами. Уже упоминалась библиотека wxWidgets, а еще мы используем:
  • cURL для работы с HTTP и FTP.
  • OpenSSL для работы с криптографией и установки TLS соединений
  • libxml2 и libxslt для разбора XML
  • libetpan для работы с почтовыми протоколами (POP3, SMTP, IMAP)
  • mimetic для разбора сообщений электронной почты
  • sqllite для хранения журналов работы пользователей
  • ICU для интернационализации

Список еще можно продолжать.
Кроме того, мы используем сильно модифицированную версии Google Test и Google Mock при разработке юнит-тестов.
Библиотеки потребовали адаптации для совместимости со SCOM-моделью организации компонент.
Распространенность 1С делает платформу отличной проверкой на прочность для используемых в ней библиотек. Разнообразие пользователей и сценариев быстро обнаруживает ошибки даже в самых редкоиспользуемых участах кода. Мы исправляем их у себя и стараемся отдавать обратно авторам библиотек. Опыт взаимодействия оказывается очень разный.
Разработчики cURL и libetpan быстро откликаются на pull-request, но патч, например, в OpenSSL нам так и не получилось отдать.

Заключение


В статье мы коснулись нескольких основных аспектов разработки платформы «1С: Предприятие». В ограниченном объеме статьи мы затронули лишь некоторые интересные, на наш взгляд, аспекты.
Общее описание различных механизмов платформы можно посмотреть тут.
Какие темы были бы интересны Вам в следующих статьях?

Как реализована мобильная платформа 1С?
Описание внутреннего устройства веб-клиента?
Или, может быть, Вам интересен процесс выбора фич для новых релизов, разработки и тестирования?

Пишите в комментариях!
+17
58.4k 179
Comments 160