Platforma „1C: Enterprise” – co kryje się pod maską?

Hej Habra!
W tym artykule zaczniemy opowieść o tym, jak to działa w środku platforma „1C:Enterprise 8” i jakie technologie są wykorzystywane przy jego tworzeniu.

Platforma „1C: Enterprise” – co kryje się pod maską?

Dlaczego uważamy, że to interesujące? Po pierwsze dlatego, że platforma 1C:Enterprise 8 to duża (ponad 10 milionów linii kodu) aplikacja w języku C++ (klient, serwer itp.), JavaScript (klient sieciowy), a ostatnio także And Java. Duże projekty mogą być ciekawe chociażby ze względu na swoją skalę, bo w takich projektach problemy niewidoczne w małej bazie kodu pojawiają się z pełną mocą. Po drugie, „1C:Enterprise” to produkt możliwy do replikacji, „pudełkowy” i na Habré znajduje się bardzo niewiele artykułów na temat takich rozwiązań. Zawsze ciekawie jest też dowiedzieć się, jak wygląda życie w innych zespołach i firmach.

Więc zacznijmy. W tym artykule dokonamy przeglądu niektórych technologii zastosowanych na platformie i zarysujemy jej krajobraz, bez zagłębiania się w implementację. Rzeczywiście, w przypadku wielu mechanizmów szczegółowa historia wymagałaby osobnego artykułu, a dla niektórych całej książki!
Na początek warto zdecydować się na podstawowe rzeczy - czym jest platforma 1C:Enterprise i z jakich komponentów się składa. Odpowiedź na to pytanie nie jest taka prosta, ponieważ termin „Platforma” (w skrócie, tak to nazwiemy) odnosi się do środka do tworzenia aplikacji biznesowych, środowiska uruchomieniowego i narzędzi administracyjnych. Z grubsza można wyróżnić następujące elementy:

  • klaster serwerów
  • „cienki” klient, który może łączyć się z serwerem poprzez protokół http i własny protokół binarny
  • klient do pracy w architekturze dwuwarstwowej z bazą danych zlokalizowaną na dysku twardym lub w folderze sieciowym
  • klient sieciowy
  • narzędzia administracyjne serwera aplikacji
  • środowisko programistyczne (znane jako Konfigurator)
  • środowisko wykonawcze dla systemów iOS, Android i Windows Phone (platforma mobilna 1C)

Wszystkie te części, z wyjątkiem klienta WWW, są napisane w C++. Dodatkowo istnieje niedawno ogłoszony Konfigurator nowej generacji, napisany w Javie.

Aplikacje natywne

C++ 03 służy do tworzenia aplikacji natywnych. W przypadku systemu Windows jako kompilator używany jest Microsoft Visual C++ 12 (profil zgodny z systemem Windows XP), a dla systemów Linux i Android - gcc 4.8, dla iOS - clang 5.0. Stosowana standardowa biblioteka jest taka sama dla wszystkich systemów operacyjnych i kompilatorów - STLPort. To rozwiązanie zmniejsza prawdopodobieństwo wystąpienia błędów specyficznych dla implementacji STL. Obecnie planujemy migrację do implementacji STL dostarczanej z CLang, ponieważ STLPort został wycofany i jest niekompatybilny z trybem włączonym C++ 11 gcc.
Baza kodu serwera jest w 99% wspólna, klienta - w 95%. Co więcej, nawet platforma mobilna korzysta z tego samego kodu C++ co „duża”, chociaż procent unifikacji jest tam nieco niższy.
Podobnie jak większość użytkowników C++, nie rościmy sobie pretensji do wykorzystania 100% możliwości języka i jego bibliotek. Praktycznie więc nie używamy Boosta, a jedną z funkcji języka jest dynamiczne rzutowanie typów. Jednocześnie aktywnie wykorzystujemy:

  • STL (w szczególności ciągi znaków, kontenery i algorytmy)
  • dziedziczenie wielokrotne, m.in. wielokrotne dziedziczenie implementacyjne
  • Patterns
  • исключения
  • inteligentne wskaźniki (implementacja niestandardowa)

Dzięki zastosowaniu wielokrotnego dziedziczenia interfejsów (całkowicie abstrakcyjnych klas) możliwy staje się model komponentowy, co zostanie omówione poniżej.

Components

Aby zapewnić modułowość, cała funkcjonalność została podzielona na komponenty będące bibliotekami dynamicznymi (*.dll dla Windows, *.so dla Linux). W sumie komponentów jest ponad sto pięćdziesiąt; oto opisy niektórych z nich:

Backend
Zawiera silnik metadanych platformy

akcent
Obiekty wykorzystywane przez twórców aplikacji do budowy zapisów księgowych (plany kont i rejestry księgowe)

bsl
Wbudowany silnik wykonawczy języka

nuke
Niestandardowa implementacja alokatora pamięci

dbeng8
Silnik bazy danych plików. Prosty silnik bazy danych serwera plików oparty na ISAM, który zawiera również prosty procesor SQL

wbaza
Zawiera podstawowe klasy i funkcje do implementacji interfejsu użytkownika Windows - klasy okien, dostęp GDI itp.

Podział na wiele komponentów jest przydatny z kilku punktów widzenia:

  • Separacja sprzyja lepszemu projektowaniu, w szczególności lepszej izolacji kodu
  • Z zestawu komponentów można elastycznie montować różne opcje dostawy:
    • Na przykład instalacja cienkiego klienta będzie zawierać wbase, ale nie będzie miała zaplecza
    • ale na serwerze wbase wręcz przeciwnie, tak nie będzie
    • obie opcje będą oczywiście zawierać nuke i bsl

Wszystkie komponenty wymagane dla tej opcji uruchamiania są ładowane podczas uruchamiania programu. Jest to w szczególności konieczne do rejestracji klas SCOM, co zostanie omówione poniżej.

SCOM

Do dekompozycji na niższym poziomie wykorzystywany jest system SCOM, biblioteka podobna ideologią do ATL. Dla tych, którzy nie pracowali z ATL, pokrótce wymieniamy główne możliwości i funkcje.
Dla specjalnie zaprojektowanej klasy SCOM:

  • Udostępnia metody fabryczne, które pozwalają utworzyć klasę z innego komponentu, znając jedynie jego nazwę (bez ujawniania implementacji)
  • Zapewnia infrastrukturę inteligentnych wskaźników zliczających referencje. Czas życia klasy SCOM nie musi być monitorowany ręcznie
  • Pozwala dowiedzieć się, czy obiekt implementuje określony interfejs i automatycznie przekonwertować wskaźnik na obiekt na wskaźnik na interfejs
  • Utwórz obiekt usługi, który będzie zawsze dostępny poprzez metodę get_service itp.

Można na przykład opisać klasę do odczytu formatu JSON (na przykład JSONStreamReader) w komponencie json.dll.
Klasy i instancje można tworzyć z innych komponentów, należy je zarejestrować na maszynie SCOM:

SCOM_CLASS_ENTRY(JSONStreamReader)

To makro opisuje specjalną statyczną klasę rejestratora, której konstruktor zostanie wywołany po załadowaniu komponentu do pamięci.
Następnie możesz utworzyć jego instancję w innym komponencie:

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

Do wsparcia usług SCOM oferuje dodatkową, dość złożoną infrastrukturę. Centralne miejsce zajmuje koncepcja procesu SCOM, który służy jako kontener na uruchamianie usług (tj. pełni rolę lokalizatora usług), a także zawiera powiązanie ze zlokalizowanymi zasobami. Proces SCOM jest powiązany z wątkiem systemu operacyjnego. Dzięki temu wewnątrz aplikacji możesz otrzymać takie usługi jak:

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

Co więcej, przełączając procesy logiczne (SCOM) powiązane z wątkiem, można uzyskać aplikacje praktycznie niezależne z punktu widzenia przestrzeni informacyjnej, działające w ramach tego samego wątku. Tak działa nasz cienki klient z plikową bazą danych - w jednym procesie systemu operacyjnego znajdują się dwa procesy SCOM, jeden powiązany z klientem, drugi z serwerem. Takie podejście pozwala nam ujednolicić pisanie kodu, który będzie działał zarówno na lokalnej bazie plików, jak i w „prawdziwej” wersji klient-serwer. Cena za taką jednolitość jest wysoka, ale praktyka pokazuje, że warto.

W oparciu o model komponentów SCOM zaimplementowano zarówno logikę biznesową, jak i część interfejsu 1C: Enterprise.

Interfejs użytkownika

Nawiasem mówiąc, o interfejsach. Nie używamy standardowych kontrolek systemu Windows; nasze kontrole są zaimplementowane bezpośrednio w interfejsie API systemu Windows. Dla wersji Linux została stworzona warstwa działająca poprzez bibliotekę wxWidgets.
Biblioteka kontrolek nie zależy od innych części 1C:Enterprise i jest przez nas używana w kilku innych małych narzędziach wewnętrznych.

Przez lata rozwoju 1C:Enterprise wygląd kontroli się zmienił, ale poważna zmiana zasad nastąpiła tylko raz, w 2009 roku, wraz z wydaniem wersji 8.2 i pojawieniem się „formularzy zarządzanych”. Oprócz zmiany wyglądu zasadniczo zmieniła się zasada układu formularzy - odrzucono pozycjonowanie elementów piksel po pikselu na rzecz układu płynnego. Dodatkowo w nowym modelu kontrole nie działają bezpośrednio z obiektami domenowymi, lecz ze specjalnymi DTO (Obiekty transferu danych).
Zmiany te umożliwiły stworzenie klienta WWW 1C:Enterprise, który replikuje logikę C++ kontroli JavaScript. Staramy się zachować funkcjonalną równoważność pomiędzy klientami cienkimi i internetowymi. W przypadkach, gdy nie jest to możliwe, na przykład ze względu na ograniczenia dostępnego API JavaScript (np. możliwość pracy z plikami jest bardzo ograniczona), często implementujemy niezbędną funkcjonalność za pomocą rozszerzeń przeglądarki napisanych w C++. Obecnie obsługujemy przeglądarki Internet Explorer i Microsoft Edge (Windows), Google Chrome (Windows), Firefox (Windows i Linux) oraz Safari (MacOS).

Ponadto technologia zarządzanych formularzy służy do tworzenia interfejsu dla aplikacji mobilnych na platformie 1C. Na urządzeniach mobilnych renderowanie kontroli odbywa się przy użyciu technologii natywnych dla systemu operacyjnego, ale w przypadku logiki układu formularza i odpowiedzi interfejsu używany jest ten sam kod, co w „dużej” platformie 1C:Enterprise.

Platforma „1C: Enterprise” – co kryje się pod maską?
Interfejs 1C w systemie operacyjnym Linux

Platforma „1C: Enterprise” – co kryje się pod maską?
Interfejs 1C na urządzeniu mobilnym

Interfejs 1C na innych platformach Platforma „1C: Enterprise” – co kryje się pod maską?
Interfejs 1C w systemie operacyjnym Windows

Platforma „1C: Enterprise” – co kryje się pod maską?
Interfejs 1C - klient sieciowy

Otwarte źródło

Choć nie korzystamy ze standardowych bibliotek dla programistów C++ pod Windows (MFC, kontrolki z WinAPI), to nie piszemy wszystkich komponentów sami. O bibliotece już wspomniano wxWidgety, a także używamy:

  • cURL do pracy z HTTP i FTP.
  • OpenSSL do pracy z kryptografią i ustanawiania połączeń TLS
  • libxml2 i libxslt do analizowania XML
  • libetpan do pracy z protokołami pocztowymi (POP3, SMTP, IMAP)
  • mimetyczny do analizowania wiadomości e-mail
  • sqllite do przechowywania logów użytkowników
  • ICU dla internacjonalizacji

I tak dalej.
Dodatkowo używamy wersji mocno zmodyfikowanej Test Google и Próba Google'a podczas opracowywania testów jednostkowych.
Biblioteki wymagały adaptacji, aby były kompatybilne z modelem organizacji komponentów SCOM.
Powszechność 1C sprawia, że ​​platforma jest doskonałym testem wytrzymałości dla używanych w niej bibliotek. Różnorodność użytkowników i scenariuszy szybko ujawnia błędy nawet w najrzadziej używanych obszarach kodu. Sami je poprawiamy i staramy się zwracać autorom biblioteki. Doświadczenie interakcji okazuje się zupełnie inne.
Deweloperzy cURL и libetpan szybko odpowiadaj na pull-requesty, ale łatka np OpenSSL Nigdy nie udało nam się tego oddać.

wniosek

W artykule poruszyliśmy kilka głównych aspektów rozwoju platformy 1C: Enterprise. W ograniczonym zakresie artykułu poruszyliśmy jedynie niektóre, naszym zdaniem, interesujące aspekty.
Można znaleźć ogólny opis różnych mechanizmów platformy tutaj.
Jakie tematy byłyby dla Ciebie interesujące w przyszłych artykułach?

W jaki sposób wdrażana jest platforma mobilna 1C?
Opis wewnętrznej struktury klienta WWW?
A może interesuje Cię proces doboru funkcji do nowych wydań, rozwijania i testowania?

Napisz w komentarzach!

Źródło: www.habr.com

Dodaj komentarz