Sobre el cliente web 1C

Una de las características interesantes de la tecnología 1C:Enterprise es que la solución de aplicación, desarrollada utilizando tecnología de formularios administrados, se puede ejecutar tanto en un cliente ligero (ejecutable) para Windows, Linux, MacOS X como en un cliente web para 5 navegadores. Chrome, Internet Explorer, Firefox, Safari, Edge y todo ello sin cambiar el código fuente de la aplicación. Además, externamente la aplicación en el cliente ligero y en el navegador funciona y se ve casi idéntica.
Encuentra 10 diferencias (2 imágenes debajo del corte):

Ventana de cliente ligero 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 un cliente web? Para decirlo un poco patéticamente, el tiempo nos ha encomendado esa tarea. Trabajar a través de Internet ha sido durante mucho tiempo un requisito previo para las aplicaciones empresariales. Primero, agregamos la capacidad de trabajar a través de Internet para nuestro cliente ligero (algunos de nuestros competidores, por cierto, se detuvieron en esto; otros, por el contrario, abandonaron el cliente ligero y se limitaron a implementar un cliente web). Decidimos darles a nuestros usuarios la oportunidad de elegir la opción de cliente que más les convenga.

Sobre el cliente web 1C

Agregar capacidades basadas en web al cliente ligero fue un gran proyecto con un cambio completo en la arquitectura cliente-servidor. Crear un cliente web es un proyecto completamente nuevo, que comienza desde cero.

Formulación del problema

Entonces, los requisitos del proyecto: el cliente web debe hacer lo mismo que el cliente ligero, es decir:

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

La interfaz de usuario en 1C se describe en un editor visual, pero de forma declarativa, sin disposición de elementos píxel por píxel; Se utilizan alrededor de tres docenas de tipos de elementos de interfaz: botones, campos de entrada (texto, numérico, fecha/hora), listas, tablas, gráficos, etc.

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

Tanto el cliente ligero (cuando se trabaja 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. Las implementaciones del cliente, por supuesto, son diferentes: el cliente ligero está escrito en C++, el cliente web está escrito en JavaScript.

Un poco de historia

El proyecto del cliente web comenzó en 2006, con un equipo de (en promedio) 5 personas. En determinadas etapas del proyecto, los desarrolladores participaron para implementar funcionalidades específicas (documento de hoja de cálculo, diagramas, etc.); Como regla general, estos eran los mismos desarrolladores que implementaron esta funcionalidad en el cliente ligero. Aquellos. Los desarrolladores reescribieron componentes en JavaScript que habían creado previamente en C++.

Desde el principio, rechazamos la idea de cualquier conversión automática (incluso parcial) del código de cliente ligero C++ en un cliente web JavaScript debido a las fuertes diferencias conceptuales entre los dos lenguajes; El cliente web fue escrito en JavaScript desde cero.

En las primeras iteraciones del proyecto, el cliente web convirtió el código del cliente en el lenguaje 1C integrado directamente a JavaScript. El cliente ligero actúa de manera diferente: el código en el lenguaje 1C incorporado se compila en un código de bytes y luego este código de bytes se interpreta en el cliente. Posteriormente, el cliente web comenzó a hacer lo mismo: en primer lugar, aumentó el rendimiento y, en segundo lugar, permitió unificar la arquitectura de los clientes web y ligeros.

La primera versión de la plataforma 1C:Enterprise con soporte para cliente web se lanzó en 2009. El cliente web en ese momento admitía 2 navegadores: Internet Explorer y Firefox. Los planes originales incluían soporte para Opera, pero debido a problemas insuperables en ese momento con los controladores de cierre de aplicaciones en Opera (no era posible rastrear con 100% de certeza que la aplicación se estaba cerrando, y en ese momento realizar el procedimiento de desconexión de el servidor de aplicaciones 1C) de estos planes tuvo que ser abandonado.

Estructura del proyecto

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

  1. WebTools: bibliotecas compartidas utilizadas por otros proyectos (también incluimos Biblioteca de cierre de Google).
  2. Elemento de control Documento formateado (implementado en JavaScript tanto en el cliente ligero como en el cliente web)
  3. Elemento de control Planificador (implementado en JavaScript tanto en el cliente ligero como en el cliente web)
  4. cliente web

La estructura de cada proyecto se asemeja a la estructura de los proyectos Java (o proyectos .NET, lo que esté más cerca); Tenemos espacios de nombres y cada espacio de nombres está en una carpeta separada. Dentro de la carpeta hay archivos y clases de espacio de nombres. Hay alrededor de 1000 archivos en el proyecto del cliente web.

Estructuralmente, el cliente web se divide en gran medida en los siguientes subsistemas:

  • Interfaz de aplicación cliente administrada
    • Interfaz general de la aplicación (menús del sistema, paneles)
    • Interfaz de formularios administrados, que incluye, entre otras cosas, alrededor de 30 controles (botones, varios tipos de campos de entrada: texto, numérico, fecha/hora, etc., tablas, listas, gráficos, etc.)

  • Modelo de objetos disponible para los desarrolladores en el cliente (más de 400 tipos en total: modelo de objetos de interfaz administrada, configuración de diseño de datos, estilo condicional, etc.)
  • Intérprete del lenguaje 1C incorporado.
  • Extensiones del navegador (utilizadas para funciones no compatibles con JavaScript)
    • Trabajar con criptografía
    • Trabajar con archivos
    • Tecnología de componentes externos, lo que permite su uso tanto en clientes ligeros como web.

Funciones de desarrollo

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

Para minimizar el tamaño del código del cliente, primero usamos nuestro propio ofuscador y, a partir de la versión de plataforma 8.3.6 (octubre de 2014), comenzamos a usar Compilador de cierre de Google. El efecto del uso en números: el tamaño del marco del cliente web después de la ofuscación:

  • Ofuscador propio – 1556 kb
  • Compilador de cierre de Google – 1073 kb

El uso de Google Close Compiler nos ayudó a mejorar el rendimiento del cliente web en un 30% en comparación con nuestro propio ofuscador. Además, la cantidad de memoria consumida por la aplicación se ha reducido entre un 15 y un 25 % (según el navegador).

Google Close Compiler funciona muy bien con código orientado a objetos, por lo que su eficiencia para el cliente web es la mayor posible. El compilador de cierre hace algunas cosas buenas por nosotros:

  • Verificación de tipos estáticos en la etapa de construcción del proyecto (garantiza que cubrimos el código con anotaciones JSDoc). El resultado es una escritura estática, muy cercana en nivel a la escritura en C++. Esto ayuda a detectar un porcentaje bastante grande de errores en la etapa de compilación del proyecto.
  • Reducir el tamaño del código mediante ofuscación
  • Varias optimizaciones del código ejecutado, por ejemplo, como:
    • sustituciones de funciones en línea. Llamar a una función en JavaScript es una operación bastante costosa y las sustituciones en línea de métodos pequeños de uso frecuente aceleran significativamente el código.
    • Contando constantes en tiempo de compilación. Si una expresión depende de una constante, se sustituirá en ella el valor real de la constante.

Utilizamos WebStorm como nuestro entorno de desarrollo de clientes web.

Para el análisis de código utilizamos SonarQube, donde integramos analizadores de código estático. Utilizando analizadores, monitoreamos la degradación de la calidad del código fuente JavaScript e intentamos prevenirla.

Sobre el cliente web 1C

¿Qué problemas resolvimos/estamos resolviendo?

Durante la implementación del proyecto, nos encontramos con una serie de problemas interesantes que tuvimos que resolver.

Intercambiar datos con el servidor y entre Windows.

Hay 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 los que espera nuestro código ejecutable. El código externo para nosotros es:

  • Código procedente del servidor en forma de estructuras de datos.
  • Código para otra ventana de aplicación

Para evitar confusió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 confusión al interactuar con otras ventanas, utilizamos las llamadas interfaces exportadas (interfaces en las que se exportan todos los métodos).

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

Como todos los desarrolladores que trabajan con UI web complejas, rápidamente nos dimos cuenta 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 DOM se almacenan en la memoria y, solo cuando se completan todas las operaciones, los cambios acumulados se aplican al árbol DOM.

Optimización del cliente web

Para que nuestro cliente web funcione más rápido, intentamos utilizar al máximo las capacidades estándar del navegador (CSS, etc.). Por lo tanto, el panel de comando del formulario (ubicado en casi todos los formularios de la aplicación) se representa exclusivamente utilizando herramientas 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 patentada (escrita en Java y C++), así como un conjunto de pruebas creadas sobre Selenio.

Nuestra herramienta es universal: le permite probar casi cualquier programa de ventana y, por lo tanto, es adecuada para probar tanto un cliente ligero como un cliente web. La herramienta registra las acciones del usuario que inició la solución de la aplicación 1C en un archivo de script. Al mismo tiempo, se graban imágenes del área de trabajo de la pantalla (estándares). Al monitorear nuevas versiones del cliente web, los scripts se reproducen sin la participación del usuario. En los casos en que la captura de pantalla no coincide con la de referencia en algún paso, la prueba se considera fallida, tras lo cual un especialista en calidad realiza una investigación para determinar si se trata de un error o un cambio planificado en el comportamiento del sistema. En caso de comportamiento planificado, los estándares se reemplazan automáticamente por otros 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, repitiendo la entrada de la orden varias veces) para analizar la degradación del tiempo de ejecución a lo largo del tiempo. Los resultados de todas las mediciones se registran en un registro para su análisis.

Sobre el cliente web 1C
Nuestra herramienta de prueba y aplicación bajo prueba

Nuestra herramienta y Selenium se complementan; por ejemplo, si algún botón en una de las pantallas ha cambiado su ubicación, es posible que Selenium no lo rastree, pero nuestra herramienta lo notará, porque hace una comparación píxel por píxel de la captura de pantalla con el estándar. La herramienta también puede rastrear problemas con el procesamiento de entradas desde el teclado o el mouse, ya que esto es exactamente lo que reproduce.

Las pruebas en ambas herramientas (la nuestra y Selenium) ejecutan escenarios de trabajo típicos de nuestras soluciones de aplicaciones. Las pruebas se inician automáticamente después de la compilación diaria de la plataforma 1C:Enterprise. Si los scripts son más lentos (en comparación con la versión anterior), investigamos y resolvemos la causa de la desaceleración. Nuestro criterio es simple: la nueva construcción no debería funcionar más lento que la anterior.

Los desarrolladores utilizan diferentes herramientas para investigar incidentes de desaceleración; utilizado principalmente Edición Dynatrace AJAX productora DynaTrace. Se registran los registros de la ejecución de la operación problemática en las compilaciones nuevas y anteriores y luego se analizan. Al mismo tiempo, el tiempo de ejecución de operaciones individuales (en milisegundos) puede no ser un factor decisivo: periódicamente se inician en el navegador procesos de servicio como la recolección de basura, pueden superponerse con el tiempo de ejecución de funciones y distorsionar la imagen. Los parámetros más relevantes en este caso serían la cantidad de instrucciones JavaScript ejecutadas, la cantidad de operaciones atómicas en el DOM, etc. Si el número de instrucciones/operaciones en el mismo script ha aumentado en una nueva versión, esto casi siempre significa una caída en el rendimiento que debe corregirse.

Además, una de las razones de la caída en el rendimiento puede ser que Google Close Compiler, por algún motivo, 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 del navegador

Cuando una solución de aplicación necesita una 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 una extensión del navegador (generalmente extensiones para Chrome y Firefox escritas en JavaScript), que interactúa 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. La primera vez que se llama desde un cliente web, se descarga en la computadora del cliente y se instala en el navegador.

Cuando se ejecutan en Safari, nuestras extensiones usan NPAPI; cuando se ejecutan en Internet Explorer, usan tecnología ActiveX. Microsoft Edge aún no admite extensiones, por lo que el cliente web que contiene funciona con restricciones.

Un mayor desarrollo

Una de las tareas del equipo de desarrollo del cliente web es el desarrollo posterior de la funcionalidad. La funcionalidad del cliente web debe ser idéntica a la funcionalidad del cliente ligero; todas las funciones nuevas se implementan simultáneamente tanto en el cliente ligero como en el cliente web.

Otras tareas incluyen desarrollar la arquitectura, refactorizar, mejorar el rendimiento y la confiabilidad. Por ejemplo, una de las direcciones es avanzar hacia un modelo de trabajo asincrónico. Algunas de las funciones del cliente web se basan actualmente en un modelo sincrónico de interacción con el servidor. El modelo asincrónico ahora se está volviendo más relevante en los navegadores (y no solo en los navegadores), y esto nos obliga a modificar el cliente web reemplazando las llamadas sincrónicas por asincrónicas (y refactorizando el código en consecuencia). La transición gradual a un modelo asincrónico se explica por la necesidad de respaldar las soluciones lanzadas y su adaptación gradual.

Fuente: habr.com

Añadir un comentario