Plataforma "1C:Enterprise" - o que está por trás?

Oi, Habr!
Neste artigo começaremos a história sobre como funciona dentro plataforma "1C:Enterprise 8" e quais tecnologias são utilizadas em seu desenvolvimento.

Plataforma "1C:Enterprise" - o que está por trás?

Por que achamos isso interessante? Em primeiro lugar, porque a plataforma 1C:Enterprise 8 é uma grande aplicação (mais de 10 milhões de linhas de código) em C++ (cliente, servidor, etc.), JavaScript (cliente web) e, mais recentemente, E Java. Grandes projetos podem ser interessantes pelo menos por causa de sua escala, porque questões que são invisíveis em uma pequena base de código surgem com força total nesses projetos. Em segundo lugar, “1C:Enterprise” é um produto replicável, “em caixa”, e há muito poucos artigos sobre tais desenvolvimentos em Habré. Também é sempre interessante saber como é a vida em outras equipes e empresas.

Então vamos começar. Neste artigo daremos uma visão geral de algumas das tecnologias utilizadas na plataforma e delinearemos o panorama, sem nos aprofundarmos na implementação. Na verdade, para muitos mecanismos, uma história detalhada exigiria um artigo separado e, para alguns, um livro inteiro!
Para começar, vale a pena decidir sobre as coisas básicas - o que é a plataforma 1C:Enterprise e em que componentes ela consiste. A resposta a esta pergunta não é tão simples, porque o termo “Plataforma” (para resumir, vamos chamá-lo assim) refere-se a um meio de desenvolvimento de aplicações de negócios, um ambiente de execução e ferramentas de administração. Os seguintes componentes podem ser distinguidos aproximadamente:

  • cluster de servidores
  • cliente “thin” capaz de se conectar ao servidor via http e seu próprio protocolo binário
  • cliente para trabalhar em uma arquitetura de duas camadas com um banco de dados localizado em um disco rígido ou pasta de rede
  • cliente da web
  • ferramentas de administração de servidor de aplicativos
  • ambiente de desenvolvimento (conhecido como Configurador)
  • ambiente de execução para iOS, Android e Windows Phone (plataforma móvel 1C)

Todas essas partes, com exceção do cliente web, são escritas em C++. Além disso, há o recentemente anunciado Configurador de nova geração, escrito em Java.

Aplicativos nativos

C++ 03 é usado para desenvolver aplicativos nativos. Para Windows, o Microsoft Visual C++ 12 (perfil compatível com Windows XP) é usado como compilador, e para Linux e Android - gcc 4.8, para iOS - clang 5.0. A biblioteca padrão utilizada é a mesma para todos os sistemas operacionais e compiladores - STLPort. Esta solução reduz a probabilidade de erros específicos de implementação do STL. No momento, estamos planejando migrar para a implementação STL fornecida com CLang, pois o STLPort foi descontinuado e é incompatível com o modo habilitado para C++11 do gcc.
A base de código do servidor é 99% comum, a do cliente - 95%. Além disso, mesmo a plataforma móvel utiliza o mesmo código C++ que a “grande”, embora a percentagem de unificação aí seja um pouco menor.
Como a maioria dos usuários de C++, não pretendemos usar 100% dos recursos da linguagem e de suas bibliotecas. Então, praticamente não usamos Boost, e um dos recursos da linguagem é a conversão dinâmica de tipos. Ao mesmo tempo, usamos ativamente:

  • STL (especificamente strings, contêineres e algoritmos)
  • herança múltipla, incl. herança de implementação múltipla
  • Templates
  • exceções
  • ponteiros inteligentes (implementação personalizada)

Ao utilizar herança múltipla de interfaces (classes completamente abstratas), torna-se possível um modelo de componentes, que será discutido a seguir.

Componentes

Para garantir a modularidade, todas as funcionalidades são divididas em componentes, que são bibliotecas dinâmicas (*.dll para Windows, *.so para Linux). Existem mais de cento e cinquenta componentes no total; aqui estão as descrições de alguns deles:

backend
Contém o mecanismo de metadados da plataforma

conta
Objetos que os desenvolvedores de aplicativos usam para criar registros contábeis (planos de contas e registros contábeis)

bsl
Mecanismo de execução de linguagem incorporado

nuke
Implementação personalizada do alocador de memória

dbeng8
Mecanismo de banco de dados de arquivos. Um mecanismo de banco de dados de servidor de arquivos simples baseado em ISAM, que também inclui um processador SQL simples

wbase
Contém as classes base e funções para implementar a interface de usuário do Windows - classes de janela, acesso GDI, etc.

A divisão em vários componentes é útil sob vários pontos de vista:

  • A separação promove um melhor design, em particular um melhor isolamento de código
  • A partir de um conjunto de componentes você pode montar de forma flexível diferentes opções de entrega:
    • Por exemplo, uma instalação de thin client conterá wbase, mas não terá backend
    • mas no servidor wbase, pelo contrário, não será
    • ambas as opções conterão, é claro, nuke e bsl

Todos os componentes necessários para esta opção de inicialização são carregados quando o programa é iniciado. Isto, em particular, é necessário para registrar classes SCOM, que serão discutidas abaixo.

SCOM

Para decomposição em nível inferior, utiliza-se o sistema SCOM, uma biblioteca semelhante em ideologia à ATL. Para quem ainda não trabalhou com ATL, listamos resumidamente as principais capacidades e funcionalidades.
Para uma classe SCOM especialmente projetada:

  • Fornece métodos de fábrica que permitem criar uma classe a partir de outro componente sabendo apenas seu nome (sem revelar a implementação)
  • Fornece uma infraestrutura de ponteiro inteligente para contagem de referências. A vida útil da classe SCOM não precisa ser monitorada manualmente
  • Permite descobrir se um objeto implementa uma interface específica e converter automaticamente um ponteiro para o objeto em um ponteiro para a interface
  • Crie um objeto de serviço que esteja sempre acessível através do método get_service, etc.

Por exemplo, você pode descrever uma classe para leitura de JSON (por exemplo, JSONStreamReader) no componente json.dll.
Classes e instâncias podem ser criadas a partir de outros componentes; elas precisam ser registradas na máquina SCOM:

SCOM_CLASS_ENTRY(JSONStreamReader)

Esta macro descreverá uma classe especial de gravador estático, cujo construtor será chamado quando o componente for carregado na memória.
Depois disso, você pode criar uma instância dele em outro componente:

IJSONStreamReaderPtr jsonReader = create_instance<IJSONStreamReader>(SCOM_CLSIDOF(JSONStreamReader));

Para apoiar os serviços, o SCOM oferece uma infra-estrutura adicional e bastante complexa. Central para isso é o conceito de um processo SCOM, que serve como um contêiner para a execução de serviços (ou seja, desempenha o papel de localizador de serviços) e também contém uma ligação a recursos localizados. O processo SCOM está vinculado ao thread do sistema operacional. Graças a isso, dentro do aplicativo você poderá receber serviços como este:

SCOM_Process* process = core::current_process();
if (process)
         return get_service<IMyService>(process);

Além disso, ao alternar processos lógicos (SCOM) vinculados a um thread, é possível obter aplicações praticamente independentes do ponto de vista do espaço de informação, rodando dentro do mesmo thread. É assim que nosso thin client funciona com um banco de dados de arquivos - dentro de um processo do sistema operacional existem dois processos SCOM, um associado ao cliente e o segundo ao servidor. Essa abordagem nos permite unificar a escrita do código que funcionará tanto no banco de dados de arquivos local quanto na versão “real” cliente-servidor. O preço dessa uniformidade é caro, mas a prática mostra que vale a pena.

Com base no modelo de componentes SCOM, tanto a lógica de negócios quanto a parte de interface do 1C:Enterprise são implementadas.

Interface do usuário

A propósito, sobre interfaces. Não usamos controles padrão do Windows; nossos controles são implementados diretamente na API do Windows. Para a versão Linux foi feita uma camada que funciona através da biblioteca wxWidgets.
A biblioteca de controles não depende de outras partes do 1C:Enterprise e é usada por nós em vários outros pequenos utilitários internos.

Ao longo dos anos de desenvolvimento do 1C:Enterprise, a aparência dos controles mudou, mas uma mudança séria nos princípios ocorreu apenas uma vez, em 2009, com o lançamento da versão 8.2 e o advento dos “formulários gerenciados”. Além de mudar a aparência, o princípio do layout do formulário mudou fundamentalmente - houve uma rejeição do posicionamento dos elementos pixel por pixel em favor do layout de fluxo dos elementos. Além disso, no novo modelo, os controles não funcionam diretamente com objetos de domínio, mas com DTOs especiais (Objetos de transferência de dados).
Essas mudanças possibilitaram a criação de um cliente web 1C:Enterprise que replica a lógica C++ dos controles JavaScript. Tentamos manter a equivalência funcional entre thin clients e web clients. Nos casos em que isso não é possível, por exemplo devido a limitações da API JavaScript disponível (por exemplo, a capacidade de trabalhar com arquivos é muito limitada), muitas vezes implementamos a funcionalidade necessária usando extensões de navegador escritas em C++. Atualmente oferecemos suporte para Internet Explorer e Microsoft Edge (Windows), Google Chrome (Windows), Firefox (Windows e Linux) e Safari (MacOS).

Além disso, a tecnologia de formulários gerenciados é usada para criar uma interface para aplicativos móveis na plataforma 1C. Em dispositivos móveis, a renderização de controles é implementada usando tecnologias nativas do sistema operacional, mas para a lógica de layout do formulário e resposta da interface, o mesmo código é usado na plataforma “grande” 1C:Enterprise.

Plataforma "1C:Enterprise" - o que está por trás?
Interface 1C no sistema operacional Linux

Plataforma "1C:Enterprise" - o que está por trás?
Interface 1C em um dispositivo móvel

Interface 1C em outras plataformas Plataforma "1C:Enterprise" - o que está por trás?
Interface 1C no sistema operacional Windows

Plataforma "1C:Enterprise" - o que está por trás?
Interface 1C - cliente web

Código aberto

Embora não utilizemos bibliotecas padrão para desenvolvedores C++ no Windows (MFC, controles do WinAPI), não escrevemos todos os componentes por conta própria. A biblioteca já foi mencionada wxWidgets, e também usamos:

  • cURL para trabalhar com HTTP e FTP.
  • OpenSSL para trabalhar com criptografia e estabelecer conexões TLS
  • libxml2 e libxslt para análise XML
  • libetpan para trabalhar com protocolos de correio (POP3, SMTP, IMAP)
  • mimético para analisar mensagens de e-mail
  • SQLite para armazenar logs de usuários
  • UTI para internacionalização

A lista continua.
Além disso, usamos uma versão altamente modificada Teste Google и Google Simulado ao desenvolver testes de unidade.
As bibliotecas necessitaram de adaptação para serem compatíveis com o modelo de organização dos componentes do SCOM.
A prevalência de 1C torna a plataforma um excelente teste de força para as bibliotecas nela utilizadas. Uma variedade de usuários e cenários revela rapidamente erros até mesmo nas áreas de código mais raramente usadas. Nós mesmos os corrigimos e tentamos devolvê-los aos autores da biblioteca. A experiência de interação acaba sendo muito diferente.
Desenvolvedores cURL и libetpan responder rapidamente às solicitações pull, mas o patch, por exemplo, em OpenSSL Nunca conseguimos devolvê-lo.

Conclusão

No artigo abordamos vários aspectos principais do desenvolvimento da plataforma 1C:Enterprise. No escopo limitado do artigo, abordamos apenas alguns aspectos interessantes, em nossa opinião.
Uma descrição geral dos vários mecanismos da plataforma pode ser encontrada aqui.
Que tópicos seriam de seu interesse em artigos futuros?

Como a plataforma móvel 1C é implementada?
Descrição da estrutura interna do cliente web?
Ou talvez você esteja interessado no processo de seleção de recursos para novos lançamentos, desenvolvimento e teste?

Escreva nos comentários!

Fonte: habr.com

Adicionar um comentário