Over de 1C webclient

Een van de prettige kenmerken van de 1C:Enterprise-technologie is dat een applicatieoplossing die is ontwikkeld met behulp van de technologie van beheerde formulieren, zowel kan worden uitgevoerd als een dunne (uitvoerende) client op Windows, Linux, MacOS X, als als een webclient in 5 browsers – Chrome, Internet Explorer, Firefox, Safari, Edge, en dit alles – zonder de broncode van de applicatie te wijzigen. Sterker nog, visueel functioneert en ziet de applicatie in de dunne client en in de browser er praktisch identiek uit.
Vind de 10 verschillen (onder de kat 2 afbeeldingen):

Het venster van de dunne client op Linux:

Over de 1C webclient

Hetzelfde venster in de webclient (in de browser Chrome):

Over de 1C webclient

Waarom hebben we een webclient gemaakt? Wat wat grandioos klinkt, is dat de tijd ons deze uitdaging heeft gesteld. Al geruime tijd is werken via het internet een vereiste geworden voor business applicaties. Eerst hebben we de mogelijkheid toegevoegd om via het internet te werken met onze dunne client (enkele van onze concurrenten zijn hier bijvoorbeeld bij gebleven; andere, daarentegen, hebben de dunne client opgegeven en hebben zich beperkt tot de implementatie van de webclient). Wij hebben echter besloten onze gebruikers de keuze te geven over welke clientvariant het beste bij hen past.

Over de 1C webclient

Het toevoegen van de mogelijkheid om via het internet te werken met de dunne client was een groot project met een volledige wijziging van de architectuur van de client-serverinteractie. De creatie van de webclient is zelfs een geheel nieuw project dat vanuit het niets is begonnen.

Taakstelling

Dus, de vereisten voor het project: de webclient moet hetzelfde doen als de dunne client, namelijk:

  1. De gebruikersinterface weergeven
  2. Clientcode uitvoeren, geschreven in de 1C-taal

De gebruikersinterface in 1C wordt beschreven in een visuele editor, maar declaratief, zonder pixel-perfect positionering van elementen; er worden ongeveer dertig verschillende typen interface-elementen gebruikt – knoppen, invoervelden (tekst, cijfers, datum/tijd), lijsten, tabellen, grafieken, enz.

Clientcode in de 1C-taal kan serveraanroepen, werken met lokale resources (bestanden, enz.), afdrukken en nog veel meer bevatten.

Zowel de dunne client (bij gebruik via het web) als de webclient maken gebruik van dezelfde set webservices voor communicatie met de 1C-applicatieserver. De implementatie bij de clients is natuurlijk verschillend – de dunne client is geschreven in C++, de webclient – in JavaScript.

Een beetje geschiedenis

Het project voor de ontwikkeling van een webclient is in 2006 gestart, met gemiddeld een team van 5 personen. Gedurende bepaalde fases van het project werden ontwikkelaars aangetrokken voor de implementatie van specifieke functionaliteiten (zoals spreadsheets, diagrammen, enz.); doorgaans waren dit dezelfde ontwikkelaars die deze functionaliteit ook in de thin client hadden gemaakt. Dat wil zeggen, de ontwikkelaars herschreven de componenten die ze eerder in C++ hadden gemaakt opnieuw in JavaScript.

Vanaf het begin hebben we het idee van enige automatische (zelfs gedeeltelijke) conversie van C++-code van de thin client naar de JavaScript-webclient verworpen, vanwege de sterke conceptuele verschillen tussen deze twee talen; de webclient werd vanaf het begin in JavaScript geschreven.

In de vroege iteraties van het project converteerde de webclient de clientcode in de ingebedde taal 1C direct naar JavaScript. De thin client doet dit anders — de code in de ingebedde taal 1C wordt gecompileerd naar bytecode, en deze bytecode wordt vervolgens op de client geïnterpreteerd. Later begon ook de webclient dit te doen — ten eerste zorgde dit voor prestatieverbeteringen, en ten tweede maakte het mogelijk de architectuur van de thin client en de webclient te uniformiseren.

De eerste versie van het 1C:Enterprise-platform met ondersteuning voor de webclient werd in 2009 uitgebracht. De webclient ondersteunde op dat moment 2 browsers – Internet Explorer en Firefox. In de oorspronkelijke plannen was er ondersteuning voor Opera, maar door onoverkomelijke problemen met de afhandelingsmechanismen voor het sluiten van de applicatie in Opera (het was niet mogelijk om met 100% zekerheid te traceren wanneer de applicatie werd gesloten, en op dat moment de ontkoppelprocedure van de 1C-applicatieserver uit te voeren) moesten deze plannen worden afgeblazen.

Projectstructuur

Er zijn in totaal 4 projecten op het 1C:Enterprise-platform geschreven in JavaScript:

  1. WebTools – algemene bibliotheken die door de andere projecten worden gebruikt (hierbij voegen we ook Google Closure Library).
  2. Besturings element GeformatteerdDocument (geïmplementeerd in zowel de thin client als de webclient)
  3. Besturings element Scheduler (geïmplementeerd in zowel de thin client als de webclient)
  4. Webclient

De structuur van elk project lijkt op de structuur van Java-projecten (of .NET-projecten – wat je ook het dichtst bij de hand hebt); we hebben namespaces, en elke namespace ligt in een aparte map. Binnen de map bevinden zich de bestanden en klassen van de namespace. Het webclient-project bevat ongeveer 1000 bestanden.

Structueel wordt de webclient grofweg verdeeld in de volgende subsysteem:

  • Beheerde interface van de clientapplicatie
    • Algemene gebruikersinterface van de applicatie (systeemmenu's, panels)
    • Interface van beheerde formulieren, met inbegrip van ongeveer 30 besturingselementen (knoppen, verschillende soorten invoervelden - tekst, cijfers, datum/tijd, enz., tabellen, lijsten, grafieken, enz.)

  • Objectmodel, beschikbaar voor ontwikkelaars aan de clientzijde (meer dan 400 typen: objectmodel van de beheerde interface, gegevenslay-outinstellingen, voorwaardelijke opmaak, enz.)
  • Interpreter voor de ingebouwde 1C-taal
  • Browserextensies (gebruikt voor functionaliteit die niet door JavaScript wordt ondersteund)
    • Werken met cryptografie
    • Werken met bestanden
    • Technologie van externe componenten, waarmee ze zowel in de dunne als de webclient gebruikt kunnen worden

Kenmerken van ontwikkeling

De implementatie van alles hierboven beschreven in JavaScript is niet eenvoudig. Mogelijk is de 1C webclient een van de grootste client-side applicaties die in JavaScript zijn geschreven - ongeveer 450.000 regels. We maken actief gebruik van een objectgeoriënteerde aanpak in de code van de webclient, waardoor het werken met zo'n groot project wordt vergemakkelijkt.

Om de grootte van de clientcode te minimaliseren, hebben we oorspronkelijk onze eigen obfuscator gebruikt, en vanaf versie 8.3.6 van het platform (oktober 2014) zijn we gaan werken met Google Closure Compiler. Het effect van het gebruik in cijfers - de grootte van het framework van de webclient na obfuscatie:

  • Eigen obfuscator - 1556 kB
  • Google Closure Compiler - 1073 kB

Het gebruik van Google Closure Compiler heeft ons geholpen de prestaties van de webclient met 30% te verhogen ten opzichte van onze eigen obfuscator. Bovendien is het geheugenverbruik van de applicatie met 15-25% (afhankelijk van de browser) verminderd.

Google Closure Compiler werkt zeer goed met objectgeoriënteerde code, waardoor de effectiviteit ervan voor de webclient maximaal is. Closure Compiler doet enkele goede dingen voor ons:

  • Statische typecontrole tijdens de bouwfase van het project (doorgesteld door het dekken van de code met JSDoc-annotaties). Dit resulteert in statische typificatie, die zeer dicht bij de typen in C++ komt. Dit helpt een aanzienlijk percentage van de fouten te vangen tijdens de compilatiefase van het project.
  • Vermindering van de codegrootte door obfuscatie
  • Een aantal optimalisaties van de uitgevoerde code, zoals:
    • inline-functiesubstitutie. Het aanroepen van een functie in JavaScript is een behoorlijk dure operatie, en inline-substitutie van vaak gebruikte kleine methoden versnelt de code aanzienlijk.
    • Constanten tellen tijdens de compilatiefase. Als een expressie afhankelijk is van een constante, wordt de werkelijke waarde van de constante erin gezet.

Als ontwikkelomgeving voor de webclient gebruiken we WebStorm.

Voor code-analyse gebruiken we SonarQube, waar we statische code-analysetools integreren. Met de analysetools volgen we de verslechtering van de kwaliteit van de broncode in JavaScript en werken we ernaar dat te voorkomen.

Over de 1C webclient

Welke taken hebben we opgelost / oplossen we

Tijdens de uitvoering van het project zijn we tegen een aantal interessante taken aangelopen die we moesten oplossen.

Gegevensuitwisseling met de server en tussen vensters

Er zijn situaties waarin het obfusceren van de broncode de werking van het systeem kan belemmeren. Code die extern is ten opzichte van de uitvoerbare code van de webclient kan als gevolg van obfuscatie functienamen en parameters hebben die verschillen van wat onze uitvoerbare code verwacht. De externe code voor ons is:

  • Code die van de server komt in de vorm van datastructuren
  • Code van een ander venster van de toepassing

Om obfuscatie te vermijden bij interactie met de server gebruiken we de 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;
}

En om obfuscatie te vermijden bij interaction met andere vensters gebruiken we zogenaamde geëxporteerde interfaces (interfaces waarvan alle methoden geëxporteerd zijn).

/**
 * Экспортируемый интерфейс контрола 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 (){}

We gebruikten Virtual DOM voordat het mainstream werd)

Net als alle ontwikkelaars die met complexe web-UI werken, realiseerden we ons snel dat de DOM niet goed geschikt is voor interactie met dynamische gebruikersinterfaces. Vrijwel onmiddellijk werd een analoge Virtual DOM geïmplementeerd voor het optimaliseren van de UI. Tijdens het verwerken van de gebeurtenis worden alle DOM-wijzigingen in het geheugen opgeslagen en pas na voltooiing van alle bewerkingen worden de verzamelde wijzigingen op de DOM-boom toegepast.

Optimalisatie van de webclient

Om onze webclient sneller te laten werken, proberen we maximaal gebruik te maken van de standaardmogelijkheden van de browser (CSS enz.). Zo wordt de commandopanel van het formulier (die zich op bijna elk formulier van de applicatie bevindt) uitsluitend met de middelen van de browser gerenderd, met dynamische lay-out op basis van CSS.

Over de 1C webclient

Testen

Voor functionele en prestatie-testen gebruiken we een zelfontwikkeld hulpmiddel (geschreven in Java en C++), evenals een set tests gebaseerd op Selenium.

Ons hulpmiddel is veelzijdig – het kan vrijwel alle vensterprogramma's testen en is daarom geschikt voor zowel het testen van een dunne client als een webclient. Het hulpmiddel legt de acties van de gebruiker die de applicatie ‘1C’ heeft gestart vast in een scriptbestand. Tegelijkertijd worden de afbeeldingen van de werkruimte van het scherm – referenties – opgenomen. Bij de controle van nieuwe versies van de webclient worden de scripts afgespeeld zonder gebruikersdeelname. In gevallen waarin de screenshot niet overeenkomt met de referentie op een bepaalde stap, wordt de test als mislukt beschouwd, waarna een kwaliteitsmedewerker een onderzoek voert – is het een fout of een geplande wijziging in het gedrag van het systeem. In het geval van een gepland gedrag worden de referenties automatisch vervangen door nieuwe.

Het hulpmiddel meet ook de prestaties van applicaties met een nauwkeurigheid van 25 milliseconden. In bepaalde gevallen herhalen we delen van het script (bijvoorbeeld voeren we de orderinvoer meerdere keren uit) om de degradatie van de looptijd in de loop van de tijd te analyseren. De resultaten van alle metingen worden in een logboek vastgelegd voor analyse.

Over de 1C webclient
Ons testhulpmiddel en de geteste applicatie

Ons hulpmiddel en Selenium complementeren elkaar; bijvoorbeeld, als een knop op een van de schermen van plaats is veranderd – kan Selenium dat mogelijk niet opmerken, maar ons hulpmiddel zal het opmerken, omdat het pixel-voor-pixel vergelijkingen van de screenshot met de referentie maakt. Ook is het hulpmiddel in staat om problemen met de verwerking van invoer van toetsenbord of muis op te sporen, omdat het precies dat reproduceert.

Tests op beide hulpmiddelen (ons en Selenium) starten typische werkscenario's uit onze applicaties. Tests worden automatisch gestart na de dagelijkse bouw van het platform ‘1C:Enterprise’. In het geval van vertraging van de scripts (ten opzichte van de vorige build) voeren we een onderzoek uit en elimineren we de oorzaak van de vertraging. Ons criterium is eenvoudig – de nieuwe build moet niet langzamer werken dan de vorige.

Voor het onderzoeken van incidenten van vertraging in de werking gebruiken ontwikkelaars verschillende hulpmiddelen; voornamelijk wordt gebruikgemaakt van Dynatrace AJAX Edition gemaakt door DynaTrace. Er wordt een registratie gemaakt van de logs van de problematische operatie op de vorige en de nieuwe versie, waarna de logs worden geanalyseerd. In dit geval kan de tijd voor het uitvoeren van enkele operaties (in milliseconden) niet bepalend zijn - in de browser worden periodiek achtergrondprocessen zoals garbage collection uitgevoerd, die de uitvoeringstijd van functies kunnen beïnvloeden en de situatie kunnen vervormen. Meer relevante parameters zijn in dit geval het aantal uitgevoerde JavaScript-instructies, het aantal atomische operaties op de DOM, enzovoorts. Als het aantal instructies/operaties in hetzelfde scenario in de nieuwe versie is toegenomen, betekent dit bijna altijd een verlaging van de snelheid die moet worden gecorrigeerd.

Een andere oorzaak van de prestatieverlaging kan zijn dat de Google Closure Compiler om de een of andere reden geen inline substitutie van de functie heeft kunnen maken (bijvoorbeeld omdat de functie recursief of virtueel is). In dit geval proberen we de situatie te corrigeren door de broncode opnieuw te schrijven.

Browsere extensies

Wanneer de applicatie functionaliteit nodig heeft die niet in JavaScript beschikbaar is, gebruiken we browsere extensies:

Onze extensies bestaan uit twee delen. Het eerste deel is wat men een browsere extensie noemt (meestal geschreven in JavaScript voor Chrome en Firefox), die interactie heeft met het tweede deel - de binaire extensie, die de benodigde functionaliteit implementeert. We moeten vermelden dat we drie versies van binaire extensies schrijven - voor Windows, Linux en MacOS. De binaire extensie wordt geleverd als onderdeel van het 1C:Enterprise platform en bevindt zich op de 1C applicatieserver. Bij de eerste oproep vanaf de webclient wordt deze op de clientcomputer gedownload en in de browser geïnstalleerd.

Wanneer we in Safari werken, maken onze extensies gebruik van NPAPI, terwijl ze in Internet Explorer gebruikmaken van ActiveX technologie. Microsoft Edge ondersteunt momenteel geen extensies, waardoor de webclient met beperkingen werkt.

Verdere ontwikkeling

Een van de taakgroepen voor het ontwikkelteam van de webclient is de verdere ontwikkeling van functionaliteit. De functionaliteit van de webclient moet identiek zijn aan die van de dunne client, en alle nieuwe functionaliteit moet gelijktijdig worden geïmplementeerd in zowel de dunne als de webclient.

Andere taken zijn de ontwikkeling van de architectuur, refactoring, en het verbeteren van de prestaties en betrouwbaarheid. Een van de richtingen is de verdere verschuiving naar een asynchrone werkmodel. Een deel van de functionaliteit van de webclient is momenteel gebaseerd op een synchrone interactiemodel met de server. Het asynchrone model wordt nu steeds relevanter in browsers (en niet alleen in browsers), wat ons dwingt de webclient te modificeren door synchrone aanroepen te vervangen door asynchrone (en de bijbehorende refactoring van de code). De geleidelijke overgang naar het asynchrone model wordt verklaard door de noodzaak om uitgebracht oplossingen te ondersteunen en ze geleidelijk aan te passen.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster