En av de trevliga egenskaperna med teknologin 1C:Enterprise Àr att applikationslösningen, som utvecklats med hjÀlp av tekniken för hanterade formulÀr, kan köras bÄde i en tunn (exekveringsbar) klient pÄ Windows, Linux, MacOS X och som webbklient i fem webblÀsare - Chrome, Internet Explorer, Firefox, Safari, Edge, och allt detta - utan att Àndra kÀllkoden för applikationen. Dessutom fungerar och ser applikationen i den tunna klienten och i webblÀsaren praktiskt taget identiskt ut.
Hitta 10 skillnader (under bilden 2 bilder):
Fönstret för den tunna klienten pÄ Linux:

Samma fönster i webbklienten (i webblÀsaren Chrome):

Varför skapade vi en webbklient? För att sÀga det lite pompöst, stÀllde tiden en sÄdan uppgift för oss. Det har lÀnge varit nödvÀndigt att arbeta via Internet för affÀrsapplikationer. Till en början tillade vi möjligheten att arbeta via Internet för vÄr tunna klient (vissa av vÄra konkurrenter, för övrigt, stannade dÀr; andra, tvÀrtom, övergav den tunna klienten och begrÀnsade sig till att implementera webbklienten). Vi bestÀmde oss för att ge vÄra anvÀndare möjlighet att vÀlja den klientversion som passar dem bÀst.

Att lÀgga till möjligheten att arbeta via Internet för den tunna klienten var ett stort projekt med en fullstÀndig förÀndring av arkitekturen för klient-server interaktion. Skapandet av webbklienten var en helt ny projekt som började frÄn grunden.
UppgiftsstÀllande
SÄ, kraven för projektet: webbklienten ska göra samma sak som den tunna klienten, nÀmligen:
- Visa anvÀndargrÀnssnittet
- Köra klientkod skriven i 1C-sprÄket
AnvÀndargrÀnssnittet i 1C beskrivs i en visuell redigerare, men deklarativt, utan pixel-mÀssig placering av element; cirka tre dussin typer av grÀnselement anvÀnds - knappar, inmatningsfÀlt (text, siffra, datum/tid), listor, tabeller, diagram osv.
Klientkoden i 1C-sprÄket kan innehÄlla serveranrop, arbete med lokala resurser (filer etc.), utskrift och mycket mer.
BÄde den tunna klienten (vid arbete via webben) och webbklienten anvÀnder samma uppsÀttning webbservrar för kommunikation med 1C:s applikationsserver. Implementeringen hos klienterna Àr naturligtvis olika - den tunna klienten Àr skriven i C++, webbklienten - i JavaScript.
Lite historia
Projektet med att skapa en webbkund pÄbörjades 2006 och involverade i genomsnitt ett team pÄ 5 personer. Vid olika skeden av projektet anlitades utvecklare för att implementera specifik funktionalitet (tabeller, diagram etc.); som regel var det samma utvecklare som hade skapat denna funktionalitet för den tunna klienten. Det vill sÀga, utvecklarna skrev om komponenter pÄ JavaScript som de tidigare hade skapat i C++.
Redan frÄn början avfÀrdade vi idén om nÄgon form av automatisk (Àven partiell) konvertering av C++-koden frÄn den tunna klienten till JavaScript-webbkunden med hÀnvisning till de stora konceptuella skillnaderna mellan de tvÄ sprÄken; webbkunden skrevs i JavaScript frÄn grunden.
I de första iterationerna av projektet konverterade webbkunden klientkoden i det inbyggda sprĂ„ket 1C direkt till JavaScript. Den tunna klienten fungerar annorlunda â koden i det inbyggda sprĂ„ket 1C kompileras till bytekod, och denna bytekod tolkas sedan pĂ„ klienten. Senare började Ă€ven webbkunden göra likadant â först och frĂ€mst gav det en prestandaförbĂ€ttring, för det andra möjliggjorde det en enhetlig arkitektur för den tunna och webbkunden.
Den första versionen av plattformen 1C:Enterprise med stöd för webbkunden slĂ€pptes 2009. Vid det tillfĂ€llet stödde webbkunden tvĂ„ webblĂ€sare â Internet Explorer och Firefox. I de ursprungliga planerna fanns stöd för Opera, men pĂ„ grund av oöverkomliga problem med hĂ€ndelsehanterare för stĂ€ngning av applikationen i Opera (vi kunde inte med 100% sĂ€kerhet spĂ„ra att applikationen stĂ€ngdes, och vid den tiden utföra proceduren för att koppla ifrĂ„n 1C-applikationsservern) var vi tvungna att ge upp dessa planer.
Projektstruktur
Det finns totalt 4 projekt inom plattformen 1C:Enterprise som Àr skrivna i JavaScript:
- WebTools â allmĂ€nna bibliotek som anvĂ€nds av de övriga projekten (hĂ€r inkluderas ocksĂ„ ).
- Kontrollelement (implementerad i bÄde JavaScript och i den tunna klienten och webbkunden)
- Kontrollelement (implementerad i bÄde JavaScript och i den tunna klienten och webbkunden)
- Webbkund
Strukturen för varje projekt pĂ„minner om strukturen för Java-projekt (eller .NET-projekt â vad som kĂ€nns nĂ€rmare); vi har namnrymder, dĂ€r varje namnrymd ligger i en egen mapp. Inuti mappen ligger filer och klasser under namnrymden. I webbkundens projekt finns det cirka 1000 filer.
StrukturmÀssigt delas webbkunden grovt upp i följande delsystem:
- Hantera grÀnssnittet för kundapplikationen
- Det gemensamma applikationsgrÀnssnittet (systemmenyer, paneler)
- GrĂ€nssnitt för hanterade formulĂ€r med cirka 30 kontrollobjekt (knappar, olika typer av inmatningsfĂ€lt â text, numeriska, datum/tid m.m., tabeller, listor, diagram, osv.)
- Objektmodellen som Àr tillgÀnglig för utvecklare pÄ klienten (över 400 typer: objektmodellen för det hanterade grÀnssnittet, datalayoutinstÀllningar, villkorlig formatering, osv.)
- Tolk för det inbyggda sprÄket 1C
- WebblÀsartillÀgg (anvÀnds för funktionalitet som inte stöds av JavaScript)
- Arbete med kryptografi
- Arbete med filer
- Teknik för externa komponenter som gör det möjligt att anvÀnda dem bÄde i tunn och webklient
Utvecklingsfunktioner
Att implementera allt ovanstĂ„ende i JavaScript Ă€r en utmaning. Kanske Ă€r webklienten 1C ett av de största klientbaserade programmen skrivna i JavaScript â cirka 450.000 rader. Vi anvĂ€nder aktivt objektorienterad programmering i koden för webklienten, vilket förenklar arbetet med ett sĂ„ stort projekt.
För att minimera storleken pĂ„ klientkoden anvĂ€nde vi först vĂ„r egen obfuskator, men frĂ„n och med version 8.3.6 (oktober 2014) började vi anvĂ€nda . Effekten av anvĂ€ndningen i siffror â storleken pĂ„ ramverket för webklienten efter obfuskering:
- Egen obfuskator â 1556 kB
- Google Closure Compiler â 1073 kB
AnvÀndningen av Google Closure Compiler har hjÀlpt oss att öka prestandan för webklienten med 30 % jÀmfört med vÄr egen obfuskator. Dessutom minskade minnesanvÀndningen för applikationen med 15-25 % (beroende pÄ webblÀsare).
Google Closure Compiler fungerar mycket bra med objektorienterad kod, vilket maximerar dess effektivitet för webklienten. Closure Compiler gör flera bra saker för oss:
- Statisk typkontroll vid byggfasen av projektet (garanteras genom att vi tÀcker koden med JSDoc-annoteringar). Slutresultatet blir statisk typning som Àr mycket nÀra den i C++. Detta hjÀlper till att fÄnga en stor andel av felen i projektets kompilering.
- Minskning av kodens storlek genom obfuskering
- En rad optimeringar av den körda koden, sÄsom:
- inline-inbÀddningar av funktioner. Funktionanrop i JavaScript Àr en ganska kostsam operation, och inline-inbÀddningar av ofta anvÀnda smÄ metoder pÄskyndar kodens arbete avsevÀrt.
- BerÀkning av konstanter vid kompilering. Om uttrycket beror pÄ en konstant, kommer det faktiska vÀrdet pÄ konstanten att infogas.
Som utvecklingsmiljö för webbkunden anvÀnder vi WebStorm.
För kodanalys anvÀnder vi , dit vi integrerar statiska kodanalysatorer. Med hjÀlp av analysatorerna övervakar vi nedgÄngen av kvaliteten pÄ kÀllkoden i JavaScript och försöker undvika det.

Vilka uppgifter har vi löst/löser?
Under genomförandet av projektet stötte vi pÄ en rad intressanta uppgifter som vi var tvungna att lösa.
Datakommunikation med servern och mellan fönster
Det finns situationer dÀr obfuscering av kÀllkoden kan störa systemets funktion. Koden som Àr extern i förhÄllande till den körbara koden för webbkunden kan pÄ grund av obfusceringen ha funktions- och parameter-namn som skiljer sig frÄn de som vÄr körbara kod förvÀntar sig. Den externa koden för oss Àr:
- Koden som kommer frÄn servern i form av datatyper
- Koden frÄn ett annat applikationsfönster
För att undvika obfuscering vid interaktion med servern anvÀnder vi taggen @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;
}Och för att undvika obfuscering vid interaktion med andra fönster anvÀnder vi sÄ kallade exporterade grÀnssnitt (grÀnssnitt dÀr alla metoder Àr exporterade).
/**
* ĐĐșŃĐżĐŸŃŃĐžŃŃĐ”ĐŒŃĐč ĐžĐœŃĐ”ŃŃĐ”ĐčŃ ĐșĐŸĐœŃŃĐŸĐ»Đ° 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 anvÀnde Virtual DOM innan det blev mainstream)
Som alla utvecklare som arbetar med komplexa webb-UI insÄg vi snabbt att DOM Àr dÄligt lÀmpad för att arbeta med dynamiska anvÀndargrÀnssnitt. NÀstan omedelbart implementerade vi en kopia av Virtual DOM för att optimera arbetet med UI. Under hÀndelsebehandlingen sparas alla Àndringar av DOM i minnet och först efter att alla operationer har slutförts tillÀmpas de samlade Àndringarna pÄ DOM-trÀdet.
Optimering av webbkundens arbete
För att vÄr webbkund ska fungera snabbare försöker vi utnyttja webblÀsarens inbyggda funktioner sÄ mycket som möjligt (CSS osv.). SÄledes ritas kommandopanelen för formulÀret (som Àr placerad pÄ nÀstan varje formulÀr i applikationen) enbart med hjÀlp av webblÀsarens medel, med dynamisk layout baserad pÄ CSS.

Testning
För funktionell testning och prestandatestning anvÀnder vi ett in-house verktyg (skapat i Java och C++), samt en testuppsÀttning baserad pÄ .
VĂ„rt verktyg Ă€r mĂ„ngsidigt â det möjliggör testning av praktiskt taget alla skrivbordsprogram, vilket gör det lĂ€mpligt för bĂ„de tunn klient och webbklient. Verktyget registrerar anvĂ€ndarens Ă„tgĂ€rder som startar tillĂ€mpningen "1C" i en skriptfil. Samtidigt registreras bilder av skrivbordets arbetsomrĂ„de â referenser. NĂ€r nya versioner av webbklienten kontrolleras, körs skripten utan anvĂ€ndarens medverkan. Vid avvikelser mellan skĂ€rmdumpen och referensen vid nĂ„got steg anses testet ha misslyckats, och en kvalitetspecialist genomför en utredning â om det Ă€r ett fel eller en planerad förĂ€ndring av systemets beteende. Vid planerat beteende ersĂ€tts referenserna automatiskt med nya.
Verktyget mÀter ocksÄ applikationernas prestanda med en noggrannhet pÄ 25 millisekunder. I vissa fall slussar vi delar av skriptet (till exempel upprepar vi bestÀllningsinmatningen flera gÄnger) för att analysera tidsdegradering över tid. Resultaten av alla mÀtningar loggas för analys.

VÄrt testverktyg och den testade applikationen
VĂ„rt verktyg och Selenium kompletterar varandra; till exempel kan Selenium ha svĂ„rt att spĂ„ra om en knapp pĂ„ en av skĂ€rmarna har Ă€ndrat sin plats â men vĂ„rt verktyg kommer att mĂ€rka det, eftersom det gör en pixel-för-pixel-jĂ€mförelse av skĂ€rmdumpen med referensen. Dessutom kan verktyget spĂ„ra problem med hantering av inmatning frĂ„n tangentbord eller mus, eftersom det just reproducerar dessa.
Tester pĂ„ bĂ„da verktygen (vĂ„rt och Selenium) kör typiska arbetsflöden frĂ„n vĂ„ra applikationer. Tester startas automatiskt efter den dagliga byggningen av plattformen "1C:Enterprise". Vid försĂ€mrad prestanda i skripten (jĂ€mfört med föregĂ„ende byggnad) genomför vi en utredning för att faststĂ€lla orsaken till nedgĂ„ngen. VĂ„r kriterium Ă€r enkel â den nya byggnaden ska inte vara lĂ„ngsammare Ă€n den föregĂ„ende.
För att utreda incidenter av prestandaförsĂ€mringar anvĂ€nder utvecklarna olika verktyg; frĂ€mst anvĂ€nds företaget . Loggfiler för problematiska operationer spelas in pĂ„ bĂ„de den tidigare och den nya versionen, och loggarna analyseras. I detta fall kan tiden för enskilda operationer (i millisekunder) vara mindre avgörande faktorer â i webblĂ€saren körs ibland tjĂ€nsteprocesser som skrĂ€pning, som kan pĂ„verka tiden för funktionsanrop och förvrĂ€nga bilden. Mer relevanta parametrar i det hĂ€r fallet Ă€r antalet utförda JavaScript-instruktioner och antalet atomĂ€ra operationer pĂ„ DOM, osv. Om antalet instruktioner/operationer i samma scenario i den nya versionen ökar â innebĂ€r det nĂ€stan alltid en försĂ€mring av prestandan som mĂ„ste Ă„tgĂ€rdas.
En annan anledning till prestandaförsÀmringen kan vara att Google Closure Compiler av nÄgon anledning inte kunde utföra inline-substitution av en funktion (till exempel för att funktionen Àr rekursiv eller virtuell). I detta fall försöker vi ÄtgÀrda situationen genom att skriva om koden.
webblÀsartillÀgg
Om den applikationslösning behöver funktionalitet som inte finns i JavaScript, anvÀnder vi webblÀsartillÀgg:
- för filhantering
- för kryptografi
- arbete med
VĂ„ra tillĂ€gg bestĂ„r av tvĂ„ delar. Den första delen Ă€r det som kallas ett webblĂ€sartillĂ€gg (som vanligtvis Ă€r skrivna i JavaScript för Chrome och Firefox) som interagerar med den andra delen - ett binĂ€rt tillĂ€gg som implementerar den funktionalitet vi behöver. Det bör nĂ€mnas att vi skriver tre versioner av binĂ€ra tillĂ€gg â för Windows, Linux och MacOS. Det binĂ€ra tillĂ€gget ingĂ„r i plattformen 1C:Enterprise och finns pĂ„ 1C-applikationsservern. Vid första anropet frĂ„n webbklienten laddas det ner till klientdatorn och installeras i webblĂ€saren.
Vid arbete i Safari anvÀnder vÄra tillÀgg NPAPI, medan de i Internet Explorer anvÀnder ActiveX-teknologin. stöder Ànnu inte tillÀgg, sÄ webbklienten fungerar med begrÀnsningar.
Vidare utveckling
En av uppgiftgrupperna för teamet som utvecklar webbklienten Àr att vidareutveckla funktionaliteten. Funktionaliteten i webbklienten ska vara identisk med funktionaliteten i den tunna klienten; all ny funktionalitet implementeras samtidigt bÄde i den tunna och i webbklienten.
Andra uppgifter Àr att utveckla arkitekturen, refaktorisera, samt förbÀttra prestanda och tillförlitlighet. Ett exempel pÄ detta Àr att vi rör oss mot en asynkron arbetsmodell. Delar av funktionaliteten i webbklienten Àr för nÀrvarande byggda pÄ en synkron interaktionsmodell med servern. Den asynkrona modellen blir nu mer relevant i webblÀsare (och inte bara i webblÀsare), och detta tvingar oss att modifiera webbklienten genom att ersÀtta synkrona anrop med asynkrona (och göra motsvarande refaktorisering av koden). Den gradvisa övergÄngen till den asynkrona modellen förklaras av behovet att stödja tidigare lanserade lösningar och deras gradvisa anpassning.
KĂ€lla: habr.com
