Az 1C: Vállalat egyik kellemes jellemzője, hogy a kezelőformák technológiájával készült alkalmazás, amely futtatható vékony (kliens) kliensként Windows, Linux, MacOS X rendszereken, valamint webklientként 5 böngésző alatt – Chrome, Internet Explorer, Firefox, Safari, Edge – mindez a program forráskódjának megváltoztatása nélkül. Sőt, a vékony kliensben és a böngészőben az alkalmazás külseje és működése gyakorlatilag azonos.
Találd meg a 10 különbséget (a kattintás alatt 2 kép):
A vékony kliens ablaka Linuxon:

Ugyanez az ablak a webklienseben (Chrome böngészőben):

Miért készítettük el a webklienst? Mondhatni, ezt a feladatot az idő állította elénk. Régóta szükségessé vált az interneten keresztüli munkavégzés az üzleti alkalmazások számára. Először lehetőséget adtunk az internetes munkavégzésre a vékony kliensünk számára (egyébként néhány versenytársunk itt megállt, míg mások, éppen ellenkezőleg, felhagytak a vékony kliens használatával, és csupán a webklienst valósították meg). Mi azonban azt a lehetőséget akarjuk nyújtani felhasználóinknak, hogy választhassák azt az ügyféltípust, amelyik a legjobban megfelel számukra.

Az internetes munkavégzés lehetőségének hozzáadása a vékony klienshez egy jelentős projekt volt, amely a kliens-szerver interakció teljes architektúrájának megváltoztatásával járt. A webkliens létrehozása pedig teljesen új projekt, amely a nulláról indult.
Lépjünk át a kitűzött feladatra: írjunk egy XDP mechanizmust SYN cookie-kkal.
Tehát a projekt követelményei: a webklientnek ugyanazt kell tennie, mint a vékony kliens, nevezetesen:
- Megjeleníteni a felhasználói felületet
- Végrehajtani a 1C nyelven írt kliens kódot
A felhasználói felület a 1C-ben vizuális szerkesztőben van leírva, de deklaratív módon, anélkül, hogy pixel pontosan elhelyezné a elemeket; körülbelül harminc különböző felületi elem típus van használatban – gombok, beviteli mezők (szöveges, numerikus, dátum/idő), listák, táblázatok, grafikonok stb.
A 1C nyelven írt kliens kód tartalmazhat szerverhívásokat, helyi erőforrásokkal (fájlok stb.) való munkát, nyomtatást és sok egyebet.
A vékony kliens (weben való használat során) és a webkliensek ugyanazt a webszolgáltatási készletet használják az 1C alkalmazásszerverrel való kommunikációhoz. A kliens megvalósítása természetesen eltérő – a vékony kliens C++-ban íródott, míg a webklient JavaScript-ben.
Egy kis történelem
A web client project was launched in 2006, with an average team of 5 people participating. At various stages of the project, developers were brought in to implement specific functionality (spreadsheet, diagrams, etc.); generally, these were the same developers who created this functionality in the thin client. This means that the developers rewrote on JavaScript the components they had previously created in C++.
From the very beginning, we rejected the idea of any automatic (even partial) conversion of C++ code from the thin client to JavaScript for the web client due to significant conceptual differences between the two languages; the web client was built on JavaScript from scratch.
In the early iterations of the project, the web client converted client code written in the 1C built-in language directly into JavaScript. The thin client operates differently—code in the 1C built-in language is compiled into bytecode, which is then interpreted on the client side. Eventually, the web client also began to do the same—firstly, this resulted in a performance gain; secondly, it allowed for the unification of the architecture of the thin and web clients.
The first version of the 1C:Enterprise platform with web client support was released in 2009. At that time, the web client supported 2 browsers – Internet Explorer and Firefox. Initial plans included support for Opera, but due to insurmountable problems at that time with the application closure handlers in Opera (it was impossible to reliably track when the application was closing and perform the disconnection procedure from the 1C application server at that moment), we had to abandon those plans.
Project Structure
In total, the 1C:Enterprise platform has 4 projects written in JavaScript:
- WebTools – general libraries used by other projects (we also include here ).
- Control Element (implemented in both JavaScript in the thin client and in the web client)
- Control Element (implemented in both JavaScript in the thin client and in the web client)
- Web kliens
The structure of each project resembles that of Java projects (or .NET projects – whichever is closer to you); we have namespaces, and each namespace resides in a separate folder. Inside the folder, there are files and classes of the namespace. The web client project contains about 1000 files.
Structurally, the web client is broadly divided into the following subsystems:
- Kezelt ügyfélalkalmazás felülete
- Az alkalmazás általános felülete (rendszermenük, panelek)
- Kezelt űrlapok felülete, amely körülbelül 30 vezérlőelemet tartalmaz (gombok, különböző típusú beviteli mezők – szöveges, numerikus, dátum/idő stb., táblázatok, listák, grafikonok stb.)
- Objektummodell, amely a fejlesztők számára elérhető a kliensen (több mint 400 típus: a kezelt interfész objektummodellje, adatmegjelenítési beállítások, feltételes formázás stb.)
- Beépített nyelv értelmezője 1C-hez
- Böngészőbővítmények (a JavaScript-ben nem támogatott funkciókhoz használják)
- Munka kriptográfiával
- Munka a fájlokkal
- Külső komponensek technológiája, amely lehetővé teszi ezek használatát mind a vékony, mind a webkliensben
Fejlesztési jellemzők
Az összes fent leírt megvalósítása JavaScript-ben nem egyszerű feladat. Valószínűleg a 1C webkliens az egyik legnagyobb kliensoldali alkalmazás, amelyet JavaScript-ben írtak – körülbelül 450.000 sor. A webkliens kódjában aktívan alkalmazzuk az objektumorientált megközelítést, amely megkönnyíti a munka végzését egy ilyen nagy projekttel.
A kliens kód méretének minimalizálása érdekében kezdetben saját elrejtőnket használtuk, és a 8.3.6 platformverziótól (2014 október) kezdve a használjuk. A használat hatása számokban – a webkliens keretrendszere az elrejtés után:
- Saját elrejtőnk – 1556 kB
- Google Closure Compiler – 1073 kB
A Google Closure Compiler használata lehetővé tette számunkra, hogy 30%-kal növeljük a webkliens teljesítményét a saját elrejtőnkhöz képest. Ezen kívül 15-25%-kal (böngészőtől függően) csökkent a program által használt memória mennyisége.
A Google Closure Compiler nagyon jól működik az objektumorientált kódokkal, ezért a webkliens esetében a hatékonysága maximális. A Closure Compiler több jót tesz számunkra:
- Statikus típusellenőrzés a projekt összeállításának fázisában (azt biztosítva, hogy kódunkat JSDoc annotációkkal fedi le). Ennek eredményeként egy statikus típussal rendelkező rendszer áll elő, amely nagyon közel áll a C++-hoz. Ez segít a projekt fordításának fázisában nagy százalékú hibát kiszűrni.
- A kód méretének csökkentése rejtés révén
- Számos optimalizálás a végrehajtott kód esetében, például:
- inline helyettesítések funkciók. A JavaScript-ben a funkciók hívása meglehetősen költséges művelet, és az inline helyettesítések gyakran használt kisebb metódusok esetében jelentősen felgyorsítják a kód működését.
- Konstansok számlálása a fordítási lépésben. Ha a kifejezés egy konstansra támaszkodik, akkor a konstans tényleges értéke kerül beillesztésre.
Webkliensek fejlesztési környezeteként a WebStorm-ot használjuk.
A kód elemzésére használjuk , ahová integráljuk a statikus kódellenőrzőket. Az elemzők segítségével nyomon követjük a kódminőség romlását JavaScript-ben, és igyekszünk elkerülni azt.

Milyen feladatokat oldottunk/oldunk meg
A projekt megvalósítása során számos érdekes feladattal szembesültünk, amelyeket meg kellett oldanunk.
Adatcsere a szerverrel és az ablakok között
Vannak olyan helyzetek, amikor a forráskód obfuszkálása akadályozhatja a rendszer működését. A végrehajtásra váró kódban az obfuszkálás miatt a funkciók és paraméterek nevei eltérhetnek azoktól, amelyeket a mi végrehajtott kódunk elvár. Az külső kód számunkra a következő:
- Kód, amely a szervertől érkezik adatszerkezetek formájában
- Kód egy másik alkalmazásablakból
Az obfuszkálás elkerülése érdekében a szerverrel való kommunikáció során a @expose címkét használjuk:
/**
* @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;
}Az obfuszkálás elkerülése érdekében pedig a másik ablakokkal való kommunikációnál úgynevezett exportált interfészeket (interfészek, amelyek minden metódusa exportált) alkalmazunk.
/**
* Экспортируемый интерфейс контрола 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 (){}Használatban volt a Virtual DOM, mielőtt elterjedt volna)
Mint minden olyan fejlesztő, aki összetett web UI-val foglalkozik, gyorsan rájöttünk, hogy a DOM nem ideális a dinamikus felhasználói interfész kezelésére. Szinte azonnal megvalósítottuk a Virtual DOM analógját a UI-val való munka optimalizálására. Az események feldolgozása során az összes DOM-módosítást a memóriában tároljuk, és csak az összes művelet befejezése után alkalmazzuk az összegyűjtött változásokat a DOM-fának.
A webkliensek teljesítményének optimalizálása
Annak érdekében, hogy a webkliensek gyorsabban működjenek, a böngésző beépített lehetőségeit (CSS, stb.) maximálisan kihasználjuk. Így az alkalmazás minden űrlapján elhelyezkedő parancssor kizárólag a böngésző eszközeivel, dinamikus CSS-alapú megjelenítéssel készül.

Tesztelés
Funkcionális teszteléshez és teljesítmény teszteléshez saját fejlesztésű eszközt használunk (Java és C++ nyelven), valamint egy tesztcsomagot, amely alapja .
Eszközünk univerzális – szinte bármilyen asztali program tesztelésére alkalmas, ezért használható mind a vékony kliens, mind a webkliens tesztelésére. Az eszköz rögzíti a felhasználó cselekedeteit, aki elindította az „1C” alkalmazást, egy forgatókönyv fájlba. Eközben a képernyő munkaterülete képeinek – referencia képek – rögzítése is megtörténik. Az új verziók webkliensének ellenőrzésekor a forgatókönyvek felhasználói részvétel nélkül játszódnak le. Ha a képernyő kép és a referencia bármely lépésnél eltér, a teszt megbukik, ezt követően a minőségellenőr vizsgálatot folytat – ez hiba vagy a rendszer viselkedésének tervezett megváltozása. Tervezett viselkedés esetén a referenciák automatikusan újakkal helyettesítődnek.
Az eszköz emellett az alkalmazások teljesítményét 25 milliszekundum pontossággal méri. Bizonyos esetekben a forgatókönyv részeit ciklussá tesszük (például több alkalommal megismételjük a rendelés leadását) a végrehajtási idő degradációjának elemzéséhez. Minden mért eredmény naplózásra kerül az elemzéshez.

Az eszközünk tesztelésére és a tesztelt alkalmazásra
Eszközünk és a Selenium kiegészítik egymást; például ha egy gomb helye megváltozik egy képernyőn – a Selenium ezt nem biztos, hogy nyomon követi, de az eszközünk észlelni fogja, mivel pixelről pixelre összehasonlítja a képernyőképet a referencia képpel. Az eszköz képes az egér vagy billentyűzet bemenetének feldolgozásával kapcsolatos problémákat is észlelni, mivel ezeket idézőjelben ismétli.
Mindkét eszközön (a miénken és a Seleniumon) a tipikus munkafolyamat forgatókönyveit futtatják a alkalmazásainkból. A tesztek automatikusan elindulnak az „1C:Enterprise” platform napi összeállítása után. Ha a forgatókönyvek végrehajtási sebessége lelassul (az előző összeállításhoz képest), vizsgálatot végzünk és megszüntetjük a lassulás okát. Egyszerű kritériumunk van – az új összeállításnak nem szabad lassabban működnie, mint az előző.
A lassulási incidensek vizsgálatához a fejlesztők különböző eszközöket használnak; javarészt a vállalat gyártása . A problémás művelet végrehajtásának naplózása megtörténik az előző és az új verzióban, majd a naplókat elemzik. Ebben az esetben az egyes műveletek végrehajtásának időtartama (ezredmásodpercben) nem mindig döntő tényező lehet – a böngészőben időnként háttérfolyamatok indulnak, mint például a szemetes ürítése, amelyek befolyásolhatják a funkciók végrehajtási idejét és torzíthatják a képet. A relevánsabb paraméterek ebben az esetben a végrehajtott JavaScript utasítások száma, a DOM-ra vonatkozó atomikus műveletek száma stb. Ha az új verzióban ugyanazon forgatókönyvben az utasítások/műveletek száma megnövekedett – ez szinte mindig a teljesítmény csökkenését jelenti, amelyet ki kell javítani.
A teljesítmény csökkenésének egyik oka lehet az is, hogy a Google Closure Compiler valamilyen okból nem tudta elvégezni a függvény inline-helyettesítését (például mert a függvény rekurzív vagy virtuális). Ebben az esetben próbáljuk javítani a helyzetet a forrást kód átírásával.
Böngészőbővítmények
Abban az esetben, ha az alkalmazási megoldásnak olyan funkcióra van szüksége, ami nincs a JavaScriptben, böngészőbővítményeket használunk:
- fájlok kezeléséhez
- kriptográfiához
- munkája
Böngészőbővítményeink két részből állnak. Az első része az, amit böngészőbővítménynek hívnak (jellemzően JavaScriptben írt bővítmények Chrome és Firefox számára), amelyek interakcióba lépnek a második részzel — egy bináris bővítménnyel, amely a szükséges funkciót valósítja meg. Meg kell említeni, hogy 3 verziót írunk a bináris bővítményekből – Windows, Linux és MacOS alatt. A bináris bővítmény a 1C: Vállalkozás platform részét képezi, és a 1C alkalmazásszerverén található. Az első híváskor a webklienből a kliens számítógépre töltődik le, és települ a böngészőbe.
Safari használatakor a bővítményeink NPAPI-t használnak, Internet Explorer esetén pedig az ActiveX technológiát. jelenleg nem támogatja a bővítményeket, ezért a webklien korlátozásokkal működik.
További fejlesztés
A fejlesztőcsapat feladatainak egy csoportja a webkliens funkcióinak további fejlesztése. A webkliens funkcióinak meg kell egyeznie a vékony kliensével, minden új funkciót egyszerre kell megvalósítani mind a vékony, mind a webkliensben.
A további feladatok közé tartozik az architektúra fejlesztése, a refaktorálás, a teljesítmény és megbízhatóság növelése. Például az egyik irány a szinkron munkamódról a aszinkron munkamódra való átállás. Jelenleg a webkliens egy része szinkron modellekre épül a kiszolgálóval való kapcsolattartás során. Az aszinkron modell mostanában egyre relevánsabbá válik a böngészőkben (és nem csak ott), ami arra kényszerít minket, hogy módosítsuk a webklienset azáltal, hogy a szinkron hívásokat aszinkron hívásokra cseréljük (és ennek megfelelően refaktoráljuk a kódot). Az aszinkron modellre való fokozatos áttérés szükségességét az adja, hogy támogassuk a már megjelent megoldásokat és fokozatosan alakítsuk azokat.
Forrás: habr.com
