Om webklienten 1C

En af de behagelige funktioner ved 1C:Enterprise-teknologi er, at applikationsløsningen, der er udviklet ved hjælp af teknologien med styrede former, kan køre både som en tynd klient på Windows, Linux, MacOS X og som en webklient i 5 browsere – Chrome, Internet Explorer, Firefox, Safari, Edge, alt sammen uden at ændre kildekoden til applikationen. Desuden fungerer applikationen i den tynde klient og i browseren næsten identisk i både funktion og udseende.
Find 10 forskelle (under kattebilledet 2 billeder):

Vindue til den tynde klient på Linux:

Om webklienten 1C

Det samme vindue i webklienten (i browseren Chrome):

Om webklienten 1C

Hvorfor lavede vi webklienten? For at sige det lidt dramatisk, var dette en opgave, som tiden har stillet os. Det er længe siden, at arbejde over internettet er blevet en nødvendig betingelse for forretningsapplikationer. Først tilføjede vi muligheden for at arbejde over internettet for vores tynde klient (nogle af vores konkurrenter stoppede faktisk hier; andre, derimod, opgav den tynde klient og begrænsede sig til implementeringen af webklienten). Vi besluttede at give vores brugere mulighed for at vælge den klienttype, der passer dem bedst.

Om webklienten 1C

Tilføjelsen af muligheden for at arbejde over internettet for den tynde klient var et stort projekt med en fuldstændig ændring af arkitekturen for klient-server-interaktionen. Oprettelsen af webklienten er derimod et helt nyt projekt, der startede fra bunden.

Problemformulering

Så kravene til projektet: webklienten skal kunne udføre det samme som den tynde klient, nemlig:

  1. Vise brugergrænsefladen
  2. Udføre klientskode skrevet i 1C-sprog

Brugergrænsefladen i 1C beskrives i en visuel editor, men deklarativt, uden pixel-for-pixel placering af elementer; der anvendes omkring tre dusin typer af interfaceelementer – knapper, indtastningsfelter (tekst, tal, dato/tid), lister, tabeller, grafer osv.

Klientskoden i 1C-sprog kan indeholde serveropkald, arbejde med lokale ressourcer (filer osv.), udskrivning og meget andet.

Både den tynde klient (ved arbejde via web) og webklienten bruger det samme sæt webtjenester til kommunikation med 1C-applikationsserveren. Implementeringen hos klienterne er selvfølgelig forskellig – den tynde klient er skrevet i C++, mens webklienten er skrevet i JavaScript.

Lidt historie

Projektet om at skabe en webklient blev startet i 2006, og i gennemsnit deltog et hold på 5 personer. På bestemte stadier af projektet blev der tilknyttet udviklere for at implementere specifik funktionalitet (regneark, diagrammer osv.); som regel var det de samme udviklere, der havde skabt denne funktionalitet i den tynde klient. Dvs. at udviklerne genprogrammerede JavaScript-komponenter, som de tidligere havde lavet i C++.

Fra begyndelsen forkastede vi idéen om en eller anden automatisk (om end delvis) konvertering af C++-koden fra den tynde klient til JavaScript-webklienten på grund af de stærke konceptuelle forskelle mellem disse to sprog; webklienten blev skrevet i JavaScript fra bunden.

I de tidlige iterationer af projektet konverterede webklienten klientkoden på det indbyggede 1C-sprog direkte til JavaScript. Den tynde klient fungerer anderledes - koden på det indbyggede 1C-sprog kompileres til bytekode, og derefter bliver denne bytekode fortolket på klienten. Senere begyndte webklienten også at gøre det samme – for det første gav det en præstationsfordel, for det andet gjorde det det muligt at ensrette arkitekturen mellem den tynde og web-klient.

Den første version af 1C:Enterprise-platformen med støtte til webklienten blev udgivet i 2009. På det tidspunkt understøttede webklienten 2 browsere - Internet Explorer og Firefox. I de oprindelige planer var der støtte til Opera, men på grund af uovervindelige problemer med håndteringen af lukning af applikationen i Opera (det var ikke muligt at spore med 100% sikkerhed, hvornår applikationen lukkede, og på det tidspunkt gennemføre proceduren for at afbryde forbindelsen til 1C-applikationsserveren) måtte disse planer opgives.

Project structure

I alt er der 4 projekter i 1C:Enterprise-platformen, der er skrevet i JavaScript:

  1. WebTools – generiske biblioteker, der anvendes af de øvrige projekter (herunder) Google Closure Library).
  2. Brugergrænseelement FormatteretDokument (implementeret i både JavaScript og i den tynde klient og i webklienten)
  3. Brugergrænseelement Scheduler (implementeret i både JavaScript og i den tynde klient og i webklienten)
  4. A web client

Strukturen af hvert projekt minder om strukturen af Java-projekter (eller .NET-projekter - alt efter hvad der er nærmest for én); vi har navneområder, og hvert navneområde ligger i en separat mappe. Inde i mappen findes filer og klasser af navneområdet. I webklientens projekt er der omkring 1000 filer.

Strukturelt er webklienten groft opdelt i følgende delsystemer:

  • Håndteret brugergrænseflade til klientapplikationen
    • Brugergrænseflade til applikationen (systemmenuer, paneler)
    • Grænseflade til administrerede formularer, herunder cirka 30 kontrolelementer (knapper, forskellige typer indtastningsfelter – tekst, tal, dato/tid osv., tabeller, lister, grafer osv.)

  • Objektmodel tilgængelig for udviklere på klientsiden (over 400 typer: objektmodel for den administrerede grænseflade, dataopstillingsindstillinger, betinget formatering osv.)
  • Fortolker til det indbyggede sprog 1C
  • Browserudvidelser (bruges til funktionalitet, der ikke understøttes i JavaScript)
    • Arbejder med kryptografi
    • Arbejde med filer
    • Teknologi til eksterne komponenter, der gør det muligt at bruge dem i både den tynde og webklient

Funktioner ved udvikling

Implementeringen af alt det ovenfor beskrevne i JavaScript er en udfordrende opgave. Måske er 1C webklient en af de største client-side applikationer skrevet i JavaScript – omkring 450.000 linjer. Vi bruger en objektorienteret tilgang i vores webklientkode, hvilket forenkler arbejdet med et så stort projekt.

For at minimere størrelsen af klientskoden brugte vi oprindeligt vores egen obfuskator, og fra version 8.3.6 (oktober 2014) begyndte vi at bruge Google Closure Compiler. Effekten af anvendelsen i tal – størrelsen af webklientens ramme efter obfuskation:

  • Egen obfuskator – 1556 kB
  • Google Closure Compiler – 1073 kB

Brugen af Google Closure Compiler har hjulpet os med at øge hastigheden på webklienten med 30% sammenlignet med vores egen obfuskator. Desuden er mængden af hukommelse, der bruges af applikationen, reduceret med 15-25% (afhængigt af browseren).

Google Closure Compiler fungerer meget godt med objektorienteret kode, hvilket gør dens effektivitet til webklienten maksimal. Closure Compiler gør flere gode ting for os:

  • Statisk typekontrol på tidspunktet for projektbygning (sikret ved at vi dækker koden med JSDoc-annoteringer). Dette resulterer i statisk typificering, der er meget tæt på typificeringen i C++. Det hjælper med at fange et ret stort procentdel af fejlene på kompileringstidspunktet.
  • Reduceret kodelængde gennem obfuskation
  • Rækken af optimeringer af den udførte kode, for eksempel som:
    • Inline-funktioner. At kalde en funktion i JavaScript er en relativt omkostningstung operation, og inline-implementering af ofte brugte små metoder kan betydeligt fremskynde kodekørslen.
    • Konstantberegning ved kompilering. Hvis et udtryk afhænger af en konstant, vil den faktiske værdi af konstanten blive indsat.

Som udviklingsmiljø for webklienten bruger vi WebStorm.

Til kodeanalyse anvender vi SonarQube, hvor vi integrerer statiske kodeanalysatorer. Ved hjælp af analysatorerne overvåger vi forringelsen af kvaliteten af kildekoden i JavaScript og forsøger at undgå det.

Om webklienten 1C

Hvilke opgaver har vi løst/ løser?

Under projektets gennemførelse stødte vi på en række interessante opgaver, som vi måtte løse.

Dataudveksling med serveren og mellem vinduerne.

Der er situationer, hvor obfuskeret kildekode kan forstyrre systemets funktion. Koden, der er ekstern i forhold til den udførende kode i webklienten, kan på grund af obfuskering have funktions- og parameter-navne, der adskiller sig fra dem, som vores udførende kode forventer. Den eksterne kode for os er:

  • Koden, der kommer fra serveren i form af datakonstruktioner.
  • Koden fra et andet vindue i applikationen.

For at undgå obfuskering ved interaktion med serveren bruger vi 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;
}

Og for at undgå obfuskering ved interaktion med andre vinduer bruger vi såkaldte eksporterede grænseflader (grænseflader, hvor alle metoder er eksporterede).

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

Vi brugte Virtual DOM, før det blev mainstream.

Som alle udviklere, der arbejder med komplekse web-UI'er, indså vi hurtigt, at DOM ikke er velegnet til at arbejde med dynamiske brugergrænseflader. Næsten med det samme blev der implementeret en analog til Virtual DOM for at optimere arbejdet med UI. Under behandlingen af begivenheden gemmes alle DOM-ændringer i hukommelsen, og først ved afslutningen af alle operationer anvendes de akkumulerede ændringer på DOM-træet.

Optimering af webklientens ydeevne.

For at få vores webklient til at fungere hurtigere, stræber vi efter at udnytte de indbyggede funktioner i browseren (CSS osv.) så meget som muligt. Således tegnes kontrolpanelet i formularen (placeres praktisk talt på hver formular i applikationen) udelukkende ved hjælp af browserens funktioner, med dynamisk layout baseret på CSS.

Om webklienten 1C

Testning

Til funktionel test og ydelsestest bruger vi et værktøj, vi selv har udviklet (skrevet i Java og C++), samt en testsamling baseret på Selenium.

Vores værktøj er alsidigt – det gør det muligt at teste næsten enhver desktop-applikation og er derfor egnet til både test af tynde klienter og webklienter. Værktøjet optager handlingerne fra brugeren, der har startet applikationen "1C", i en scriptfil. Samtidig optages billeder af skrivebordets arbejdsområde som referencebilleder. Når der kontrolleres nye versioner af webklienten, afspilles scripts uden brugerens deltagelse. Hvis skærmbilledet ikke stemmer overens med referencen på et hvilket som helst trin, betragtes testen som mislykket, hvorefter en kvalitetsansvarlig foretager en undersøgelse – for at afgøre, om det er en fejl eller en planlagt ændring af systemets adfærd. I tilfælde af planlagt adfærd erstattes referencen automatisk med nye.

Værktøjet udfører også ydelsesmålinger af applikationerne med en nøjagtighed på 25 millisekunder. I visse tilfælde cirkulerer vi dele af scriptet (f.eks. gentager vi ordreindlæg flere gange) for at analysere forringelsen af udførelsestiden over tid. Resultaterne af alle målinger registreres i en log til analyse.

Om webklienten 1C
Vores testværktøj og den testede applikation

Vores værktøj og Selenium supplerer hinanden; for eksempel, hvis en knap på en af skærmene har ændret position, kan Selenium muligvis ikke registrere dette, men vores værktøj vil lægge mærke til det, da det udfører pixel-til-pixel sammenligning mellem skærmbilledet og referencen. Værktøjet kan også opdage problemer med behandlingen af input fra tastatur eller mus, da det netop reproducerer disse.

Testene på begge værktøjer (vores og Selenium) kører standard arbejdsflows fra vores applikationsløsninger. Testene startes automatisk efter den daglige bygning af platformen "1C:Enterprise". Hvis der er en forsinkelse i workflows (sammenlignet med den tidligere bygning), gennemfører vi en undersøgelse og fjerner årsagen til forsinkelsen. Vores kriterium er simpelt – den nye bygning skal ikke være langsommere end den forrige.

Til undersøgelse af hændelser med forsinket arbejde bruger udviklerne forskellige værktøjer; primært anvendes Dynatrace AJAX Edition produktionsselskab DynaTrace. Der foretages optagelse af logs for udførelsen af den problematiske operation i den tidligere og den nye version, hvorefter loggene analyseres. Her kan udførelsestiden for enkelte operationer (i millisekunder) muligvis ikke være en afgørende faktor – i browseren kører der periodisk serviceprocesser som oprydning, der kan påvirke udførelsestiden for funktioner og forvride billedet. De mere relevante parametre i dette tilfælde vil være antallet af udførte JavaScript-kommandoer, antallet af atomiske operationer på DOM osv. Hvis antallet af kommandoer/operationer i det samme scenarie i den nye version er steget – betyder det næsten altid en reduktion i ydeevne, som skal rettes.

En anden årsag til reduktionen i ydeevne kan være, at Google Closure Compiler af en eller anden grund ikke kunne udføre inline-udskiftningen af en funktion (f.eks. fordi funktionen er rekursiv eller virtuel). I dette tilfælde forsøger vi at rette situationen ved at omskrive kildekoden.

Browserudvidelser

Når den applikationsmæssige løsning har brug for funktionalitet, som ikke findes i JavaScript, bruger vi browserudvidelser:

Vores udvidelser består af to dele. Den første del er det, der kaldes en browserudvidelse (typisk udvidelser skrevet i JavaScript til Chrome og Firefox), som interagerer med den anden del – en binær udvidelse, der implementerer den funktionalitet, vi har brug for. Det skal nævnes, at vi skriver 3 versioner af de binære udvidelser – til Windows, Linux og MacOS. Den binære udvidelse leveres som en del af platformen 1C:Enterprise og findes på 1C-applikationsserveren. Ved første opkald fra webklienten indlæses den på klientcomputeren og installeres i browseren.

Når man arbejder i Safari, bruger vores udvidelser NPAPI, mens de i Internet Explorer bruger ActiveX-teknologien. Microsoft Edge understøtter endnu ikke udvidelser, så webklienten fungerer med begrænsninger.

Fremtidig udvikling

En af opgavegrupperne for teamet bag webklienten er at videreudvikle funktionaliteten. Funktionaliteten i webklienten skal være identisk med funktionaliteten i den tynde klient, og al ny funktionalitet implementeres samtidig i begge klienter.

Andre opgaver inkluderer udvikling af arkitektur, refactoring, samt forbedring af ydeevne og pålidelighed. Et eksempel på dette er den fortsatte bevægelse mod en asynkron arbejdsmåde. En del af funktionaliteten i webklienten er i øjeblikket bygget på en synkron model for interaktion med serveren. Den asynkrone model bliver nu mere relevant i browsere (og ikke kun i browsere), hvilket tvinger os til at modificere webklienten ved at erstatte synkrone opkald med asynkrone (samt tilhørende refactoring af koden). Den gradvise overgang til en asynkron model skyldes behovet for at støtte de frigivne løsninger og gradvist tilpasse dem.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster