Sobre o cliente web 1C

Um dos recursos interessantes da tecnologia 1C:Enterprise é que a solução de aplicativo, desenvolvida usando tecnologia de formulários gerenciados, pode ser lançada tanto em um cliente fino (executável) para Windows, Linux, MacOS X, quanto como um cliente web para 5 navegadores - Chrome, Internet Explorer, Firefox, Safari, Edge e tudo isso sem alterar o código-fonte do aplicativo. Além disso, externamente o aplicativo no thin client e no navegador funciona e parece quase idêntico.
Encontre 10 diferenças (2 fotos abaixo do corte):

Janela do cliente fino no Linux:

Sobre o cliente web 1C

A mesma janela no cliente web (no navegador Chrome):

Sobre o cliente web 1C

Por que criamos um cliente web? Para dizer de forma um tanto patética, o tempo estabeleceu essa tarefa para nós. Trabalhar pela Internet sempre foi um pré-requisito para aplicações empresariais. Primeiramente, adicionamos a possibilidade de trabalhar via Internet para nosso thin client (alguns de nossos concorrentes, aliás, pararam por aí; outros, ao contrário, abandonaram o thin client e se limitaram a implementar um web client). Decidimos dar aos nossos usuários a oportunidade de escolher a opção de cliente que melhor lhes convier.

Sobre o cliente web 1C

Adicionar recursos baseados na Web ao thin client foi um grande projeto com uma mudança completa na arquitetura cliente-servidor. Criar um cliente web é um projeto completamente novo, começando do zero.

Formulação do problema

Então, os requisitos do projeto: o web client deve fazer o mesmo que o thin client, a saber:

  1. Exibir interface do usuário
  2. Execute o código do cliente escrito em linguagem 1C

A interface do usuário em 1C é descrita em um editor visual, mas de forma declarativa, sem arranjo de elementos pixel por pixel; São usados ​​cerca de três dúzias de tipos de elementos de interface - botões, campos de entrada (texto, numérico, data/hora), listas, tabelas, gráficos, etc.

O código do cliente na linguagem 1C pode conter chamadas de servidor, trabalhar com recursos locais (arquivos, etc.), imprimir e muito mais.

Tanto o thin client (ao trabalhar via web) quanto o web client usam o mesmo conjunto de serviços web para se comunicar com o servidor de aplicativos 1C. As implementações do cliente, é claro, são diferentes - o thin client é escrito em C++, o cliente web é escrito em JavaScript.

Um pouco de história

O projeto do cliente web começou em 2006, com uma equipe de (em média) 5 pessoas. Em determinadas etapas do projeto, os desenvolvedores foram envolvidos para implementar funcionalidades específicas (planilha, diagramas, etc.); via de regra, esses foram os mesmos desenvolvedores que criaram essa funcionalidade no thin client. Aqueles. os desenvolvedores reescreveram componentes em JavaScript que haviam criado anteriormente em C++.

Desde o início, rejeitamos a ideia de qualquer conversão automática (mesmo parcial) do código do thin client C++ em cliente web JavaScript devido às fortes diferenças conceituais entre as duas linguagens; o cliente web foi escrito em JavaScript do zero.

Nas primeiras iterações do projeto, o cliente web converteu o código do cliente na linguagem 1C integrada diretamente em JavaScript. O thin client age de maneira diferente - o código na linguagem 1C integrada é compilado em bytecode e, em seguida, esse bytecode é interpretado no cliente. Posteriormente, o web client passou a fazer o mesmo - em primeiro lugar, proporcionou um ganho de desempenho e, em segundo lugar, possibilitou unificar a arquitetura dos thin clients e web clients.

A primeira versão da plataforma 1C:Enterprise com suporte ao cliente web foi lançada em 2009. O cliente web naquela época suportava 2 navegadores - Internet Explorer e Firefox. Os planos originais incluíam suporte para Opera, mas devido a problemas intransponíveis naquele momento com os manipuladores de fechamento do aplicativo no Opera (não era possível rastrear com 100% de certeza que o aplicativo estava fechando, e naquele momento realizar o procedimento de desconexão do o servidor de aplicativos 1C) desses planos teve que ser abandonado.

Estrutura do projeto

No total, a plataforma 1C:Enterprise possui 4 projetos escritos em JavaScript:

  1. WebTools – bibliotecas compartilhadas usadas por outros projetos (incluímos também Biblioteca do Google Closure).
  2. elemento de controle Documento formatado (implementado em JavaScript tanto no thin client quanto no web client)
  3. elemento de controle Agendador (implementado em JavaScript tanto no thin client quanto no web client)
  4. cliente da web

A estrutura de cada projeto se assemelha à estrutura dos projetos Java (ou projetos .NET - o que estiver mais próximo); Temos namespaces e cada namespace está em uma pasta separada. Dentro da pasta existem arquivos e classes de namespace. Existem cerca de 1000 arquivos no projeto do cliente web.

Estruturalmente, o cliente web é amplamente dividido nos seguintes subsistemas:

  • Interface de aplicativo cliente gerenciado
    • Interface geral do aplicativo (menus do sistema, painéis)
    • Interface de formulários gerenciados, incluindo, entre outros, cerca de 30 controles (botões, vários tipos de campos de entrada - texto, numérico, data/hora, etc., tabelas, listas, gráficos, etc.)

  • Modelo de objeto disponível para desenvolvedores no cliente (mais de 400 tipos no total: modelo de objeto de interface gerenciada, configurações de layout de dados, estilo condicional, etc.)
  • Intérprete da linguagem 1C integrada
  • Extensões de navegador (usadas para funcionalidades não suportadas em JavaScript)
    • Trabalhando com criptografia
    • Trabalhando com arquivos
    • Tecnologia de componentes externos, permitindo sua utilização tanto em thin clients quanto em web clients

Recursos de desenvolvimento

Implementar tudo isso em JavaScript não é fácil. Talvez o cliente web 1C seja um dos maiores aplicativos do lado do cliente escritos em JavaScript - cerca de 450.000 linhas. Usamos ativamente uma abordagem orientada a objetos no código do cliente web, o que simplifica o trabalho com um projeto tão grande.

Para minimizar o tamanho do código do cliente, primeiro usamos nosso próprio ofuscador e, a partir da versão 8.3.6 da plataforma (outubro de 2014), começamos a usar Compilador de fechamento do Google. O efeito do uso em números – o tamanho da estrutura do cliente web após ofuscação:

  • Ofuscador próprio – 1556 kb
  • Compilador de fechamento do Google – 1073 kb

Usar o Google Closure Compiler nos ajudou a melhorar o desempenho do cliente web em 30% em comparação com nosso próprio ofuscador. Além disso, a quantidade de memória consumida pelo aplicativo diminuiu de 15 a 25% (dependendo do navegador).

O Google Closure Compiler funciona muito bem com código orientado a objetos, portanto sua eficiência para o cliente web é a mais alta possível. O Closure Compiler faz algumas coisas boas para nós:

  • Verificação de tipo estático no estágio de construção do projeto (garante que cobrimos o código com anotações JSDoc). O resultado é uma digitação estática, com nível muito próximo da digitação em C++. Isso ajuda a detectar uma porcentagem bastante grande de erros na fase de compilação do projeto.
  • Reduzindo o tamanho do código por meio de ofuscação
  • Uma série de otimizações do código executado, por exemplo, como:
    • substituições de funções embutidas. Chamar uma função em JavaScript é uma operação bastante cara, e as substituições in-line de pequenos métodos usados ​​com frequência aceleram significativamente o código.
    • Contando constantes em tempo de compilação. Se uma expressão depende de uma constante, o valor real da constante será substituído nela

Usamos WebStorm como nosso ambiente de desenvolvimento de cliente web.

Para análise de código usamos SonarQubeGenericName, onde integramos analisadores de código estático. Usando analisadores, monitoramos a degradação da qualidade do código-fonte JavaScript e tentamos evitá-la.

Sobre o cliente web 1C

Que problemas resolvemos/estamos resolvendo?

Durante a implementação do projeto, encontramos vários problemas interessantes que tivemos que resolver.

Troque dados com o servidor e entre janelas

Existem situações em que a ofuscação do código-fonte pode interferir no funcionamento do sistema. Código externo ao código executável do cliente web, devido à ofuscação, pode ter nomes de funções e parâmetros diferentes daqueles que nosso código executável espera. O código externo para nós é:

  • Código vindo do servidor na forma de estruturas de dados
  • Código para outra janela do aplicativo

Para evitar ofuscação ao interagir com o servidor, usamos a tag @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;
}

E para evitar ofuscação ao interagir com outras janelas, usamos as chamadas interfaces exportadas (interfaces nas quais todos os métodos são exportados).

/**
 * Экспортируемый интерфейс контрола 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 o Virtual DOM antes de se tornar popular)

Como todos os desenvolvedores que lidam com interfaces de usuário da Web complexas, percebemos rapidamente que o DOM é pouco adequado para trabalhar com interfaces de usuário dinâmicas. Quase imediatamente, um análogo do Virtual DOM foi implementado para otimizar o trabalho com a UI. Durante o processamento de eventos, todas as alterações do DOM são armazenadas na memória e, somente quando todas as operações são concluídas, as alterações acumuladas são aplicadas à árvore do DOM.

Otimizando o cliente web

Para fazer nosso cliente web funcionar mais rápido, tentamos usar ao máximo os recursos padrão do navegador (CSS, etc.). Assim, o painel de comando do formulário (localizado em quase todos os formulários da aplicação) é renderizado exclusivamente por meio de ferramentas do navegador, utilizando layout dinâmico baseado em CSS.

Sobre o cliente web 1C

Teste

Para testes funcionais e de desempenho, utilizamos uma ferramenta proprietária (escrita em Java e C++), bem como um conjunto de testes construídos sobre Selênio.

Nossa ferramenta é universal - permite testar quase qualquer programa em janela e, portanto, é adequada para testar tanto um thin client quanto um web client. A ferramenta registra as ações do usuário que lançou a solução do aplicativo 1C em um arquivo de script. Ao mesmo tempo, são gravadas imagens da área de trabalho da tela – padrões. Ao monitorar novas versões do cliente web, os scripts são reproduzidos sem a participação do usuário. Nos casos em que a captura de tela não corresponde à de referência em nenhuma etapa, o teste é considerado reprovado, após o qual um especialista em qualidade conduz uma investigação para determinar se se trata de um erro ou de uma mudança planejada no comportamento do sistema. Em caso de comportamento planejado, os padrões são automaticamente substituídos por novos.

A ferramenta também mede o desempenho do aplicativo com precisão de até 25 milissegundos. Em alguns casos, repetimos partes do script (por exemplo, repetindo a entrada do pedido várias vezes) para analisar a degradação do tempo de execução ao longo do tempo. Os resultados de todas as medições são registrados em um registro para análise.

Sobre o cliente web 1C
Nossa ferramenta de teste e aplicativo em teste

Nossa ferramenta e o Selenium se complementam; por exemplo, se algum botão em uma das telas mudou de localização, o Selenium pode não rastrear isso, mas nossa ferramenta notará, pois faz uma comparação pixel por pixel da captura de tela com o padrão. A ferramenta também é capaz de rastrear problemas de processamento de entradas do teclado ou mouse, pois é exatamente isso que ela reproduz.

Os testes em ambas as ferramentas (nossa e Selenium) executam cenários de trabalho típicos de nossas soluções de aplicação. Os testes são iniciados automaticamente após a construção diária da plataforma 1C:Enterprise. Se os scripts forem mais lentos (em comparação com a compilação anterior), investigamos e resolvemos a causa da lentidão. Nosso critério é simples - a nova compilação não deve funcionar mais lentamente que a anterior.

Os desenvolvedores usam ferramentas diferentes para investigar incidentes de lentidão; usado principalmente Edição Dynatrace AJAX produção da empresa DynaTrace. Os logs da execução da operação problemática nas compilações anteriores e novas são registrados e, em seguida, os logs são analisados. Ao mesmo tempo, o tempo de execução de operações únicas (em milissegundos) pode não ser um fator decisivo - processos de serviço como coleta de lixo são iniciados periodicamente no navegador, podem se sobrepor ao tempo de execução de funções e distorcer a imagem. Parâmetros mais relevantes neste caso seriam o número de instruções JavaScript executadas, o número de operações atômicas no DOM, etc. Se o número de instruções/operações no mesmo script aumentou em uma nova versão, isso quase sempre significa uma queda no desempenho que precisa ser corrigida.

Além disso, um dos motivos para a queda no desempenho pode ser que o Google Closure Compiler, por algum motivo, não conseguiu realizar a substituição in-line da função (por exemplo, porque a função é recursiva ou virtual). Neste caso, tentamos corrigir a situação reescrevendo o código-fonte.

Extensões de navegador

Quando uma solução de aplicativo precisa de funcionalidades que não estão disponíveis em JavaScript, usamos extensões de navegador:

Nossas extensões consistem em duas partes. A primeira parte é chamada de extensão do navegador (geralmente extensões para Chrome e Firefox escritas em JavaScript), que interagem com a segunda parte - uma extensão binária que implementa a funcionalidade que precisamos. Deve-se mencionar que escrevemos 3 versões de extensões binárias - para Windows, Linux e MacOS. A extensão binária é fornecida como parte da plataforma 1C:Enterprise e está localizada no servidor de aplicativos 1C. Quando chamado pela primeira vez a partir de um cliente web, ele é baixado no computador cliente e instalado no navegador.

Quando executadas no Safari, nossas extensões usam NPAPI; quando executadas no Internet Explorer, elas usam tecnologia ActiveX. Microsoft Edge ainda não suporta extensões, portanto o cliente web nele funciona com restrições.

Um maior desenvolvimento

Uma das tarefas da equipe de desenvolvimento do cliente web é o desenvolvimento adicional de funcionalidades. A funcionalidade do cliente web deve ser idêntica à funcionalidade do cliente fino; todas as novas funcionalidades são implementadas simultaneamente nos clientes finos e web.

Outras tarefas incluem desenvolver a arquitetura, refatorar, melhorar o desempenho e a confiabilidade. Por exemplo, uma das direções é avançar em direção a um modelo de trabalho assíncrono. Algumas das funcionalidades do cliente web são atualmente construídas em um modelo síncrono de interação com o servidor. O modelo assíncrono está agora se tornando mais relevante em navegadores (e não apenas em navegadores), e isso nos obriga a modificar o cliente web, substituindo chamadas síncronas por assíncronas (e refatorando o código de acordo). A transição gradual para um modelo assíncrono é explicada pela necessidade de apoiar as soluções lançadas e a sua adaptação gradual.

Fonte: habr.com

Adicionar um comentário