Over 1C webclient

Een van de leuke kenmerken van de 1C:Enterprise-technologie is dat de applicatie-oplossing, ontwikkeld met behulp van beheerde formulieren-technologie, zowel in een thin (uitvoerbare) client voor Windows, Linux, MacOS X, als als een webclient voor 5 browsers kan worden gestart - Chrome, Internet Explorer, Firefox, Safari, Edge en dit alles zonder de broncode van de applicatie te wijzigen. Bovendien functioneert en ziet de applicatie in de thin client en in de browser uiterlijk vrijwel identiek uit.
Zoek 10 verschillen (2 foto's onder de snit):

Thin client-venster op Linux:

Over 1C webclient

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

Over 1C webclient

Waarom hebben we een webclient gemaakt? Om het enigszins zielig te zeggen: de tijd heeft ons zo'n taak opgelegd. Werken via internet is lange tijd een voorwaarde geweest voor zakelijke toepassingen. Ten eerste hebben we voor onze thin client de mogelijkheid toegevoegd om via internet te werken (sommige van onze concurrenten zijn daar overigens mee gestopt; anderen hebben daarentegen de thin client verlaten en zich beperkt tot het implementeren van een webclient). We hebben besloten om onze gebruikers de mogelijkheid te geven de klantoptie te kiezen die het beste bij hen past.

Over 1C webclient

Het toevoegen van webgebaseerde mogelijkheden aan de thin client was een groot project met een complete verandering in de client-server-architectuur. Het maken van een webclient is een compleet nieuw project, dat helemaal opnieuw begint.

Formulering van het probleem

Dus de projectvereisten: de webclient moet hetzelfde doen als de thin client, namelijk:

  1. Gebruikersinterface weergeven
  2. Voer clientcode uit die is geschreven in 1C-taal

De gebruikersinterface in 1C wordt beschreven in een visuele editor, maar declaratief, zonder pixel-voor-pixel rangschikking van elementen; Er worden ongeveer drie dozijn soorten interface-elementen gebruikt: knoppen, invoervelden (tekst, numeriek, datum/tijd), lijsten, tabellen, grafieken, enz.

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

Zowel de thin client (wanneer u via internet werkt) als de webclient gebruiken dezelfde set webservices om met de 1C-applicatieserver te communiceren. Clientimplementaties zijn uiteraard anders: de thin client is geschreven in C++, de webclient is geschreven in JavaScript.

Een beetje geschiedenis

Het webclientproject startte in 2006 met een team van (gemiddeld) 5 personen. In bepaalde fasen van het project werden ontwikkelaars betrokken om specifieke functionaliteit te implementeren (spreadsheetdocument, diagrammen, enz.); in de regel waren dit dezelfde ontwikkelaars die deze functionaliteit in de thin client deden. Die. ontwikkelaars herschreven componenten in JavaScript die ze eerder in C++ hadden gemaakt.

Vanaf het allereerste begin hebben we het idee van elke automatische (zelfs gedeeltelijke) conversie van C++ thin client-code naar JavaScript-webclient verworpen vanwege de sterke conceptuele verschillen tussen de twee talen; de webclient is helemaal opnieuw in JavaScript geschreven.

In de eerste iteraties van het project converteerde de webclient clientcode in de ingebouwde 1C-taal rechtstreeks naar JavaScript. De thin client gedraagt ​​zich anders: de code in de ingebouwde 1C-taal wordt gecompileerd tot bytecode, en vervolgens wordt deze bytecode op de client geïnterpreteerd. Vervolgens begon de webclient hetzelfde te doen - ten eerste leverde het een prestatiewinst op en ten tweede maakte het het mogelijk om de architectuur van de thin- en webclients te verenigen.

De eerste versie van het 1C:Enterprise-platform met webclientondersteuning werd in 2009 uitgebracht. De webclient ondersteunde destijds 2 browsers: Internet Explorer en Firefox. De oorspronkelijke plannen omvatten ondersteuning voor Opera, maar vanwege onoverkomelijke problemen op dat moment met de sluitingshandlers van de applicatie in Opera (het was niet mogelijk om met 100% zekerheid te volgen dat de applicatie werd afgesloten, en op dat moment de ontkoppelingsprocedure uit te voeren de 1C-applicatieserver) uit deze plannen moesten worden opgegeven.

Projectstructuur

In totaal heeft het 1C:Enterprise-platform 4 projecten geschreven in JavaScript:

  1. WebTools – gedeelde bibliotheken die door andere projecten worden gebruikt (we nemen ook Google Sluitingsbibliotheek).
  2. Controle-element Opgemaakt document (geïmplementeerd in JavaScript in zowel de thin client als de webclient)
  3. Controle-element Планировщик (geïmplementeerd in JavaScript in zowel de thin client als de webclient)
  4. web cliënt

De structuur van elk project lijkt op de structuur van Java-projecten (of .NET-projecten - welke het dichtst in de buurt komt); We hebben naamruimten en elke naamruimte bevindt zich in een aparte map. In de map bevinden zich bestanden en naamruimteklassen. Er zijn ongeveer 1000 bestanden in het webclientproject.

Structureel is de webclient grotendeels onderverdeeld in de volgende subsystemen:

  • Beheerde clientapplicatie-interface
    • Algemene applicatie-interface (systeemmenu's, panelen)
    • Interface van beheerde formulieren, inclusief onder andere ongeveer 30 bedieningselementen (knoppen, verschillende soorten invoervelden - tekst, numeriek, datum/tijd, enz., tabellen, lijsten, grafieken, enz.)

  • Objectmodel beschikbaar voor ontwikkelaars op de client (meer dan 400 typen in totaal: beheerd interface-objectmodel, instellingen voor gegevenslay-out, voorwaardelijke stijl, enz.)
  • Tolk van de ingebouwde 1C-taal
  • Browserextensies (gebruikt voor functionaliteit die niet wordt ondersteund in JavaScript)
    • Werken met cryptografie
    • Werken met bestanden
    • Technologie van externe componenten, waardoor ze kunnen worden gebruikt in zowel thin- als webclients

Ontwikkelingsfuncties

Het implementeren van al het bovenstaande in JavaScript is niet eenvoudig. Misschien is de 1C-webclient een van de grootste client-side applicaties geschreven in JavaScript - ongeveer 450.000 regels. We maken actief gebruik van een objectgeoriënteerde aanpak in de webclientcode, wat het werken met zo'n groot project vereenvoudigt.

Om de grootte van de clientcode te minimaliseren, hebben we eerst onze eigen obfuscator gebruikt, en vanaf platformversie 8.3.6 (oktober 2014) zijn we begonnen met het gebruik van Google Sluitingscompiler. Het effect van gebruik in cijfers – de grootte van het webclientframework na verduistering:

  • Eigen verduisteraar – 1556 kb
  • Google Sluitingscompiler – 1073 kb

Door Google Closure Compiler te gebruiken, konden we de prestaties van de webclient met 30% verbeteren in vergelijking met onze eigen obfuscator. Bovendien is de hoeveelheid geheugen die door de applicatie wordt verbruikt met 15-25% afgenomen (afhankelijk van de browser).

Google Closure Compiler werkt heel goed met objectgeoriënteerde code, dus de efficiëntie voor de webclient is zo hoog mogelijk. Closure Compiler doet een paar goede dingen voor ons:

  • Statische typecontrole tijdens de bouwfase van het project (zorgt ervoor dat we de code afdekken met JSDoc-annotaties). Het resultaat is statisch typen, dat qua niveau zeer dicht bij typen in C++ ligt. Dit helpt om een ​​vrij groot percentage fouten op te sporen in de fase van het samenstellen van het project.
  • Het verkleinen van de codegrootte door verduistering
  • Een aantal optimalisaties van de uitgevoerde code bijvoorbeeld, zoals:
    • inline functievervangingen. Het aanroepen van een functie in JavaScript is een vrij dure operatie, en inline vervangingen van veelgebruikte kleine methoden versnellen de code aanzienlijk.
    • Constanten tellen tijdens het compileren. Als een uitdrukking afhankelijk is van een constante, wordt de werkelijke waarde van de constante daarin vervangen

We gebruiken WebStorm als onze ontwikkelomgeving voor webclients.

Voor codeanalyse gebruiken we SonarQube, waar we statische code-analysatoren integreren. Met behulp van analysers monitoren we de achteruitgang van de kwaliteit van de JavaScript-broncode en proberen we deze te voorkomen.

Over 1C webclient

Welke problemen hebben/zijn we aan het oplossen?

Tijdens de uitvoering van het project kwamen we een aantal interessante problemen tegen die we moesten oplossen.

Gegevens uitwisselen met de server en tussen vensters

Er zijn situaties waarin verduistering van de broncode de werking van het systeem kan verstoren. Code die buiten de uitvoerbare code van de webclient ligt, kan vanwege onduidelijkheid functie- en parameternamen hebben die verschillen van de namen die onze uitvoerbare code verwacht. De externe code voor ons is:

  • Code afkomstig van de server in de vorm van datastructuren
  • Code voor een ander toepassingsvenster

Om verwarring te voorkomen bij interactie met de server, gebruiken we de @expose-tag:

/**
 * @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 verwarring bij de interactie met andere vensters te voorkomen, gebruiken we zogenaamde geëxporteerde interfaces (interfaces waarin alle methoden worden geëxporteerd).

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

Zoals alle ontwikkelaars die te maken hebben met complexe web-UI's, realiseerden we ons al snel dat de DOM slecht geschikt is voor het werken met dynamische gebruikersinterfaces. Vrijwel onmiddellijk werd een analoog van Virtual DOM geïmplementeerd om het werken met de gebruikersinterface te optimaliseren. Tijdens de gebeurtenisverwerking worden alle DOM-wijzigingen in het geheugen opgeslagen en pas wanneer alle bewerkingen zijn voltooid, worden de verzamelde wijzigingen toegepast op de DOM-boom.

Het optimaliseren van de webclient

Om onze webclient sneller te laten werken, proberen wij de standaard browsermogelijkheden (CSS etc.) maximaal te benutten. Het formulieropdrachtpaneel (dat zich op vrijwel elk formulier van de applicatie bevindt) wordt dus uitsluitend weergegeven met behulp van browsertools, met behulp van een dynamische lay-out op basis van CSS.

Over 1C webclient

Testen

Voor functionele en prestatietests gebruiken we een eigen tool (geschreven in Java en C++), evenals een reeks tests die daarop zijn gebouwd Selenium.

Onze tool is universeel: u kunt er vrijwel elk vensterprogramma mee testen en is daarom geschikt voor het testen van zowel een thin client als een webclient. De tool registreert de acties van de gebruiker die de 1C-applicatieoplossing heeft gestart in een scriptbestand. Tegelijkertijd worden beelden van het werkgebied van het scherm – standaarden – opgenomen. Bij het monitoren van nieuwe versies van de webclient worden scripts afgespeeld zonder deelname van de gebruiker. In gevallen waarin de schermafbeelding bij geen enkele stap overeenkomt met de referentie, wordt de test als mislukt beschouwd, waarna een kwaliteitsspecialist onderzoek doet om vast te stellen of dit een fout is of een geplande verandering in het gedrag van het systeem. Bij gepland gedrag worden de standaarden automatisch vervangen door nieuwe.

De tool meet ook de applicatieprestaties met een nauwkeurigheid van maximaal 25 milliseconden. In sommige gevallen herhalen we delen van het script (bijvoorbeeld door de orderinvoer verschillende keren te herhalen) om de verslechtering van de uitvoeringstijd in de loop van de tijd te analyseren. De resultaten van alle metingen worden vastgelegd in een logboek voor analyse.

Over 1C webclient
Onze testtool en applicatie die worden getest

Onze tool en Selenium vullen elkaar aan; Als bijvoorbeeld een knop op een van de schermen van locatie is veranderd, zal Selenium dit mogelijk niet volgen, maar onze tool zal dit merken, omdat maakt een pixel-voor-pixel vergelijking van de screenshot met de standaard. De tool kan ook problemen met de verwerking van invoer vanaf het toetsenbord of de muis opsporen, aangezien dit precies is wat het reproduceert.

Tests op beide tools (de onze en Selenium) voeren typische werkscenario's uit van onze applicatieoplossingen. Tests worden automatisch gelanceerd na de dagelijkse bouw van het 1C:Enterprise-platform. Als scripts langzamer zijn (vergeleken met de vorige build), onderzoeken we de oorzaak van de vertraging en lossen we deze op. Ons criterium is simpel: de nieuwe build mag niet langzamer werken dan de vorige.

Ontwikkelaars gebruiken verschillende tools om vertragingsincidenten te onderzoeken; voornamelijk gebruikt Dynatrace AJAX-editie productiebedrijf Dyna Trace. Logboeken van de uitvoering van de problematische bewerking op de vorige en nieuwe builds worden vastgelegd, waarna de logs worden geanalyseerd. Tegelijkertijd is de uitvoeringstijd van afzonderlijke bewerkingen (in milliseconden) misschien geen doorslaggevende factor: serviceprocessen zoals garbage collection worden periodiek in de browser gestart, ze kunnen overlappen met de uitvoeringstijd van functies en het beeld vertekenen. Relevantere parameters in dit geval zijn het aantal uitgevoerde JavaScript-instructies, het aantal atomaire bewerkingen op de DOM, enz. Als het aantal instructies/bewerkingen in hetzelfde script in een nieuwe versie is toegenomen, betekent dit vrijwel altijd een prestatiedaling die moet worden gecorrigeerd.

Een van de redenen voor de prestatiedaling kan ook zijn dat Google Closure Compiler om de een of andere reden geen inline vervanging van de functie kon uitvoeren (bijvoorbeeld omdat de functie recursief of virtueel is). In dit geval proberen we de situatie te corrigeren door de broncode te herschrijven.

Browser-extensies

Wanneer een applicatieoplossing functionaliteit nodig heeft die niet beschikbaar is in JavaScript, gebruiken wij browserextensies:

Onze uitbreidingen bestaan ​​uit twee delen. Het eerste deel is een zogenaamde browserextensie (meestal extensies voor Chrome en Firefox geschreven in JavaScript), die samenwerken met het tweede deel: een binaire extensie die de functionaliteit implementeert die we nodig hebben. Er moet worden vermeld dat we 3 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. Wanneer het voor de eerste keer wordt aangeroepen vanaf een webclient, wordt het naar de clientcomputer gedownload en in de browser geïnstalleerd.

Wanneer ze in Safari worden uitgevoerd, gebruiken onze extensies NPAPI; wanneer ze in Internet Explorer worden uitgevoerd, gebruiken ze ActiveX-technologie. Microsoft Edge ondersteunt nog geen extensies, dus de webclient daarin werkt met beperkingen.

Verdere ontwikkeling

Eén van de taken van het webclient ontwikkelteam is het verder ontwikkelen van functionaliteit. De functionaliteit van de webclient dient identiek te zijn aan de functionaliteit van de thin client; alle nieuwe functionaliteit wordt gelijktijdig geïmplementeerd in zowel de thin- als de webclient.

Andere taken zijn onder meer het ontwikkelen van de architectuur, refactoring en het verbeteren van de prestaties en betrouwbaarheid. Eén van de richtingen is bijvoorbeeld een verdere beweging in de richting van een asynchroon werkmodel. Een deel van de functionaliteit van de webclient is momenteel gebouwd op een synchroon interactiemodel met de server. Het asynchrone model wordt nu relevanter in browsers (en niet alleen in browsers), en dit dwingt ons om de webclient aan te passen door synchrone oproepen te vervangen door asynchrone oproepen (en de code dienovereenkomstig te herstructureren). De geleidelijke overgang naar een asynchroon model wordt verklaard door de noodzaak om vrijgegeven oplossingen en hun geleidelijke aanpassing te ondersteunen.

Bron: www.habr.com

Voeg een reactie