Platform "1C: Enterprise" - what's under the hood?

Hey Habr!
In this article, we will begin a story about how it works inside 1C:Enterprise 8 platform and what technologies are used in its development.

Platform "1C: Enterprise" - what's under the hood?

Why do we think it's interesting? Firstly, because the 1C:Enterprise 8 platform is a large (more than 10 million lines of code) application written in C++ (client, server, etc.), JavaScript (web client), and, more recently, And Java. Large projects are interesting, if only because of their scale, because issues that are invisible in a small code base, in such projects, rise to their full height. Secondly, 1C:Enterprise is a replicated, β€œboxed” product, and there are very few articles about such developments on HabrΓ©. And it's always interesting to find out how they live in other teams and firms.

So let's get started. In this article, we will give an overview of some of the technologies that are used in the platform, outline the landscape, without diving deep into the implementation. Indeed, for many mechanisms, a detailed story will draw on a separate article, and for some - on a whole book!
To begin with, it is worth deciding on the basic things - what is the 1C:Enterprise platform and what components it consists of. The answer to this question is not so simple, because the term "Platform" (for brevity, we will call it that way) is understood as a tool for developing business applications, and an execution environment, and administration tools. Conditionally, the following components can be distinguished:

  • server cluster
  • "thin" client capable of connecting to the server via http and its own binary protocol
  • client for working in a two-tier architecture with a database located on a hard disk or network folder
  • web client
  • application server administration tools
  • development environment (known as Configurator)
  • execution environment for iOS, Android and Windows Phone (mobile platform 1C)

All of these parts, with the exception of the web client, are written in C++. In addition, there is the recently announced New generation configurator, written in Java.

Native apps

C++03 is used to develop native applications. Under Windows, Microsoft Visual C++ 12 (a profile compatible with Windows XP) is used as a compiler, while under Linux and Android, gcc 4.8 is used, and for iOS, clang 5.0. The standard library used is the same for all operating systems and compilers - STLPort. This solution reduces the possibility of errors specific to the implementation of the STL. We are currently planning to switch to the STL implementation provided with CLang, as STLPort has been deprecated and is not compatible with gcc's enabled C++11 support mode.
The code base of the server is 99% common, the client - 95% percent. Moreover, even the mobile platform uses the same C++ code as the "large" one, although the percentage of unification is somewhat lower there.
Like most C++ users, we do not claim to use 100% of the language and its libraries. So, we practically do not use Boost, and from the possibilities of the language - dynamic type casting. In doing so, we actively use:

  • STL (specifically strings, containers and algorithms)
  • multiple inheritance, incl. multiple implementation inheritance
  • Patterns
  • exceptions
  • smart pointers (native implementation)

Through the use of multiple inheritance of interfaces (completely abstract classes), the component model becomes possible, which will be discussed below.

Components

To ensure modularity, all functionality is divided into components that are dynamic libraries (*.dll under Windows, *.so - under Linux). There are more than one and a half hundred components in total, we will give descriptions of some of them:

backend
Contains the "engine" of the platform metadata

accnt
Objects that application developers use to build accounting (charts of accounts and accounting registers)

bsl
Embedded Language Execution Engine

nuke
Own implementation of the memory allocator

dbeng8
File base engine. A simple ISAM-based file server database engine that also includes a simple SQL processor

wbase
Contains base classes and functions for implementing the Windows user interfaceβ€”window classes, GDI access, and so on.

Splitting into many components is useful in several ways:

  • Separation promotes better design, in particular better code isolation
  • From a set of components, you can flexibly assemble different delivery options:
    • For example, a thin client installation will contain wbase but no backend
    • and on the wbase server, on the contrary, it will not
    • both will of course contain nuke and bsl

All the components required for this launch option are loaded when the program starts. This, in particular, is necessary for registering SCOM classes, which will be discussed below.

SCOM

For decomposition at a lower level, the SCOM system is used - a library similar in ideology to ATL. For those who have not worked with ATL, briefly list the main features and features.
For a custom-styled SCOM class:

  • Provides factory methods that allow you to create a class from another component knowing only its name (without revealing the implementation)
  • Provides a reference-counted smart pointer infrastructure. The lifetime of an SCOM class does not need to be monitored manually
  • Allows you to find out if an object implements a specific interface and automatically cast the pointer to the object to the pointer to the interface
  • Create a service object that is always available via the get_service method, etc.

For example, you can define a class for reading JSON (for example, JSONStreamReader) in the json.dll component.
Classes, instances can be created from other components, you need to register in the SCOM machine:

SCOM_CLASS_ENTRY(JSONStreamReader)

This macro will describe a special static registrar class whose constructor will be called when the component is loaded into memory.
After that, you can create an instance of it in another component:

IJSONStreamReaderPtr jsonReader = create_instance<IJSONStreamReader>(SCOM_CLSIDOF(JSONStreamReader));

To support services, SCOM offers an additional, rather complex infrastructure. Central to it is the concept of an SCOM process, which serves as a container for running services (that is, acts as a Service Locator), and also contains a binding to localizable resources. An SCOM process is bound to an OS thread. Thanks to this, inside the application, you can receive services like this:

SCOM_Process* process = core::current_process();
if (process)
         return get_service<IMyService>(process);

Moreover, by switching logical (SCOM) processes attached to a thread, you can get applications that are practically independent from the point of view of the information space and run within the same thread. This is how our thin client works with the file base - inside one OS process there are two SCOM processes, one is connected to the client, and the second to the server. This approach allows you to unify writing code that will work both on a local file base and in a β€œreal” client-server version. The price for such uniformity is overhead, but practice shows that they are worth it.

Based on the SCOM component model, both the business logic and the interface part of 1C: Enterprise are implemented.

User interface

By the way, about interfaces. We do not use standard Windows controls, our controls are implemented directly on the Windows API. For the Linux version, a layer has been made that works through the wxWidgets library.
The library of controls does not depend on other parts of 1C:Enterprise and is used by us in several other small internal utilities.

Over the years of development of 1C:Enterprise, the appearance of controls has changed, but a serious change in principles occurred only once, in 2009, with the release of version 8.2 and the advent of "managed forms". In addition to changing the appearance, the principle of form layout has fundamentally changed - there has been a rejection of pixel-by-pixel positioning of elements in favor of the flow-layout of elements. In addition, in the new model, controls do not work directly with domain objects, but with special DTOs (Data Transfer Objects).
These changes made it possible to create a 1C:Enterprise web client that repeats the C++ control logic in JavaScript. We try to maintain functional equivalence between thin and web clients. When this is not possible, for example, due to limitations available from the JavaScript API (for example, the ability to work with files is very limited), we often implement the desired functionality using browser extensions written in C ++. We currently support Internet Explorer and Microsoft Edge (Windows), Google Chrome (Windows), Firefox (Windows and Linux) and Safari (MacOS).

In addition, the technology of managed forms is used to create the interface of mobile applications on the 1C platform. On mobile devices, the drawing of controls is implemented using technologies native to the operating system, but the same code is used for the form layout logic and interface response as in the "large" 1C:Enterprise platform.

Platform "1C: Enterprise" - what's under the hood?
1C interface on Linux OS

Platform "1C: Enterprise" - what's under the hood?
1C interface on a mobile device

1C interface on other platforms Platform "1C: Enterprise" - what's under the hood?
1C interface on Windows OS

Platform "1C: Enterprise" - what's under the hood?
Interface 1C - web client

Open source

Although we do not use standard libraries for C++ developers under Windows (MFC, controls from WinAPI), we do not write all the components ourselves. The library has already been mentioned. wxWidgetsand we also use:

  • cURL to work with HTTP and FTP.
  • OpenSSL for working with cryptography and establishing TLS connections
  • libxml2 and libxslt for XML parsing
  • libetpan to work with mail protocols (POP3, SMTP, IMAP)
  • camouflage to parse email messages
  • sqlite for storing user logs
  • ICU for internationalization

The list can still be continued.
In addition, we use a heavily modified version Google Test ΠΈ Google Mock when developing unit tests.
The libraries required adaptation to be compatible with the SCOM component organization model.
The prevalence of 1C makes the platform an excellent strength test for the libraries used in it. A variety of users and scripts quickly find errors in even the most rarely used parts of the code. We fix them at home and try to give them back to the authors of the libraries. The interaction experience is very different.
Developers cURL ΠΈ libetpan quickly respond to a pull-request, but the patch, for example, in OpenSSL we never got to give it back.

Conclusion

In the article, we touched on several main aspects of the development of the 1C: Enterprise platform. In the limited volume of the article, we touched on only some interesting, in our opinion, aspects.
A general description of the various mechanisms of the platform can be viewed here.
What topics would be of interest to you in future articles?

How is the 1C mobile platform implemented?
Description of the internal device of the web client?
Or maybe you are interested in the process of feature selection for new releases, development and testing?

Write in the comments!

Source: habr.com

Add a comment