À propos du client Web 1C

L'une des fonctionnalités intéressantes de la technologie 1C:Enterprise est que la solution d'application, développée à l'aide de la technologie des formulaires gérés, peut être lancée à la fois dans un client léger (exécutable) pour Windows, Linux, MacOS X et en tant que client Web pour 5 navigateurs - Chrome, Internet Explorer, Firefox, Safari, Edge, et tout cela sans changer le code source de l'application. De plus, extérieurement, l'application dans le client léger et dans le navigateur fonctionne et semble presque identique.
Trouvez 10 différences (2 images sous la coupe) :

Fenêtre client léger sous Linux :

À propos du client Web 1C

La même fenêtre dans le client web (dans le navigateur Chrome) :

À propos du client Web 1C

Pourquoi avons-nous créé un client Web ? Pour le dire de manière quelque peu pathétique, le temps nous a confié une telle tâche. Travailler sur Internet est depuis longtemps une condition préalable aux applications professionnelles. Tout d'abord, nous avons ajouté la possibilité de travailler via Internet pour notre client léger (certains de nos concurrents se sont d'ailleurs arrêtés là ; d'autres, au contraire, ont abandonné le client léger et se sont limités à la mise en œuvre d'un client web). Nous avons décidé de donner à nos utilisateurs la possibilité de choisir l'option client qui leur convient le mieux.

À propos du client Web 1C

L'ajout de fonctionnalités Web au client léger était un projet de grande envergure avec un changement complet dans l'architecture client-serveur. La création d'un client Web est un projet complètement nouveau, qui part de zéro.

Formulation du problème

Donc, les exigences du projet : le client web doit faire la même chose que le client léger, à savoir :

  1. Afficher l'interface utilisateur
  2. Exécuter le code client écrit en langage 1C

L'interface utilisateur de 1C est décrite dans un éditeur visuel, mais de manière déclarative, sans disposition des éléments pixel par pixel ; Environ trois douzaines de types d'éléments d'interface sont utilisés : boutons, champs de saisie (texte, numérique, date/heure), listes, tableaux, graphiques, etc.

Le code client en langage 1C peut contenir des appels de serveur, l'utilisation de ressources locales (fichiers, etc.), l'impression et bien plus encore.

Le client léger (lorsqu'il travaille via le Web) et le client Web utilisent le même ensemble de services Web pour communiquer avec le serveur d'applications 1C. Les implémentations client, bien sûr, sont différentes : le client léger est écrit en C++, le client Web est écrit en JavaScript.

Un peu d'histoire

Le projet client web a démarré en 2006, avec une équipe de (en moyenne) 5 personnes. A certaines étapes du projet, des développeurs ont été impliqués pour mettre en œuvre des fonctionnalités spécifiques (tableur, diagrammes, etc.) ; en règle générale, ce sont les mêmes développeurs qui ont réalisé cette fonctionnalité dans le client léger. Ceux. les développeurs ont réécrit en JavaScript les composants qu'ils avaient précédemment créés en C++.

Dès le début, nous avons rejeté l'idée de toute conversion automatique (même partielle) du code client léger C++ en client web JavaScript en raison des fortes différences conceptuelles entre les deux langages ; le client Web a été écrit en JavaScript à partir de zéro.

Dans les premières itérations du projet, le client Web a converti le code client du langage 1C intégré directement en JavaScript. Le client léger agit différemment - le code du langage 1C intégré est compilé en bytecode, puis ce bytecode est interprété sur le client. Par la suite, le client web a commencé à faire de même : d'une part, il a apporté un gain de performances, et d'autre part, il a permis d'unifier l'architecture des clients légers et web.

La première version de la plateforme 1C:Enterprise avec prise en charge du client Web a été publiée en 2009. Le client Web à cette époque prenait en charge 2 navigateurs : Internet Explorer et Firefox. Les plans originaux incluaient la prise en charge d'Opera, mais en raison de problèmes insurmontables à l'époque avec les gestionnaires de fermeture d'application dans Opera (il n'était pas possible de suivre avec une certitude à 100 % la fermeture de l'application et d'effectuer à ce moment-là la procédure de déconnexion de le serveur d'applications 1C) de ces plans ont dû être abandonnés.

Structure du projet

Au total, la plateforme 1C:Enterprise compte 4 projets écrits en JavaScript :

  1. WebTools – bibliothèques partagées utilisées par d’autres projets (nous incluons également Bibliothèque de fermeture Google).
  2. Élément de contrôle Document formaté (implémenté en JavaScript dans le client léger et le client Web)
  3. Élément de contrôle Planificateur (implémenté en JavaScript dans le client léger et le client Web)
  4. Client Web

La structure de chaque projet ressemble à la structure des projets Java (ou des projets .NET - selon celui qui est le plus proche) ; Nous avons des espaces de noms et chaque espace de noms se trouve dans un dossier séparé. À l’intérieur du dossier se trouvent des fichiers et des classes d’espace de noms. Il y a environ 1000 XNUMX fichiers dans le projet client Web.

Structurellement, le client Web est largement divisé en sous-systèmes suivants :

  • Interface d'application client gérée
    • Interface générale de l'application (menus système, panneaux)
    • Interface de formulaires gérés, comprenant entre autres une trentaine de champs (boutons, différents types de champs de saisie - texte, numérique, date/heure, etc., tableaux, listes, graphiques, etc.)

  • Modèle objet disponible pour les développeurs sur le client (plus de 400 types au total : modèle objet d'interface gérée, paramètres de disposition des données, style conditionnel, etc.)
  • Interprète du langage 1C intégré
  • Extensions de navigateur (utilisées pour les fonctionnalités non prises en charge en JavaScript)
    • Travailler avec la cryptographie
    • Travailler avec des fichiers
    • Technologie des composants externes, permettant leur utilisation aussi bien dans les clients légers que web

Fonctionnalités de développement

Implémenter tout ce qui précède en JavaScript n’est pas facile. Le client Web 1C est peut-être l'une des plus grandes applications côté client écrites en JavaScript - environ 450.000 XNUMX lignes. Nous utilisons activement une approche orientée objet dans le code du client Web, ce qui simplifie le travail avec un projet d'une telle envergure.

Pour minimiser la taille du code client, nous avons d'abord utilisé notre propre obfuscateur, et à partir de la version 8.3.6 de la plateforme (octobre 2014), nous avons commencé à utiliser Compilateur de fermeture Google. L'effet de l'utilisation en chiffres – la taille du framework client Web après obscurcissement :

  • Propre obfuscateur – 1556 Ko
  • Compilateur de fermeture Google – 1073 Ko

L'utilisation de Google Closure Compiler nous a aidé à améliorer les performances du client Web de 30 % par rapport à notre propre obfuscateur. De plus, la quantité de mémoire consommée par l'application a diminué de 15 à 25 % (selon le navigateur).

Google Closure Compiler fonctionne très bien avec le code orienté objet, son efficacité pour le client Web est donc aussi élevée que possible. Closure Compiler fait quelques bonnes choses pour nous :

  • Vérification de type statique au stade de la construction du projet (garantit que nous couvrons le code avec des annotations JSDoc). Le résultat est un typage statique, très proche en niveau du typage en C++. Cela permet de détecter un pourcentage assez important d'erreurs au stade de la compilation du projet.
  • Réduire la taille du code grâce à l'obscurcissement
  • Un certain nombre d'optimisations du code exécuté, par exemple, telles que :
    • substitutions de fonctions en ligne. L'appel d'une fonction en JavaScript est une opération assez coûteuse, et les substitutions en ligne de petites méthodes fréquemment utilisées accélèrent considérablement le code.
    • Compter les constantes au moment de la compilation. Si une expression dépend d'une constante, la valeur réelle de la constante y sera substituée

Nous utilisons WebStorm comme environnement de développement de client Web.

Pour l'analyse du code, nous utilisons SonarQube, où nous intégrons des analyseurs de code statiques. À l'aide d'analyseurs, nous surveillons la dégradation de la qualité du code source JavaScript et essayons de l'empêcher.

À propos du client Web 1C

Quels problèmes avons-nous résolus/sommes-nous résolus ?

Lors de la mise en œuvre du projet, nous avons rencontré un certain nombre de problèmes intéressants que nous avons dû résoudre.

Échanger des données avec le serveur et entre Windows

Il existe des situations dans lesquelles l'obscurcissement du code source peut interférer avec le fonctionnement du système. Le code externe au code exécutable du client Web, en raison de l'obscurcissement, peut avoir des noms de fonctions et de paramètres qui diffèrent de ceux attendus par notre code exécutable. Le code externe pour nous est :

  • Code provenant du serveur sous forme de structures de données
  • Code pour une autre fenêtre d'application

Pour éviter toute obscurcissement lors de l'interaction avec le serveur, nous utilisons la balise @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;
}

Et pour éviter toute confusion lors de l'interaction avec d'autres fenêtres, nous utilisons des interfaces dites exportées (interfaces dans lesquelles toutes les méthodes sont exportées).

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

Nous utilisions Virtual DOM avant qu'il ne devienne courant)

Comme tous les développeurs travaillant avec des interfaces utilisateur Web complexes, nous avons rapidement réalisé que le DOM était mal adapté au travail avec des interfaces utilisateur dynamiques. Presque immédiatement, un analogue de Virtual DOM a été implémenté pour optimiser le travail avec l'interface utilisateur. Pendant le traitement des événements, toutes les modifications du DOM sont stockées en mémoire et, seulement lorsque toutes les opérations sont terminées, les modifications accumulées sont appliquées à l'arborescence DOM.

Optimisation du client Web

Pour que notre client Web fonctionne plus rapidement, nous essayons d'utiliser au maximum les capacités standard du navigateur (CSS, etc.). Ainsi, le panneau de commande du formulaire (situé sur presque tous les formulaires de l'application) est rendu exclusivement à l'aide d'outils de navigateur, en utilisant une mise en page dynamique basée sur CSS.

À propos du client Web 1C

Test

Pour les tests fonctionnels et de performances, nous utilisons un outil propriétaire (écrit en Java et C++), ainsi qu'une suite de tests construits sur Sélénium.

Notre outil est universel - il vous permet de tester presque tous les programmes fenêtrés et convient donc pour tester à la fois un client léger et un client Web. L'outil enregistre les actions de l'utilisateur qui a lancé la solution applicative 1C dans un fichier script. Dans le même temps, des images de la zone de travail de l'écran (standards) sont enregistrées. Lors de la surveillance des nouvelles versions du client Web, les scripts sont exécutés sans la participation de l'utilisateur. Dans les cas où la capture d'écran ne correspond à aucune étape à celle de référence, le test est considéré comme ayant échoué, après quoi un spécialiste de la qualité mène une enquête pour déterminer s'il s'agit d'une erreur ou d'un changement planifié dans le comportement du système. En cas de comportement planifié, les normes sont automatiquement remplacées par de nouvelles.

L'outil mesure également les performances des applications avec une précision allant jusqu'à 25 millisecondes. Dans certains cas, nous bouclons des parties du script (par exemple en répétant plusieurs fois la saisie de la commande) pour analyser la dégradation du temps d'exécution au fil du temps. Les résultats de toutes les mesures sont enregistrés dans un journal pour analyse.

À propos du client Web 1C
Notre outil de test et notre application en test

Notre outil et Selenium se complètent ; par exemple, si un bouton sur l'un des écrans a changé d'emplacement, Selenium peut ne pas le suivre, mais notre outil le remarquera, car effectue une comparaison pixel par pixel de la capture d'écran avec la norme. L'outil est également capable de suivre les problèmes de traitement des entrées du clavier ou de la souris, puisque c'est exactement ce qu'il reproduit.

Les tests sur les deux outils (le nôtre et Selenium) exécutent des scénarios de travail typiques de nos solutions applicatives. Les tests sont automatiquement lancés après la construction quotidienne de la plateforme 1C:Enterprise. Si les scripts sont plus lents (par rapport à la version précédente), nous étudions et résolvons la cause du ralentissement. Notre critère est simple : la nouvelle version ne doit pas fonctionner plus lentement que la précédente.

Les développeurs utilisent différents outils pour enquêter sur les incidents de ralentissement ; principalement utilisé Dynatrace AJAX Édition société de production DynaTrace. Les journaux d'exécution de l'opération problématique sur les builds précédentes et nouvelles sont enregistrés, puis les journaux sont analysés. Dans le même temps, le temps d'exécution d'opérations uniques (en millisecondes) peut ne pas être un facteur décisif - des processus de service tels que le garbage collection sont périodiquement lancés dans le navigateur, ils peuvent chevaucher le temps d'exécution des fonctions et déformer l'image. Des paramètres plus pertinents dans ce cas seraient le nombre d'instructions JavaScript exécutées, le nombre d'opérations atomiques sur le DOM, etc. Si le nombre d'instructions/opérations dans un même script a augmenté dans une nouvelle version, cela signifie presque toujours une baisse de performances qui doit être corrigée.

En outre, l'une des raisons de la baisse des performances peut être que Google Closure Compiler, pour une raison quelconque, n'a pas pu effectuer la substitution en ligne de la fonction (par exemple, parce que la fonction est récursive ou virtuelle). Dans ce cas, nous essayons de corriger la situation en réécrivant le code source.

Extensions de navigateur

Lorsqu'une solution applicative nécessite des fonctionnalités qui ne sont pas disponibles en JavaScript, nous utilisons des extensions de navigateur :

  • travailler avec des fichiers
  • pour travailler avec la cryptographie
  • travailler avec composants externes

Nos extensions se composent de deux parties. La première partie est ce qu'on appelle une extension de navigateur (généralement des extensions pour Chrome et Firefox écrites en JavaScript), qui interagissent avec la deuxième partie - une extension binaire qui implémente les fonctionnalités dont nous avons besoin. Il convient de mentionner que nous écrivons 3 versions d'extensions binaires - pour Windows, Linux et MacOS. L'extension binaire est fournie dans le cadre de la plateforme 1C:Enterprise et se trouve sur le serveur d'applications 1C. Lorsqu'il est appelé pour la première fois depuis un client Web, il est téléchargé sur l'ordinateur client et installé dans le navigateur.

Lorsqu'elles sont exécutées dans Safari, nos extensions utilisent NPAPI ; lorsqu'elles sont exécutées dans Internet Explorer, elles utilisent la technologie ActiveX. Microsoft Edge ne prend pas encore en charge les extensions, donc le client Web qu'il contient fonctionne avec des restrictions.

Poursuite du développement du

L'une des tâches de l'équipe de développement du client Web est le développement ultérieur des fonctionnalités. La fonctionnalité du client Web doit être identique à celle du client léger ; toutes les nouvelles fonctionnalités sont implémentées simultanément dans les clients légers et Web.

D'autres tâches incluent le développement de l'architecture, la refactorisation, l'amélioration des performances et de la fiabilité. Par exemple, l’une des orientations est la poursuite de l’évolution vers un modèle de travail asynchrone. Certaines fonctionnalités du client Web sont actuellement construites sur un modèle d'interaction synchrone avec le serveur. Le modèle asynchrone devient désormais plus pertinent dans les navigateurs (et pas seulement dans les navigateurs), ce qui nous oblige à modifier le client Web en remplaçant les appels synchrones par des appels asynchrones (et en refactorisant le code en conséquence). La transition progressive vers un modèle asynchrone s'explique par la nécessité d'accompagner les solutions publiées et leur adaptation progressive.

Source: habr.com

Ajouter un commentaire