Informacje o kliencie internetowym 1C

Jedną z ciekawych cech technologii 1C:Enterprise jest to, że rozwiązanie aplikacyjne opracowane przy użyciu technologii zarządzanych formularzy można uruchomić zarówno w cienkim (wykonywalnym) kliencie dla systemów Windows, Linux, MacOS X, jak i jako klient sieciowy dla 5 przeglądarek - Chrome, Internet Explorer, Firefox, Safari, Edge, a wszystko to bez zmiany kodu źródłowego aplikacji. Co więcej, zewnętrznie aplikacja w cienkim kliencie i w przeglądarce działa i wygląda niemal identycznie.
Znajdź 10 różnic (2 obrazki pod wycięciem):

Okno cienkiego klienta w systemie Linux:

Informacje o kliencie internetowym 1C

To samo okno w kliencie WWW (w przeglądarce Chrome):

Informacje o kliencie internetowym 1C

Dlaczego stworzyliśmy klienta internetowego? Ujmując to nieco patetycznie, czas postawił przed nami takie zadanie. Praca przez Internet od dawna jest warunkiem wstępnym zastosowań biznesowych. Najpierw dodaliśmy możliwość pracy przez Internet dla naszego cienkiego klienta (nawiasem mówiąc, niektórzy z naszych konkurentów na tym poprzestali, inni wręcz przeciwnie, porzucili cienkiego klienta i ograniczyli się do wdrożenia klienta sieciowego). Postanowiliśmy dać naszym użytkownikom możliwość wyboru najbardziej odpowiadającej im opcji klienta.

Informacje o kliencie internetowym 1C

Dodanie możliwości sieciowych do cienkiego klienta było dużym projektem wymagającym całkowitej zmiany architektury klient-serwer. Stworzenie klienta WWW to zupełnie nowy projekt, zaczynany od zera.

Stwierdzenie problemu

Zatem wymagania projektu: klient sieciowy musi robić to samo, co cienki klient, a mianowicie:

  1. Wyświetl interfejs użytkownika
  2. Wykonaj kod klienta napisany w języku 1C

Interfejs użytkownika w 1C jest opisany w edytorze wizualnym, ale deklaratywnie, bez układu elementów piksel po pikselu; Wykorzystuje się około trzech tuzinów typów elementów interfejsu - przyciski, pola wejściowe (tekstowe, numeryczne, data/godzina), listy, tabele, wykresy itp.

Kod klienta w języku 1C może zawierać wywołania serwera, pracę z zasobami lokalnymi (pliki itp.), drukowanie i wiele więcej.

Zarówno cienki klient (podczas pracy przez Internet), jak i klient sieciowy korzystają z tego samego zestawu usług internetowych do komunikacji z serwerem aplikacji 1C. Implementacje klientów są oczywiście różne – cienki klient jest napisany w C++, klient sieciowy jest napisany w JavaScript.

Trochę historii

Projekt klienta internetowego rozpoczął się w 2006 roku, a zespół składał się (średnio) z 5 osób. Na niektórych etapach projektu zaangażowani byli programiści w celu wdrożenia określonej funkcjonalności (dokument arkusza kalkulacyjnego, diagramy itp.); z reguły byli to ci sami programiści, którzy wykonali tę funkcjonalność w cienkim kliencie. Te. programiści ponownie napisali komponenty w JavaScript, które wcześniej utworzyli w C++.

Od samego początku odrzucaliśmy pomysł jakiejkolwiek automatycznej (nawet częściowej) konwersji kodu cienkiego klienta C++ na klienta WWW JavaScript ze względu na duże różnice koncepcyjne pomiędzy obydwoma językami; klient WWW został napisany od podstaw w JavaScript.

W pierwszych iteracjach projektu klient sieciowy konwertował kod klienta we wbudowanym języku 1C bezpośrednio na JavaScript. Cienki klient działa inaczej - kod we wbudowanym języku 1C jest kompilowany do kodu bajtowego, a następnie ten kod bajtowy jest interpretowany na kliencie. Następnie klient sieciowy zaczął robić to samo - po pierwsze dał wzrost wydajności, a po drugie umożliwił ujednolicenie architektury klientów cienkich i internetowych.

Pierwsza wersja platformy 1C:Enterprise z obsługą klienta WWW została wydana w 2009 roku. Klient sieciowy obsługiwał wówczas 2 przeglądarki – Internet Explorer i Firefox. W pierwotnych planach była obsługa Opery, jednak ze względu na nie do pokonania problemy z obsługą zamykania aplikacji w Operze (nie było możliwości wyśledzenia ze 100% pewnością, że aplikacja się zamyka, i na ten moment przeprowadzić procedurę rozłączenia z serwer aplikacji 1C) z tych planów trzeba było porzucić.

Struktura projektu

Łącznie na platformie 1C:Enterprise znajdują się 4 projekty napisane w JavaScript:

  1. WebTools – biblioteki współdzielone używane przez inne projekty (zawieramy także Biblioteka zamknięć Google).
  2. Element kontrolny Sformatowany dokument (zaimplementowane w JavaScript zarówno w cienkim kliencie, jak i kliencie internetowym)
  3. Element kontrolny Planista (zaimplementowane w JavaScript zarówno w cienkim kliencie, jak i kliencie internetowym)
  4. Klient sieciowy

Struktura każdego projektu przypomina strukturę projektów Java (lub projektów .NET – w zależności od tego, co jest bliższe); Mamy przestrzenie nazw i każda przestrzeń nazw znajduje się w osobnym folderze. Wewnątrz folderu znajdują się pliki i klasy przestrzeni nazw. W projekcie klienta WWW znajduje się około 1000 plików.

Strukturalnie klient WWW jest w dużej mierze podzielony na następujące podsystemy:

  • Zarządzany interfejs aplikacji klienckiej
    • Ogólny interfejs aplikacji (menu systemowe, panele)
    • Interfejs zarządzanych formularzy, zawierający m.in. około 30 kontrolek (przyciski, różnego rodzaju pola wejściowe – tekstowe, numeryczne, data/godzina itp., tabele, listy, wykresy itp.)

  • Model obiektowy dostępny dla programistów na kliencie (w sumie ponad 400 typów: model obiektowy interfejsu zarządzanego, ustawienia układu danych, stylizacja warunkowa itp.)
  • Tłumacz wbudowanego języka 1C
  • Rozszerzenia przeglądarki (używane w przypadku funkcjonalności nieobsługiwanych w JavaScript)
    • Praca z kryptografią
    • Praca z plikami
    • Technologia komponentów zewnętrznych, pozwalająca na wykorzystanie ich zarówno w klientach cienkich, jak i webowych

Funkcje rozwojowe

Implementacja wszystkich powyższych w JavaScript nie jest łatwa. Być może klient sieciowy 1C jest jedną z największych aplikacji po stronie klienta napisanych w JavaScript - około 450.000 XNUMX linii. Aktywnie wykorzystujemy podejście obiektowe w kodzie klienta WWW, co ułatwia pracę z tak dużym projektem.

Aby zminimalizować rozmiar kodu klienta, najpierw użyliśmy własnego obfuscatora, a począwszy od wersji platformy 8.3.6 (październik 2014) zaczęliśmy używać Kompilator zamknięć Google. Efekt użycia w liczbach – wielkość frameworku klienta WWW po zaciemnieniu:

  • Własny obfuscator – 1556 kb
  • Kompilator zamknięcia Google – 1073 kb

Korzystanie z kompilatora Google Closure Compiler pomogło nam poprawić wydajność klienta internetowego o 30% w porównaniu z naszym własnym obfuscatorem. Ponadto ilość pamięci zużywanej przez aplikację spadła o 15-25% (w zależności od przeglądarki).

Google Closure Compiler bardzo dobrze współpracuje z kodem obiektowym, dzięki czemu jego wydajność dla klienta WWW jest jak najwyższa. Closure Compiler robi dla nas kilka dobrych rzeczy:

  • Statyczne sprawdzanie typów na etapie budowy projektu (gwarantuje, że kod zostanie pokryty adnotacjami JSDoc). Rezultatem jest pisanie statyczne, bardzo zbliżone do poziomu pisania w C++. Pozwala to wyłapać dość duży odsetek błędów już na etapie kompilacji projektu.
  • Zmniejszanie rozmiaru kodu poprzez zaciemnianie
  • Szereg optymalizacji wykonywanego kodu, np. takich jak:
    • podstawienia funkcji wbudowanych. Wywołanie funkcji w JavaScript jest operacją dość kosztowną, a podstawienia inline często używanych małych metod znacznie przyspieszają działanie kodu.
    • Zliczanie stałych w czasie kompilacji. Jeśli wyrażenie zależy od stałej, zostanie do niego podstawiona rzeczywista wartość stałej

Używamy WebStorm jako naszego środowiska programistycznego klienta internetowego.

Do analizy kodu używamy SoundQube, gdzie integrujemy statyczne analizatory kodu. Za pomocą analizatorów monitorujemy degradację jakości kodu źródłowego JavaScript i staramy się temu zapobiegać.

Informacje o kliencie internetowym 1C

Jakie problemy rozwiązaliśmy/rozwiązujemy?

W trakcie realizacji projektu napotkaliśmy szereg ciekawych problemów, które musieliśmy rozwiązać.

Wymieniaj dane z serwerem i pomiędzy oknami

Zdarzają się sytuacje, w których zaciemnienie kodu źródłowego może zakłócić działanie systemu. Kod zewnętrzny w stosunku do kodu wykonywalnego klienta WWW, ze względu na zaciemnianie, może mieć nazwy funkcji i parametrów różniące się od tych, których oczekuje nasz kod wykonywalny. Kod zewnętrzny dla nas to:

  • Kod pochodzący z serwera w postaci struktur danych
  • Kod innego okna aplikacji

Aby uniknąć zaciemniania podczas interakcji z serwerem, używamy tagu @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;
}

Aby uniknąć zaciemniania podczas interakcji z innymi oknami, używamy tak zwanych eksportowanych interfejsów (interfejsów, w których eksportowane są wszystkie metody).

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

Korzystaliśmy z wirtualnego DOM, zanim stał się on głównym nurtem)

Podobnie jak wszyscy programiści zajmujący się złożonymi interfejsami WWW, szybko zdaliśmy sobie sprawę, że DOM słabo nadaje się do pracy z dynamicznymi interfejsami użytkownika. Niemal natychmiast wdrożono analogię Virtual DOM, aby zoptymalizować pracę z interfejsem użytkownika. Podczas przetwarzania zdarzeń wszystkie zmiany DOM są przechowywane w pamięci i dopiero po zakończeniu wszystkich operacji skumulowane zmiany są stosowane w drzewie DOM.

Optymalizacja klienta internetowego

Aby nasz klient WWW działał szybciej, staramy się maksymalnie wykorzystać standardowe możliwości przeglądarki (CSS itp.). Tym samym panel poleceń formularza (znajdujący się niemal w każdej formie aplikacji) renderowany jest wyłącznie przy użyciu narzędzi przeglądarki, z wykorzystaniem dynamicznego układu opartego na CSS.

Informacje o kliencie internetowym 1C

Testowanie

Do testów funkcjonalnych i wydajnościowych wykorzystujemy autorskie narzędzie (napisane w języku Java i C++) oraz pakiet testów zbudowany na bazie Selen.

Nasze narzędzie jest uniwersalne - pozwala przetestować niemal każdy program okienkowy, dlatego nadaje się do testowania zarówno cienkiego klienta, jak i klienta WWW. Narzędzie rejestruje działania użytkownika, który uruchomił rozwiązanie aplikacyjne 1C, w pliku skryptu. Jednocześnie rejestrowane są obrazy obszaru roboczego ekranu – standardów. Podczas monitorowania nowych wersji klienta WWW skrypty są odtwarzane bez udziału użytkownika. W przypadku, gdy zrzut ekranu na którymkolwiek etapie nie odpowiada zrzutowi ekranu, test uznaje się za nieudany, po czym specjalista ds. jakości przeprowadza dochodzenie w celu ustalenia, czy jest to błąd, czy planowana zmiana w zachowaniu systemu. W przypadku zachowań planowych standardy są automatycznie zastępowane nowymi.

Narzędzie mierzy także wydajność aplikacji z dokładnością do 25 milisekund. W niektórych przypadkach zapętlamy części skryptu (na przykład kilkukrotnie powtarzając wprowadzanie zamówienia), aby przeanalizować degradację czasu wykonania w czasie. Wyniki wszystkich pomiarów zapisywane są w dzienniku w celu analizy.

Informacje o kliencie internetowym 1C
Nasze narzędzie testowe i aplikacja w trakcie testowania

Nasze narzędzie i Selenium uzupełniają się; na przykład, jeśli jakiś przycisk na jednym z ekranów zmienił swoją lokalizację, Selenium może tego nie wyśledzić, ale nasze narzędzie to zauważy, ponieważ dokonuje porównania zrzutu ekranu piksel po pikselu ze standardem. Narzędzie jest również w stanie śledzić problemy z przetwarzaniem danych wejściowych z klawiatury lub myszy, ponieważ dokładnie to odtwarza.

Testy na obu narzędziach (naszym i Selenium) uruchamiają typowe scenariusze pracy z naszych rozwiązań aplikacyjnych. Testy są uruchamiane automatycznie po codziennej kompilacji platformy 1C:Enterprise. Jeśli skrypty są wolniejsze (w porównaniu z poprzednią wersją), badamy i usuwamy przyczynę spowolnienia. Nasze kryterium jest proste – nowy build powinien działać nie wolniej niż poprzedni.

Programiści używają różnych narzędzi do badania incydentów spowolnienia; głównie używane Wersja Dynatrace AJAX produkcja firmy DynaTrace. Rejestrowane są dzienniki wykonywania problematycznych operacji w poprzednich i nowych kompilacjach, a następnie dzienniki są analizowane. Jednocześnie czas wykonania pojedynczych operacji (w milisekundach) może nie być czynnikiem decydującym – w przeglądarce okresowo uruchamiane są procesy usługowe takie jak odśmiecanie, mogą nakładać się na czas wykonania funkcji i zniekształcać obraz. Bardziej odpowiednimi parametrami w tym przypadku byłaby liczba wykonanych instrukcji JavaScript, liczba operacji atomowych na DOM itp. Jeśli w nowej wersji liczba instrukcji/operacji w tym samym skrypcie wzrosła, prawie zawsze oznacza to spadek wydajności, który należy skorygować.

Ponadto jedną z przyczyn spadku wydajności może być to, że Google Closure Compiler z jakiegoś powodu nie był w stanie wykonać wbudowanego podstawienia funkcji (na przykład dlatego, że funkcja jest rekurencyjna lub wirtualna). W takim przypadku staramy się naprawić sytuację, przepisując kod źródłowy.

Rozszerzenia przeglądarki

Gdy rozwiązanie aplikacyjne wymaga funkcjonalności niedostępnej w JavaScript, korzystamy z rozszerzeń przeglądarki:

Nasze rozszerzenia składają się z dwóch części. Pierwsza część to tak zwane rozszerzenie przeglądarki (zwykle rozszerzenia dla Chrome i Firefox napisane w JavaScript), które współdziałają z drugą częścią - rozszerzeniem binarnym, które implementuje potrzebną nam funkcjonalność. Należy wspomnieć, że piszemy 3 wersje rozszerzeń binarnych - dla Windows, Linux i MacOS. Rozszerzenie binarne jest dostarczane jako część platformy 1C:Enterprise i znajduje się na serwerze aplikacji 1C. Przy pierwszym wywołaniu z klienta WWW jest on pobierany na komputer kliencki i instalowany w przeglądarce.

Podczas działania w przeglądarce Safari nasze rozszerzenia korzystają z NPAPI, natomiast w przeglądarce Internet Explorer korzystają z technologii ActiveX. Microsoft Edge nie obsługuje jeszcze rozszerzeń, więc klient sieciowy w nim działa z ograniczeniami.

Dalszy rozwój

Jednym z zadań zespołu programistów klienta WWW jest dalszy rozwój funkcjonalności. Funkcjonalność klienta WWW powinna być identyczna z funkcjonalnością cienkiego klienta; wszystkie nowe funkcje są wdrażane jednocześnie w kliencie cienkim i internetowym.

Inne zadania obejmują rozwój architektury, refaktoryzację, poprawę wydajności i niezawodności. Przykładowo jednym z kierunków jest dalszy ruch w kierunku asynchronicznego modelu pracy. Część funkcjonalności klienta WWW jest obecnie zbudowana w oparciu o synchroniczny model interakcji z serwerem. Model asynchroniczny staje się obecnie coraz bardziej odpowiedni w przeglądarkach (i nie tylko w przeglądarkach), co zmusza nas do modyfikacji klienta WWW poprzez zastąpienie wywołań synchronicznych wywołaniami asynchronicznymi (i odpowiednią refaktoryzację kodu). Stopniowe przejście do modelu asynchronicznego tłumaczone jest koniecznością wspierania wydawanych rozwiązań i ich stopniową adaptacją.

Źródło: www.habr.com

Dodaj komentarz