Eine der angenehmen Besonderheiten der Technologie 1C:Unternehmen ist, dass die Anwendungslösung, die mit der Technologie der gesteuerten Formate entwickelt wurde, sowohl im dünnen (ausführbaren) Client unter Windows, Linux, MacOS X als auch als Web-Client unter 5 Browsern – Chrome, Internet Explorer, Firefox, Safari, Edge – gestartet werden kann, und das alles ohne Änderung des Quellcodes der Anwendung. Darüber hinaus funktioniert die Anwendung im dünnen Client und im Browser optisch nahezu identisch.
Finden Sie 10 Unterschiede (unter dem Schnitt 2 Bilder):
Fenster des dünnen Clients unter Linux:

Das gleiche Fenster im Web-Client (im Browser Chrome):

Warum haben wir den Web-Client entwickelt? Etwas pathetisch gesagt, stellte uns die Zeit diese Aufgabe. Schon lange ist die Arbeit über das Internet eine notwendige Voraussetzung für Geschäftsanwendungen geworden. Zunächst haben wir die Möglichkeit geschaffen, über das Internet mit unserem dünnen Client zu arbeiten (einige unserer Konkurrenten haben sich übrigens darauf beschränkt; andere hingegen haben den dünnen Client ganz aufgegeben und sich ausschließlich auf die Implementierung des Web-Clients konzentriert). Wir hingegen haben uns entschieden, unseren Nutzern die Wahl dieses Clients zu ermöglichen, der am besten zu ihnen passt.

Die Hinzufügung der Möglichkeit, über das Internet mit dem dünnen Client zu arbeiten, war ein großes Projekt mit einer vollständigen Änderung der Architektur der Client-Server-Interaktion. Die Erstellung des Web-Clients ist ein ganz neues Projekt, das von Grund auf neu begann.
Aufgabenstellung
Also, die Anforderungen an das Projekt: der Web-Client muss das Gleiche tun wie der dünne Client, nämlich:
- Die Benutzeroberfläche anzeigen
- Client-Code ausführen, der in der 1C-Sprache geschrieben ist
Die Benutzeroberfläche in 1C wird im visuellen Editor beschrieben, jedoch deklarativ, ohne pixelgenaue Anordnung der Elemente; es werden etwa drei Dutzend Typen von Benutzeroberflächenelementen verwendet – Schaltflächen, Eingabefelder (Text, Zahlen, Datum/Zeit), Listen, Tabellen, Diagramme usw.
Der Client-Code in der 1C-Sprache kann Serveraufrufe, Arbeiten mit lokalen Ressourcen (Dateien usw.), Drucken und vieles mehr enthalten.
Sowohl der dünne Client (bei der Nutzung über das Web) als auch der Web-Client verwenden dasselbe Set von Webdiensten zur Kommunikation mit dem 1C-Anwendungsserver. Die Implementierung bei den Clients ist natürlich unterschiedlich – der dünne Client ist in C++ geschrieben, der Web-Client in JavaScript.
Ein wenig Geschichte
Das Projekt zur Erstellung eines Web-Clients begann im Jahr 2006, wobei im Durchschnitt ein Team von 5 Personen daran beteiligt war. In bestimmten Phasen des Projekts wurden Entwickler zur Umsetzung spezifischer Funktionen (Tabellendokumente, Diagramme usw.) hinzugezogen; in der Regel waren dies dieselben Entwickler, die diese Funktionalitäten im Thin Client implementiert hatten. Das bedeutet, dass die Entwickler die Komponenten, die sie zuvor in C++ erstellt hatten, erneut in JavaScript schrieben.
Von Anfang an lehnten wir die Idee einer automatischen (auch nur teilweisen) Konversion des C++-Codes des Thin Clients in den JavaScript-Web-Client aufgrund der erheblichen konzeptionellen Unterschiede zwischen diesen beiden Sprachen ab; der Web-Client wurde von Grund auf neu in JavaScript entwickelt.
In den ersten Iterationen des Projekts konvertierte der Web-Client den Client-Code in der integrierten 1C-Sprache direkt in JavaScript. Der Thin Client funktioniert anders – der Code in der integrierten 1C-Sprache wird in Bytecode kompiliert, der dann auf dem Client interpretiert wird. Später begann auch der Web-Client, dies zu tun – erstens führte dies zu einer Leistungssteigerung, zweitens ermöglichte es die Vereinheitlichung der Architektur des Thin Clients und des Web-Clients.
Die erste Version der Plattform 1C:Unternehmen mit Unterstützung für den Web-Client wurde 2009 veröffentlicht. Zu diesem Zeitpunkt unterstützte der Web-Client 2 Browser – Internet Explorer und Firefox. In den ursprünglichen Plänen war die Unterstützung von Opera vorgesehen, aber aufgrund unüberwindbarer Probleme zum damaligen Zeitpunkt mit den Schließhandlern der Anwendung in Opera (es war nicht möglich, mit 100%-iger Sicherheit nachzuverfolgen, dass die Anwendung geschlossen wird, und in diesem Moment den Trennungsprozess vom 1C-Anwendungsserver durchzuführen) mussten wir von diesen Plänen Abstand nehmen.
Projektstruktur
In der Plattform 1C:Unternehmen gibt es insgesamt 4 Projekte, die in JavaScript geschrieben sind:
- WebTools – allgemeine Bibliotheken, die von den anderen Projekten verwendet werden (hierzu zählen wir auch ).
- Steuerelement (wurde sowohl im JavaScript als auch im Thin Client und im Web-Client implementiert)
- Steuerelement (wurde sowohl im JavaScript als auch im Thin Client und im Web-Client implementiert)
- Web-Client
Die Struktur jedes Projekts ähnelt der Struktur von Java-Projekten (oder .NET-Projekten – je nach Vorliebe); wir haben Namensräume, und jeder Namensraum befindet sich in einem separaten Ordner. Innerhalb des Ordners befinden sich die Dateien und Klassen des Namensraums. Im Projekt des Web-Clients gibt es etwa 1000 Dateien.
Strukturell wird der Web-Client grob in die folgenden Teilsysteme unterteilt:
- Verwaltete Schnittstelle der Client-Anwendung
- Allgemeine Benutzeroberfläche der Anwendung (Systemmenüs, Panels)
- Benutzeroberfläche der verwalteten Formulare, die unter anderem etwa 30 Steuerelemente umfasst (Schaltflächen, verschiedene Arten von Eingabefeldern – Text-, Zahlen-, Datum/Zeit und mehr, Tabellen, Listen, Diagramme usw.)
- Objektmodell, das Entwicklern auf der Client-Seite zur Verfügung steht (insgesamt mehr als 400 Typen: Objektmodell der verwalteten Benutzeroberfläche, Datenlayout-Einstellungen, bedingte Formatierungen usw.)
- Interpreter der integrierten 1C-Sprache
- Browsererweiterungen (werden für Funktionen verwendet, die in JavaScript nicht unterstützt werden)
- Arbeit mit Kryptographie
- Arbeit mit Dateien
- Technologie externer Komponenten, die eine Nutzung sowohl im Thin- als auch im Web-Client ermöglicht
Besonderheiten der Entwicklung
Die Implementierung all dessen, was oben beschrieben wurde, in JavaScript – ist keine einfache Aufgabe. Möglicherweise ist der 1C-Web-Client eine der größten Client-Seit-Anwendungen, die in JavaScript geschrieben wurden – etwa 450.000 Zeilen. Wir verwenden aktiv den objektorientierten Ansatz im Code des Web-Clients, der die Arbeit mit einem so großen Projekt vereinfacht.
Um die Größe des Client-Codes zu minimieren, haben wir zunächst unseren eigenen Obfuskator verwendet, und ab Version 8.3.6 der Plattform (Oktober 2014) haben wir begonnen, . Der Effekt der Verwendung in Zahlen – die Größe des Frameworks des Web-Clients nach der Obfuskation:
- Eigener Obfuskator – 1556 kB
- Google Closure Compiler – 1073 kB
Die Verwendung des Google Closure Compilers hat uns geholfen, die Leistung des Web-Clients um 30 % im Vergleich zu unserem eigenen Obfuskator zu steigern. Darüber hinaus wurde der Speicherbedarf des Programms um 15-25 % (je nach Browser) reduziert.
Google Closure Compiler funktioniert sehr gut mit objektorientiertem Code, daher ist seine Effizienz gerade für den Web-Client maximal hoch. Der Closure Compiler macht für uns mehrere gute Dinge:
- Statische Typprüfung während der Projektkompilierung (erreicht durch die Verwendung von JSDoc-Anmerkungen im Code). Am Ende ergibt sich eine statische Typisierung, die in der Nähe des Niveaus von C++ liegt. Dadurch können wir einen erheblichen Prozentsatz der Fehler während der Kompilation des Projekts aufdecken.
- Reduzierung der Codegröße durch Obfuskation
- Eine Reihe von Optimierungen des ausführbaren Codes, zum Beispiel:
- Inline-Ersatzfunktionen. Der Funktionsaufruf in JavaScript ist eine relativ teure Operation, und Inline-Ersatz für oft verwendete kleine Methoden beschleunigt die Ausführung des Codes erheblich.
- Berechnung von Konstanten zur Compile-Zeit. Wenn der Ausdruck von einer Konstante abhängt, wird dessen tatsächlicher Wert eingesetzt.
Als Entwicklungsumgebung für den Web-Client verwenden wir WebStorm.
Für die Analyse des Codes verwenden wir , in die wir statische Code-Analysatoren integrieren. Mit Hilfe der Analysatoren überwachen wir die Verschlechterung der Qualität des Quellcodes in JavaScript und versuchen, dies zu vermeiden.

Welche Aufgaben haben wir gelöst/ lösen wir
Im Laufe der Projektdurchführung sind wir auf eine Reihe interessanter Aufgaben gestoßen, die wir lösen mussten.
Datenkommunikation mit dem Server und zwischen Fenstern
Es gibt Situationen, in denen die Obfuskierung des Quellcodes die Funktionalität des Systems beeinträchtigen kann. Der Code, der extern zum ausführbaren Code des Web-Clients ist, kann aufgrund der Obfuskierung Funktions- und Parameterbezeichnungen haben, die sich von denjenigen unterscheiden, die unser ausführbarer Code erwartet. Externer Code für uns ist:
- Der Code, der vom Server in Form von Datenstrukturen kommt
- Der Code eines anderen Anwendungsfensters
Um Obfuskierung bei der Interaktion mit dem Server zu vermeiden, verwenden wir das Tag @expose:
/**
* @constructor
* @extends {Base.SrvObject}
*/
Srv.Core.GenericException = function ()
{
/**
* @type {string}
* @expose
*/
this.descr;
/**
* @type {Srv.Core.GenericException}
* @expose
*/
this.inner;
/**
* @type {string}
* @expose
*/
this.clsid;
/**
* @type {boolean}
* @expose
*/
this.encoded;
}Und um Obfuskierung bei der Interaktion mit anderen Fenstern zu vermeiden, nutzen wir sogenannte exportierte Schnittstellen (Schnittstellen, bei denen alle Methoden exportiert sind).
/**
* Экспортируемый интерфейс контрола DropDownWindow
*
* @interface
* @struct
*/
WebUI.IDropDownWindowExp = function(){}
/**
* Перемещает выделение на 1 вперед или назад
*
* @param {boolean} isForward
* @param {boolean} checkOnly
* @return {boolean}
* @expose
*/
WebUI.IDropDownWindowExp.prototype.moveMarker = function (isForward, checkOnly){}
/**
* Перемещает выделение в начало или конец
*
* @param {boolean} isFirst
* @param {boolean} checkOnly
* @return {boolean}
* @expose
*/
WebUI.IDropDownWindowExp.prototype.moveMarkerTo = function (isFirst, checkOnly){}
/**
* @return {boolean}
* @expose
*/
WebUI.IDropDownWindowExp.prototype.selectValue = function (){}Wir haben das Virtual DOM verwendet, bevor es allgemein bekannt wurde)
Wie alle Entwickler, die mit komplexen Web-UIs umgehen, haben wir schnell erkannt, dass der DOM schlecht für die Arbeit mit dynamischen Benutzeroberflächen geeignet ist. Fast sofort wurde ein Analogon zum Virtual DOM zur Optimierung der Arbeit mit der UI implementiert. Während der Verarbeitung von Ereignissen werden alle DOM-Änderungen im Speicher festgehalten und erst nach Abschluss aller Operationen werden die gesammelten Änderungen auf den DOM-Baum angewendet.
Optimierung der Funktionsweise des Web-Clients
Damit unser Web-Client schneller arbeitet, versuchen wir, die Standardfunktionen des Browsers (CSS usw.) bestmöglich zu nutzen. So wird die Befehlsleiste des Formulars (die praktisch in jedem Formular der Anwendung zu finden ist) ausschließlich mit Mitteln des Browsers und dynamischem Layout auf der Basis von CSS gerendert.

Tests
Für funktionale Tests und Leistungstests verwenden wir ein hauseigenes Tool (geschrieben in Java und C++), sowie eine Testreihe, die auf .
Unser Tool ist vielseitig – es erlaubt das Testen nahezu aller Desktop-Anwendungen und eignet sich sowohl für die Überprüfung von Thin Clients als auch von Web-Clients. Das Tool zeichnet die Aktionen des Benutzers, der die Applikation „1C“ gestartet hat, in eine Skriptdatei auf. Gleichzeitig werden Bilder des Bildschirminhalts – der Referenzen – aufgezeichnet. Bei der Kontrolle neuer Versionen des Web-Clients werden die Skripte ohne Benutzerinteraktion abgespielt. Bei einer Abweichung des Screenshots von der Referenz an irgendeinem Punkt wird der Test als fehlgeschlagen betrachtet, woraufhin ein Qualitätsspezialist eine Untersuchung durchführt – ob es sich um einen Fehler oder eine geplante Änderung des Systemverhaltens handelt. Bei geplanten Veränderungen werden die Referenzen automatisch durch neue ersetzt.
Das Tool misst auch die Leistungsdaten von Anwendungen mit einer Genauigkeit von bis zu 25 Millisekunden. In bestimmten Fällen wiederholen wir Teile des Skripts (zum Beispiel geben wir die Bestellung mehrmals ein), um die Verschlechterung der Ausführungszeit im Laufe der Zeit zu analysieren. Alle Messwerte werden in einem Protokoll festgehalten und analysiert.

Unser Testtool und die getestete Anwendung
Unser Tool und Selenium ergänzen sich; zum Beispiel, wenn eine Schaltfläche auf einem Bildschirm ihre Position geändert hat – Selenium kann das möglicherweise nicht verfolgen, aber unser Tool wird es bemerken, da es pixelgenaue Vergleiche des Screenshots mit der Referenz anstellt. Zudem ist das Tool in der Lage, Probleme bei der Verarbeitung von Tastatureingaben oder Mausbewegungen zu erkennen, da es genau diese eingibt.
Tests in beiden Tools (unserem und Selenium) führen typischen Arbeitsszenarien aus unseren Anwendungslösungen durch. Tests werden automatisch nach dem täglichen Build der Plattform „1C:Enterprise“ gestartet. Bei einer Verlangsamung der Skriptausführungen (im Vergleich zum vorherigen Build) führen wir eine Untersuchung durch und beheben die Ursache der Verlangsamung. Unser Kriterium ist einfach – der neue Build muss nicht langsamer arbeiten als der vorherige.
Zur Untersuchung von Vorfällen der Verlangsamung verwenden die Entwickler verschiedene Tools; hauptsächlich wird des Unternehmens . Es werden Protokolle der Ausführung der problematischen Operationen in der alten und der neuen Version aufgezeichnet, die dann analysiert werden. Dabei kann die Ausführungszeit einzelner Operationen (in Millisekunden) nicht der entscheidende Faktor sein – im Browser werden regelmäßig Hintergrundprozesse wie die Speicherbereinigung gestartet, die die Ausführungszeit der Funktionen überlagern und das Bild verzerren können. Relevantere Parameter in diesem Fall sind die Anzahl der ausgeführten JavaScript-Anweisungen, die Anzahl atomarer DOM-Operationen usw. Wenn die Anzahl der Anweisungen/Operationen im selben Szenario in der neuen Version gestiegen ist, bedeutet das fast immer einen Rückgang der Leistung, der behoben werden muss.
Eine weitere Ursache für die Leistungsabfälle kann sein, dass der Google Closure Compiler aus irgendeinem Grund keine Inline-Substitution der Funktion durchführen konnte (zum Beispiel, weil die Funktion rekursiv oder virtuell ist). In diesem Fall versuchen wir, die Situation zu beheben, indem wir den Quellcode umschreiben.
Browsererweiterungen
Wenn die Anwendung bestimmte Funktionalitäten benötigt, die nicht in JavaScript vorhanden sind, nutzen wir Browsererweiterungen:
- zum Arbeiten mit Dateien
- zum Arbeiten mit Kryptografie
- arbeiten mit
Unsere Erweiterungen bestehen aus zwei Teilen. Der erste Teil ist das, was als Browsererweiterung bezeichnet wird (in der Regel in JavaScript für Chrome und Firefox geschriebene Erweiterungen), die mit dem zweiten Teil — der binären Erweiterung, die die benötigte Funktionalität implementiert — interagiert. Es sei erwähnt, dass wir 3 Versionen der binären Erweiterungen für Windows, Linux und MacOS schreiben. Die binäre Erweiterung wird zusammen mit der Plattform 1C:Enterprise bereitgestellt und befindet sich auf dem Server der 1C-Anwendung. Bei der ersten Aufruf von einem Web-Client wird sie auf den Client-Computer geladen und im Browser installiert.
Bei der Arbeit in Safari verwenden unsere Erweiterungen NPAPI, im Internet Explorer kommt die ActiveX-Technologie zum Einsatz. unterstützt derzeit keine Erweiterungen, weshalb der Web-Client eingeschränkt funktioniert.
Weiterentwicklung
Eine der Aufgaben für das Entwicklungsteam des Web-Clients besteht darin, die Funktionalität weiterzuentwickeln. Die Funktionalität des Web-Clients sollte identisch mit der des dicken Clients sein, und alle neuen Funktionen werden sowohl im dicken als auch im Web-Client gleichzeitig implementiert.
Weitere Aufgaben sind die Entwicklung der Architektur, Refactoring, Leistungs- und Zuverlässigkeitssteigerung. Ein Beispiel für einen Bereich ist der Übergang zu einem asynchronen Arbeitsmodell. Ein Teil der Funktionalität des Web-Clients basiert derzeit auf einem synchronen Modell der Interaktion mit dem Server. Das asynchrone Modell wird in Browsern (und nicht nur in Browsern) zunehmend relevanter, was uns zwingt, den Web-Client durch den Austausch synchroner Aufrufe gegen asynchrone (und entsprechendes Refactoring des Codes) zu modifizieren. Der schrittweise Übergang zu einem asynchronen Modell wird durch die Notwendigkeit erklärt, die veröffentlichten Lösungen zu unterstützen und sie allmählich anzupassen.
Quelle: habr.com
