Sobre el cliente web 1C

Una de las características agradables de la tecnología 1C:Enterprise es que la solución de aplicación, desarrollada con tecnología de formularios gestionados, puede ejecutarse tanto en un cliente delgado (ejecutable) en Windows, Linux y MacOS X, como en un cliente web en 5 navegadores: Chrome, Internet Explorer, Firefox, Safari y Edge, y todo esto sin modificar el código fuente de la aplicación. Además, externamente la aplicación en el cliente delgado y en el navegador funciona y se ve prácticamente idéntica.
Encuentra 10 diferencias (debajo hay 2 imágenes):

Ventana del cliente delgado en Linux:

Sobre el cliente web 1C

La misma ventana en el cliente web (en el navegador Chrome):

Sobre el cliente web 1C

¿Por qué creamos el cliente web? Hablando con cierta pomposidad, esta tarea nos la planteó el tiempo. Desde hace tiempo, trabajar a través de Internet se ha convertido en un requisito necesario para las aplicaciones empresariales. Al principio, añadimos la posibilidad de trabajar a través de Internet para nuestro cliente delgado (algunos de nuestros competidores, por cierto, se detuvieron en esto; otros, en cambio, abandonaron el cliente delgado y se limitaron a implementar un cliente web). Nosotros decidimos dar a nuestros usuarios la opción de elegir la variante de cliente que más les convenga.

Sobre el cliente web 1C

La adición de la posibilidad de trabajar a través de Internet para el cliente delgado fue un gran proyecto que implicó un cambio completo en la arquitectura de interacción cliente-servidor. La creación del cliente web, por otro lado, es un proyecto completamente nuevo, que comenzó desde cero.

Planteamiento del problema

Entonces, los requisitos para el proyecto son: el cliente web debe hacer lo mismo que el cliente delgado, a saber:

  1. Mostrar la interfaz de usuario
  2. Ejecutar el código del cliente escrito en el lenguaje 1C

La interfaz de usuario en 1C se describe en un editor visual, pero de forma declarativa, sin disposición pixel por pixel de los elementos; se utilizan aproximadamente una treintena de tipos de elementos de interfaz: botones, campos de entrada (texto, numérico, fecha/hora), listas, tablas, gráficos, etc.

El código del cliente en el lenguaje 1C puede contener llamadas al servidor, trabajar con recursos locales (archivos, etc.), imprimir y mucho más.

Tanto el cliente delgado (al trabajar a través de la web) como el cliente web utilizan el mismo conjunto de servicios web para comunicarse con el servidor de aplicaciones 1C. La implementación en los clientes, por supuesto, es diferente: el cliente delgado está escrito en C++, mientras que el cliente web está en JavaScript.

Un poco de historia

El proyecto de creación del cliente web comenzó en 2006, con un equipo de 5 personas involucradas en promedio. En etapas específicas del proyecto, se contrataron desarrolladores para implementar funcionalidades específicas (documentos en tabla, diagramas, etc.); por lo general, eran los mismos desarrolladores que habían creado esas funcionalidades en el cliente ligero. Es decir, los desarrolladores reescribieron en JavaScript componentes que anteriormente habían creado en C++.

Desde el principio, rechazamos la idea de cualquier conversión automática (incluso parcial) del código C++ del cliente ligero a JavaScript para el cliente web debido a las profundas diferencias conceptuales entre estos dos lenguajes; el cliente web se escribió en JavaScript desde cero.

En las primeras iteraciones del proyecto, el cliente web convertía el código del lenguaje incorporado 1C directamente a JavaScript. El cliente ligero lo hace de manera diferente: el código en el lenguaje incorporado 1C se compila a bytecode, y luego se interpreta en el cliente. Posteriormente, el cliente web también comenzó a hacer esto: en primer lugar, esto mejoró el rendimiento, y en segundo lugar, permitió unificar la arquitectura del cliente ligero y del cliente web.

La primera versión de la plataforma 1C:Enterprise que soportaba el cliente web fue lanzada en 2009. En ese momento, el cliente web soportaba 2 navegadores: Internet Explorer y Firefox. En los planes iniciales estaba la inclusión de Opera, pero debido a problemas insuperables en ese momento con los controladores de cierre de la aplicación en Opera (no se podía rastrear con un 100% de certeza que la aplicación se estaba cerrando, y en ese momento realizar el procedimiento de desconexión del servidor de aplicaciones 1C), tuvimos que renunciar a esos planes.

Estructura del proyecto

En total, la plataforma 1C:Enterprise tiene 4 proyectos escritos en JavaScript:

  1. WebTools – bibliotecas generales utilizadas por los otros proyectos (aquí también incluimos Google Closure Library).
  2. Elemento de control DocumentoFormateado (implementado en JavaScript tanto en el cliente ligero como en el cliente web)
  3. Elemento de control Programador (implementado en JavaScript tanto en el cliente ligero como en el cliente web)
  4. Cliente web

La estructura de cada proyecto recuerda a la estructura de los proyectos Java (o proyectos .NET – cada quien lo que prefiera); tenemos espacios de nombres y cada espacio de nombres se encuentra en una carpeta separada. Dentro de cada carpeta hay archivos y clases del espacio de nombres. En el proyecto del cliente web hay alrededor de 1000 archivos.

Estructuralmente, el cliente web se divide grosso modo en los siguientes subsistemas:

  • Interfaz de aplicación cliente gestionada
    • Interfaz común de la aplicación (menús del sistema, paneles)
    • Interfaz de formularios gestionados, que incluye alrededor de 30 controles (botones, varios tipos de campos de entrada: texto, numéricos, fecha/hora, etc., tablas, listas, gráficos, etc.)

  • Modelo de objetos accesible para desarrolladores en el cliente (más de 400 tipos en total: modelo de objetos de la interfaz gestionada, configuraciones de diseño de datos, formato condicional, etc.)
  • Intérprete del lenguaje incorporado 1C
  • Extensiones de navegador (se utilizan para funcionalidades no soportadas en JavaScript)
    • Trabajo con criptografía
    • Trabajar con archivos
    • Tecnología de componentes externos que permite su uso tanto en clientes delgados como en web

Características del desarrollo

Implementar todo lo anteriormente descrito en JavaScript no es tarea sencilla. Quizás el cliente web de 1C sea una de las aplicaciones más grandes del lado del cliente escritas en JavaScript, con alrededor de 450.000 líneas. Utilizamos activamente en el código del cliente web un enfoque orientado a objetos que simplifica el trabajo con un proyecto tan grande.

Para minimizar el tamaño del código del cliente, inicialmente utilizamos nuestro propio ofuscador, y a partir de la versión de la plataforma 8.3.6 (octubre de 2014) comenzamos a utilizar Google Closure Compiler. El efecto del uso en cifras: el tamaño del marco del cliente web después de la ofuscación:

  • Nuestro propio ofuscador – 1556 kB
  • Google Closure Compiler – 1073 kB

El uso de Google Closure Compiler nos ayudó a aumentar la velocidad del cliente web en un 30% en comparación con nuestro propio ofuscador. Además, se redujo el uso de memoria por parte de la aplicación entre un 15% y un 25% (dependiendo del navegador).

Google Closure Compiler trabaja muy bien con código orientado a objetos, por lo que su eficacia para el cliente web es máxima. Closure Compiler realiza varias buenas cosas para nosotros:

  • Verificación estática de tipos en la etapa de compilación del proyecto (asegurada mediante la cobertura del código con anotaciones JSDoc). Esto resulta en una tipificación estática muy cercana al nivel de tipificación en C++. Esto ayuda a detectar un porcentaje bastante alto de errores en la etapa de compilación del proyecto.
  • Reducción del tamaño del código a través de ofuscación
  • Una serie de optimizaciones del código ejecutable, como las siguientes:
    • sustituciones en línea de funciones. Llamar a una función en JavaScript es una operación bastante costosa, y las sustituciones en línea de métodos pequeños que se utilizan con frecuencia aceleran significativamente el rendimiento del código.
    • Cálculo de constantes en tiempo de compilación. Si una expresión depende de una constante, se insertará el valor real de la constante.

Utilizamos WebStorm como entorno de desarrollo para el cliente web.

Para el análisis de código utilizamos SonarQube, donde integramos analizadores de código estáticos. Con la ayuda de estos analizadores, supervisamos la degradación de la calidad del código fuente en JavaScript y evitamos que ocurra.

Sobre el cliente web 1C

¿Qué tareas resolvimos/estamos resolviendo?

En el curso de la implementación del proyecto, nos enfrentamos a una serie de tareas interesantes que tuvimos que resolver.

Intercambio de datos con el servidor y entre ventanas

Existen situaciones en las que la ofuscación del código fuente puede interferir con el funcionamiento del sistema. El código externo al código ejecutable del cliente web, debido a la ofuscación, puede tener nombres de funciones y parámetros que difieren de aquellos que nuestro código ejecutable espera. El código externo para nosotros es:

  • Código que proviene del servidor en forma de estructuras de datos
  • Código de otra ventana de la aplicación

Para evitar la ofuscación al interactuar con el servidor, utilizamos la etiqueta @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;
}

Y para evitar la ofuscación al interactuar con otras ventanas, utilizamos lo que llamamos interfaces exportables (interfaces en las que todos los métodos son exportables).

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

Usamos Virtual DOM antes de que se volviera mainstream)

Como todos los desarrolladores que trabajan con interfaces de usuario web complejas, nos dimos cuenta rápidamente de que el DOM no es adecuado para trabajar con interfaces de usuario dinámicas. Casi de inmediato se implementó un análogo de Virtual DOM para optimizar el trabajo con la interfaz de usuario. Durante el procesamiento de eventos, todos los cambios en el DOM se almacenan en memoria y, solo al finalizar todas las operaciones, se aplican los cambios acumulados al árbol DOM.

Optimización del rendimiento del cliente web

Para que nuestro cliente web funcione más rápido, tratamos de aprovechar al máximo las capacidades nativas del navegador (CSS, etc.). Así, la barra de herramientas del formulario (que se encuentra prácticamente en cada formulario de la aplicación) se renderiza exclusivamente con los medios del navegador, utilizando un diseño dinámico basado en CSS.

Sobre el cliente web 1C

Pruebas

Para las pruebas funcionales y de rendimiento, utilizamos una herramienta de desarrollo propio (escrita en Java y C++), así como un conjunto de pruebas basadas en Selenium.

Nuestra herramienta es versátil: permite probar prácticamente cualquier programa de ventana, y por lo tanto es adecuada tanto para probar clientes ligeros como clientes web. La herramienta registra las acciones del usuario que inició la solución de aplicación "1C" en un archivo de script. Al mismo tiempo, se graban imágenes del área de trabajo de la pantalla, los estándares. Durante el control de nuevas versiones del cliente web, los scripts se reproducen sin la participación del usuario. En caso de que la captura de pantalla no coincida con el estándar en algún paso, la prueba se considera fallida, tras lo cual un especialista en calidad lleva a cabo una investigación para determinar si es un error o un cambio planificado en el comportamiento del sistema. En caso de comportamiento planificado, los estándares se reemplazan automáticamente por nuevos.

La herramienta también mide el rendimiento de las aplicaciones con una precisión de hasta 25 milisegundos. En algunos casos, repetimos partes del script (por ejemplo, repetimos varias veces la entrada de un pedido) para analizar la degradación del tiempo de ejecución con el tiempo. Todos los resultados de las mediciones se registran en un registro para su análisis.

Sobre el cliente web 1C
Nuestra herramienta de prueba y la aplicación que probamos

Nuestra herramienta y Selenium se complementan; por ejemplo, si un botón en una de las pantallas ha cambiado de ubicación, Selenium puede no detectarlo, pero nuestra herramienta lo notará, ya que realiza una comparación pixel por pixel de la captura de pantalla con el estándar. Además, la herramienta es capaz de rastrear problemas con el procesamiento de la entrada del teclado o del ratón, ya que precisamente eso es lo que reproduce.

Las pruebas en ambas herramientas (la nuestra y Selenium) ejecutan scripts típicos de trabajo de nuestras soluciones de aplicación. Las pruebas se inician automáticamente después de la construcción diaria de la plataforma "1C:Enterprise". En caso de que se ralentice la ejecución de los scripts (en comparación con la construcción anterior), realizamos una investigación y eliminamos la causa de la ralentización. Nuestro criterio es simple: la nueva construcción no debe funcionar más lentamente que la anterior.

Para investigar incidentes de ralentización, los desarrolladores utilizan diferentes herramientas; principalmente se utiliza Dynatrace AJAX Edition de la empresa DynaTrace. Se realiza un registro de los logs de la operación problemática en la versión anterior y en la nueva, y luego se analizan los logs. En este contexto, el tiempo de ejecución de operaciones individuales (en milisegundos) puede no ser un factor determinante, ya que en el navegador se ejecutan periódicamente procesos de servicio como la recolección de basura, que pueden interferir con el tiempo de ejecución de las funciones y distorsionar los resultados. Los parámetros más relevantes en este caso serían el número de instrucciones de JavaScript ejecutadas, el número de operaciones atómicas sobre el DOM, etc. Si el número de instrucciones/operaciones en el mismo escenario en la nueva versión ha aumentado, eso casi siempre significa una disminución en el rendimiento que debe ser corregida.

Otra de las razones de la disminución del rendimiento puede ser que Google Closure Compiler, por alguna razón, no pudo realizar la sustitución en línea de la función (por ejemplo, porque la función es recursiva o virtual). En este caso, intentamos corregir la situación reescribiendo el código fuente.

Extensiones de navegador

En caso de que la solución de aplicación necesite funcionalidad que no está disponible en JavaScript, utilizamos extensiones de navegador:

Nuestras extensiones constan de dos partes. La primera parte es lo que se llama extensión de navegador (generalmente, extensiones escritas en JavaScript para Chrome y Firefox), que interactúan con la segunda parte: una extensión binaria que implementa la funcionalidad que necesitamos. Cabe mencionar que escribimos 3 versiones de extensiones binarias: para Windows, Linux y MacOS. La extensión binaria se suministra como parte de la plataforma 1C:Enterprise y se encuentra en el servidor de aplicaciones 1C. Al primer llamado desde el cliente web, se carga en el computadora del cliente y se instala en el navegador.

Al trabajar en Safari, nuestras extensiones utilizan NPAPI, y al trabajar en Internet Explorer, utilizan la tecnología ActiveX. Microsoft Edge todavía no admite extensiones, por lo que el cliente web funciona con limitaciones.

Desarrollo futuro

Uno de los grupos de tareas para el equipo de desarrollo del cliente web es la evolución de la funcionalidad. La funcionalidad del cliente web debe ser idéntica a la del cliente ligero; toda nueva funcionalidad se implementa simultáneamente en ambos, el cliente ligero y el cliente web.

Otras tareas incluyen el desarrollo de la arquitectura, la refactorización, el aumento del rendimiento y la fiabilidad. Por ejemplo, una de las direcciones es avanzar hacia un modelo de trabajo asíncrono. Actualmente, parte de la funcionalidad del cliente web se basa en un modelo de interacción sincrónica con el servidor. El modelo asíncrono se está volviendo más relevante en los navegadores (y no solo en ellos), lo que nos lleva a modificar el cliente web reemplazando las llamadas sincrónicas por asíncronas (junto con la refactorización correspondiente del código). La transición gradual al modelo asíncrono se explica por la necesidad de apoyar las soluciones lanzadas y su adaptación gradual.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster