Ciao, Habr!
In questo articolo inizieremo a raccontare come è organizzata internamente e quali tecnologie vengono utilizzate nel suo sviluppo.

Perché consideriamo interessante questo argomento? In primo luogo, perché la piattaforma «1C:Enterprise 8» è un grande (oltre 10 milioni di righe di codice) applicativo in C++ (client, server, ecc.), JavaScript (client web) e, da poco, anche . I grandi progetti sono interessanti almeno per la loro portata, poiché questioni che passano inosservate in una piccola base di codice diventano evidenti in questi progetti. In secondo luogo, «1C:Enterprise» è un prodotto commercializzabile, e ci sono poche articoli su tali sviluppi su Habrahabr. Inoltre, è sempre interessante scoprire come lavorano altre squadre e aziende.
Dunque, iniziamo. In questo articolo forniremo una panoramica di alcune tecnologie utilizzate nella piattaforma, delineando il panorama senza approfondire la realizzazione. Infatti, per molti meccanismi una descrizione dettagliata richiederebbe un articolo a parte, e per alcuni — un intero libro!
Per cominciare, è importante chiarire alcuni aspetti fondamentali: cos'è la piattaforma "1C:Enterprise" e quali componenti la costituiscono. La risposta a questa domanda non è semplice, poiché con il termine "Piattaforma" (per brevità, la chiameremo così) si intendono sia uno strumento di sviluppo di applicazioni aziendali, sia un ambiente di esecuzione e sia strumenti di amministrazione. Si possono distinguere, in modo approssimativo, i seguenti componenti:
- cluster di server
- "client leggero" capace di connettersi al server tramite http e un proprio protocollo binario
- client per operare in architettura a due livelli con il database situato su disco rigido o in una cartella di rete
- web client
- strumenti di amministrazione del server delle applicazioni
- ambiente di sviluppo (noto come Configuratore)
- ambiente di esecuzione per iOS, Android e Windows Phone (piattaforma mobile 1C)
Tutti questi elementi, ad eccezione del web client, sono scritti in C++. Inoltre, è stato recentemente annunciato il , scritto in Java.
Applicazioni native
Per lo sviluppo di applicazioni native utilizziamo C++03. Su Windows viene utilizzato Microsoft Visual C++ 12 (profilo compatibile con Windows XP), mentre su Linux e Android si usa gcc 4.8, e su iOS – clang 5.0. La libreria standard è unica per tutti i sistemi operativi e compilatori – STLPort. Questa soluzione riduce la probabilità di errori specifici dell'implementazione di STL. Attualmente stiamo pianificando il passaggio all'implementazione di STL fornita con CLang, poiché STLPort ha cessato il suo sviluppo ed è incompatibile con la modalità di supporto C++11 attivata in gcc.
La base di codice del server è comune al 99%, quella del client al 95%. Inoltre, anche la piattaforma mobile utilizza lo stesso codice C++ della "grande" piattaforma, sebbene il grado di unificazione sia leggermente inferiore.
Come la maggior parte degli utenti di C++, non pretendiamo di utilizzare il 100% delle funzionalità del linguaggio e delle sue librerie. Ad esempio, non utilizziamo praticamente Boost e, tra le capacità del linguaggio, ci serve solo il casting dinamico dei tipi. Tuttavia, usiamo attivamente:
- STL (in particolare, stringhe, contenitori e algoritmi)
- ereditarietà multipla, inclusa l'ereditarietà multipla di implementazione
- template
- eccezioni
- puntatori intelligenti (implementazione proprietaria)
L'uso dell'ereditarietà multipla delle interfacce (classi completamente astratte) rende possibile un modello a componenti, di cui parleremo più avanti.
Componenti
Per garantire la modularità, tutta la funzionalità è suddivisa in componenti che si presentano come librerie dinamiche (*.dll per Windows, *.so per Linux). Ci sono oltre centocinquanta componenti, diamo una descrizione di alcuni di essi:
backend
Contiene il «motore» dei metadati della piattaforma
accnt
Oggetti che gli sviluppatori applicativi utilizzano per costruire la contabilità (piani dei conti e registri contabili)
bsl
Motore di esecuzione del linguaggio incorporato
nuke
Implementazione proprietaria dell'allocatore di memoria
dbeng8
Motore della base dati file. Macchina di database file-server semplice, basata su ISAM, che include anche un semplice processore SQL
wbase
Contiene classi e funzioni di base per l'implementazione dell'interfaccia utente di Windows — classi delle finestre, accesso a GDI, ecc.
La suddivisione in vari componenti è utile da diversi punti di vista:
- La divisione contribuisce a una migliore progettazione, in particolare a una maggiore isolamento del codice
- Dal set di componenti è possibile assemblare vari modelli di fornitura in modo flessibile:
- Ad esempio, l'installazione di un thin client includerà wbase, ma non includerà il backend.
- E sul server wbase, al contrario, non sarà presente.
- Entrambi i modelli conterranno, ovviamente, nuke e bsl.
Tutti i componenti necessari per questo modello di avvio vengono caricati all'avvio del programma. Questo è, in particolare, necessario per la registrazione delle classi SCOM, di cui si parlerà più avanti.
SCOM
Per la decomposizione a un livello più basso viene utilizzato il sistema SCOM, simile per ideologia alla libreria ATL. Per coloro che non hanno mai lavorato con ATL, elenchiamo brevemente le principali funzionalità e caratteristiche.
Per una classe SCOM appositamente definita:
- Fornisce metodi factory che consentono di creare una classe da un altro componente conoscendo solo il suo nome (senza rivelare l'implementazione).
- Fornisce un'infrastruttura per smart pointer con conteggio dei riferimenti. Non è necessario monitorare manualmente il ciclo di vita della classe SCOM.
- Permette di verificare se un oggetto implementa un'interfaccia specifica e di convertire automaticamente un puntatore all'oggetto in un puntatore all'interfaccia.
- Creare un oggetto-servizio sempre disponibile tramite il metodo get_service, e così via.
Ad esempio, è possibile descrivere nella componente json.dll una classe per la lettura di JSON (ad esempio, JSONStreamReader).
Le classi e le istanze possono essere create da altre componenti che devono essere registrate nella macchina SCOM:
SCOM_CLASS_ENTRY(JSONStreamReader)
Questo macro descriverà una speciale classe registratrice statica, il cui costruttore verrà chiamato al caricamento della componente in memoria.
Dopo ciò, è possibile creare la sua istanza in un'altra componente:
IJSONStreamReaderPtr jsonReader = create_instance<IJSONStreamReader>(SCOM_CLSIDOF(JSONStreamReader));
Per supportare i servizi, SCOM offre un'infrastruttura aggiuntiva, abbastanza complessa. Centrale in essa è il concetto di processo SCOM, che funge da contenitore per i servizi in esecuzione (cioè svolge il ruolo di Service Locator) e contiene anche il legame con le risorse localizzabili. Il processo SCOM è legato al thread del sistema operativo. Grazie a ciò, all'interno dell'applicazione è possibile ottenere i servizi in questo modo:
SCOM_Process* process = core::current_process();
if (process)
return get_service<IMyService>(process);
Inoltre, passando ai processi logici (SCOM) legati al flusso, si possono ottenere fondamentalmente indipendenti dal punto di vista dello spazio informativo delle applicazioni, eseguiti all'interno dello stesso flusso. Questo è il funzionamento del nostro client snello, che lavora con il database di file: all'interno di un unico processo OS ci sono due processi SCOM, uno associato al client e l'altro al server. Questo approccio consente di uniformare la scrittura del codice, che funzionerà sia su un database di file locale che in una vera architettura client-server. Il prezzo per questa uniformità sono le overhead, ma la pratica dimostra che ne vale la pena.
La logica aziendale e la parte interfaccia di 1C: Enterprise sono implementate sulla base di un modello a componenti SCOM.
Interfaccia utente
A proposito di interfacce. Non utilizziamo i controlli standard di Windows, i nostri elementi di controllo sono implementati direttamente sull'API di Windows. Per la versione Linux è stato creato uno strato che lavora attraverso la libreria wxWidgets.
La libreria degli elementi di controllo è indipendente dalle altre parti di "1C:Enterprise" e viene utilizzata anche in altre piccole utility interne.
Nel corso degli anni, l'aspetto dei controlli di 1C:Enterprise è cambiato, ma un cambiamento significativo nei principi si è verificato solo una volta, nel 2009, con il rilascio della versione 8.2 e l'introduzione delle "package forms". Oltre alla modifica dell'aspetto estetico, il principio di layout del modulo è stato radicalmente cambiato: si è abbandonata la posizione pixel-per-pixel degli elementi a favore di un layout a flusso. Inoltre, nel nuovo modello, i controlli non operano più direttamente con gli oggetti di dominio, ma con speciali DTO ().
Questi cambiamenti hanno consentito di creare un client web per "1C:Enterprise" che replica la logica dei controlli in C++ utilizzando JavaScript. Ci sforziamo di mantenere l'equivalenza funzionale tra client thin e web. Quando ciò non è possibile, ad esempio a causa delle limitazioni delle API disponibili in JavaScript (come le capacità di gestione dei file che sono molto limitate), spesso implementiamo la funzionalità necessaria tramite estensioni del browser scritte in C++. Attualmente supportiamo Internet Explorer e Microsoft Edge (Windows), Google Chrome (Windows), Firefox (Windows e Linux) e Safari (MacOS).
Inoltre, la tecnologia delle forme gestite viene utilizzata per creare l'interfaccia delle applicazioni mobili sulla piattaforma 1C. Su dispositivi mobili, il rendering dei controlli è implementato utilizzando tecnologie 'native' per il sistema operativo, ma per la logica di layout delle forme e le reazioni dell'interfaccia si utilizza lo stesso codice della 'grande' piattaforma '1C:Enterprise'.

Interfaccia 1C su OS Linux

Interfaccia 1C su dispositivo mobile
Interfaccia 1C su altre piattaforme 
Interfaccia 1C su OS Windows

Interfaccia 1C - client web
Open source
Sebbene non utilizziamo le librerie standard per sviluppatori C++ su Windows (MFC, controlli da WinAPI), non scriviamo noi stessi tutti i componenti. È già stata menzionata la libreria , e utilizziamo anche:
- per lavorare con HTTP e FTP.
- per la crittografia e la configurazione delle connessioni TLS
- per il parsing XML
- per lavorare con i protocolli di posta (POP3, SMTP, IMAP)
- per il parsing dei messaggi di posta elettronica
- per memorizzare i log delle attività degli utenti
- per l'internazionalizzazione
La lista potrebbe continuare.
Inoltre, utilizziamo versioni fortemente modificate di e nella creazione di unit test.
Le librerie hanno richiesto adattamenti per garantire la compatibilità con il modello SCOM dell'organizzazione dei componenti.
La diffusione di 1C rende la piattaforma un ottimo collaudo per le librerie usate. La varietà di utenti e scenari scova rapidamente errori anche nelle parti di codice meno utilizzate. Noi li correggiamo e cerchiamo di restituirli agli autori delle librerie. L’esperienza di interazione risulta molto varia.
Gli sviluppatori e rispondono rapidamente alle pull request, ma il patch, ad esempio, in non siamo riusciti a restituirlo.
Conclusione
Nell'articolo abbiamo toccato alcuni aspetti fondamentali dello sviluppo della piattaforma '1C: Enterprise'. Nel limitato volume dell'articolo abbiamo trattato solo alcuni aspetti che riteniamo interessanti.
Una descrizione generale dei vari meccanismi della piattaforma può essere consultata .
Quali argomenti sarebbero di suo interesse per i prossimi articoli?
Come è realizzata la piattaforma mobile 1C?
Descrizione della struttura interna del client web?
O, forse, le interessa il processo di selezione delle funzionalità per le nuove versioni, sviluppo e test?
Scrivi nei commenti!
Fonte: habr.com
