In this article, we introduce the inner structure of the 1C:Enterprise 8 platform and the technologies used in its development.
Let’s get started. This article provides an overview of some technologies behind the platform and its landscape without going into too much detail regarding the implementation. A detailed implementation story of many technologies would take up a whole article, or even a book!
First of all, let's define basic concepts, i.e. what 1C:Enterprise platform (or "Platform" for brevity) is and what components it includes. It is not so simple, because the term "Platform" may be used to define a business application development tool, as well as runtime or administration tools. Conventionally, the following components can be distinguished:
"Thin" client that can connect to the server via HTTP and its own binary protocol
A client for working with a database hosted on a hard drive or a network share in a two-tier architecture
Application server administration tools
Development environment (Designer)
Runtime for iOS, Android, and Windows Phone (1C mobile platform)
All of the above except for the web client are written with C++. Besides, there's a recently announced Java-based new-generation Designer.
C++03 is used to develop native applications. Microsoft Visual C++ 12 (Windows XP compatible profile) is used to compile applications for Windows, gcc 4.8 — to compile apps for Linux and Android, and clang 5.0 — to compile applications for iOS. A standard STLPort library is used for all common operating systems and compilers. Such an approach reduces risks of errors specific to STL implementation. Currently, we are going to make a transition to the STL implementation provided with CLang, since STLPort stopped its development and is incompatible with the C++11 support mode enabled in gcc.
Server code bases have about 99% in common, client codebases — about 95%. Moreover, even the mobile platform uses the same C++ code as its non-mobile counterpart, even though the degree of unification is slightly lower.
Like most C++ users, we do not claim to use 100% of the language features and libraries. We hardly use Boost or dynamic typecasting as far as language capabilities are concerned. On the other hand, we actively use:
STL (strings, containers and algorithms).
Multiple inheritances, including multiple inheritance of implementation
Smart pointers (our own implementation)
The component model described below is enabled via multiple inheritances of interfaces (fully abstract classes).
To support the modular structure, the functionality is divided into components (dynamic libraries — *.dll for Windows and *.so for Linux). There are over 150 components, some of them are described below:
Contains the platform metadata engine
Objects used by application developers to design accounting modules (charts of accounts and accounting registers)
Execution engine for the built-in script language
Proprietary memory allocator implementation
File base execution engine, a simple file-server ISAM-based database machine that also includes a simple SQL processor
Includes basic classes and functions to implement Windows user interface: window classes, GDI access, etc.
This multi-component structure has the following advantages:
The division improves the quality of design (ensures better code isolation, among other things)
Sets of components ensure flexibility of delivery options. For example, a thin client installation contains wbase, but not backend. At the same time, there is no wbase on the server. Both options contain nuke and bsl.
All the components required for a specific startup option are loaded at program startup. This is required for registering SCOM classes described below, among other things.
SCOM, which is similar to the ATL library, is used for a lower-level breakdown. The following list contains ATL's main features and capabilities for those who are not familiar with the technology.
For specially designed classes SCOM provides the following:
Factory methods to create a class from another component based on its name alone (without disclosing its implementation)
An infrastructure of smart pointers with reference counters; SCOM class lifetime doesn't need to be monitored manually
You can find out whether an object implements a certain interface and automatically cast an object pointer to an interface pointer
Also, you can create a service object, which is always accessible via the get_service method, etc.
For example, you can describe a class for reading JSON (such as JSONStreamReader) in json.dll:
The classes, the instances of which can be created from other components, should be registered in the SCOM-machine:
This macro describes a special static registrar class, the constructor of which is called when a component is loaded into memory.
Then its instance can be created in a different component:
Both the business logic and the interface of 1C:Enterprise are implemented on the basis of the SCOM component model.
For the purpose of supporting the services, SCOM provides a complex additional infrastructure. It is centered around the idea of SCOM process, which serves as a container for running services (i.e. Service Locator) and stores the binding to localizable resources. A SCOM process is bound to an OS thread. This provides the option to get services inside applications as follows:
SCOM_Process* process = core::current_process();
Moreover, you can switch logical (SCOM) processes bound to a stream to make several applications being executed within the stream virtually independent (from the application information space point of view). Our thin client has this structure: a single OS process encompasses two SCOM processes, one bound to a client, and another to the server. This approach ensures that the same code can be used for both a local file base and a "real" client/server system. This costs some extras but it’s well worth the effort.
Speaking of interfaces, we do not use the standard Windows controls, our controls are Windows API-based. An interlayer that works via the wxWidgets library has been created for the Linux version of the system.
The controls library is independent of other 1C:Enterprise components and is used in several other internal utilities.
The look of 1C:Enterprise controls varied over time, with just a single essential change in 2009 (release 8.2 with the new managed form concept). We decided to use the flow layout of controls instead of positioning them by pixels. Furthermore, instead of working directly with domain objects, the controls work with special DTOs (Data Transfer Objects) in the new model.
In addition, a managed forms technology is used to develop the mobile apps interface on the 1C platform. We use the OS native technologies to render controls on mobile devices, while the same code as in the "major" 1C:Enterprise platform is used for interface response and form layout logic.
1С interface in Linux OS
1С interface on a mobile device
1C interface on other platforms
Web client in Chrome browser
Thin client on Windows
Even though we don't use the standard C++ development libraries for Windows (MFC, WinAPI controls, etc.), we don't code all the components on our own. We've already mentioned the wxWidgets library. We also use the following:
The list can be expanded.
In addition, we use significantly modified versions of Google Test and Google Mock to develop unit tests.
We had to adapt the libraries to make them compatible with the SCOM component layout model.
The wide use of the 1С platform turns out to be a great test for the libraries used in it. The diversity of users and scenarios ensures the quick detection of errors even in the least used pieces of code. We fix them and share the fixes with the authors of those libraries. Our cooperation experience varies greatly. For example, cURL and libetpan developers respond to pull requests quickly, but to this day we are unable to submit a patch for OpenSSL.
We've touched upon several major aspects of the 1C:Enterprise platform development. However, this is just a small range of extremely interesting issues.
To see a general description of different platform technologies, see here.