Por que lsFusion e não 1C?





Artigo anterior "Por que não 1C?" saiu há mais de um ano e despertou um grande interesse (pouco menos de 100 mil visualizações e 2 mil comentários). No entanto, como esperado, muitas perguntas razoáveis ​​surgiram: "Se não ele, então quem?" Claro que, como muitos já entenderam, aquele artigo não foi escrito assim, mas para lançar outro depois dele, onde seria dito como os problemas descritos no primeiro artigo podem e devem ser resolvidos. No entanto, por vários motivos, o lançamento deste artigo de "resposta" foi adiado por muito tempo. Mas, como se costuma dizer, antes tarde do que nunca.







, ( ) lsFusion. , : (function-level, functional), , -, (constraint) . , buzzwords, , , .







« 1?» ( ):









1 , lsFusion.







: , ..



lsFusion , ( lsFusion — ). ( ). , , — , « ». , , :







  • , (, - , ), , , - (, / , ). , , «».
  • «» ( lsFusion / ), .




Como o lsFusion tenta aproveitar ao máximo o servidor SQL e não o servidor de aplicativos para executar a lógica de cálculo (e ele faz isso agrupando as consultas o máximo possível para executá-las o menos possível), a operação de leitura de um todo objeto em lsFusion não existe em princípio. Como consequência, tanto o problema N + 1 quanto o problema de leitura excessiva no lsFusion são extremamente raros. Por exemplo, a seguinte ação:





fillSum(Invoice i) {

    FOR invoice(InvoiceDetail id) = i DO

        sum(id) <- price(id) * quantity(id);

}





Ele será compilado em uma etapa:

fillSum(Invoice i) {

    sum(InvoiceDetail id) <- price(id) * quantity(id) WHERE invoice(id) = i

}





A qual, por sua vez, será executada com uma consulta, na qual apenas as linhas / colunas utilizadas serão lidas / escritas.



Tabelas / Visualizações: Registros



lsFusion , «» 1, , , , , « » ( , ), . , lsFusion :







  • — , (, )
  • / — , , :
    • — GROUP LAST
    • , — SUM ( lsFusion , lsFusion , )


lsFusion , .







, . lsFusion , , . - :





LEDGER Sales GROUP Stock stock, Sku sku SUM NUMERIC quantity, NUMERIC sum;



//    Sales   :

// stock, sku, quantity, sum = ABSTRACT Stock, Sku, NUMERIC, NUMERIC (Sales); - 

  / 

// quantitySales, sumSales (stock, sku) -   ( =   +  )

// quantitySales, sumSales (stock, sku, DATETIME) -    

// quantitySales, sumSales (stock, sku, DATETIME, DATETIME) -     

//  ..





E nas próximas versões, esse açúcar sintático provavelmente aparecerá. Outra coisa é que mais frequentemente em projetos complexos, os registros têm uma estrutura mais complexa (por exemplo, eles herdam um do outro, desnormalizam dados para índices compostos, expandem em módulos diferentes e assim por diante), então tal açúcar pode ser importante apenas para Desenvolvimento RAD (e mais precisamente, prototipagem), que não é mais tão relevante no mundo moderno de TI.



Os registros são suportados em casos muito especiais



Como mencionado acima, os registros em lsFusion não são uma grande combinação, mas vários mecanismos diferentes, a chave dos quais, talvez, seja o mecanismo de materialização (gravação e atualização automática de dados calculados em tabelas).







1, lsFusion , . , lsFusion :







  1. , , , ( " ").
  2. / / , .
  3. , , , “” ( ).
  4. (), .




lsFusion oferece suporte a restrições e eventos em geral, incluindo dados computados não materializados. Assim, por exemplo, para criar uma restrição de que o resto (que pode ser calculado usando qualquer número de dados / operadores diferentes) deve ser maior que 0, é suficiente escrever apenas uma linha:





CONSTRAINT currentBalance(sku, stock) < 0 MESSAGE '    ';





Consequentemente, a própria plataforma irá ela mesma o mais eficientemente possível (usando cálculos incrementais) verificar se nenhuma alteração (por exemplo, uma alteração no depósito do recebimento ou na quantidade de consumo) violará esta limitação.

Além disso, da mesma forma, você pode criar, por exemplo, notificações sobre alterações de qualquer dado, incluindo calculado:





WHEN SET(currentBalance(Sku sku, Stock stock) < 0//     0

    EMAIL SUBJECT '   ' + address(stock) + '   ' + name(sku) + 

'   0' TO responsibleEmail(group(sku));





Apenas constantes podem ser usadas em parâmetros de tabelas virtuais



- lsFusion . , , , , . , , , lsFusion . :





EXPORT FROM price(Sku sku), balance(date(sku), sku) WHERE name(sku) = '';





A plataforma enviará automaticamente a condição de nome de restrição (e como consequência da data em que o restante será calculado) na subconsulta (e em todas as subconsultas dentro desta subconsulta), realizando assim a otimização de push down do predicado . Além disso, ao contrário do mesmo SQL, a plataforma é capaz de realizar essa otimização não só para agrupamentos, mas também para partições e até mesmo para recursões. No entanto, este é um tópico para um artigo separado, não iremos nos alongar sobre ele aqui.



Inquéritos



, lsFusion SQL ( ), , . , , .









lsFusion, :







  • IDE — , , , ..
  • IDE ( ), , .


, / (IF, SHOWIF ..), (EVAL), lsFusion.









O LsFusion tem um mecanismo de otimização de consulta muito poderoso internamente, em muitos casos realizando otimizações que mesmo DBMSs comerciais caros (sem falar no PostgreSQL) não podem fazer. Portanto, todos os problemas de desempenho descritos no artigo "Por que não SQL" , lsFusion é capaz de resolver de forma independente, sem nenhuma ação adicional por parte do desenvolvedor, que, portanto, pode se concentrar na resolução de problemas de negócios, e não pensar em como escreva uma consulta corretamente e / ou em qual tabela temporária colocar seu resultado.







Portanto, um exemplo de um artigo sobre 1C no lsFusion será parecido com este:







Exemplo do artigo

    .,
    .

    ..  
          ..(,
                               (
                                    
                                    ..
                                     = &))  
         . = .

    . = & 
    (. < . 
        .  NULL)
      
      



currentBalance(InvoiceDetail id) = currentBalance(sku(id));



export(Invoice i) {

    EXPORT FROM sku(InvoiceDetail id), currentBalance(id) WHERE invoice(id) = i AND 

currentBalance(id) < quantity(id) OR NOT currentBalance(id);

}





Conseqüentemente, nenhum "Nomenclature IN (SELECT Nomenclature FROM Document.Invoice.Content WHERE Reference = & Document)" em lsFusion não precisa ser escrito.



SQL



SQL-92, ( SQL — ), lsFusion :







  • / ( SQL — )
  • ( SQL — CTE)
  • ( SQL — )


lsFusion - ( GROUP BY ).









ERP- ORM , , - , ERP- SQL- .







No entanto, no mesmo 1C, as consultas são suportadas apenas para operações de leitura de dados; para gravação, ainda é necessário usar mecanismos ORM, cujo desempenho deixa muito a desejar. Em lsFusion, esse problema não existe, e todas as operações, incluindo a criação de objetos, podem ser executadas no servidor de banco de dados e com uma solicitação. Por exemplo:





generateCards() {

    FOR iterate(i,1,10000NEW d = DiscountCard DO

            number(d) ← ‘Card:’+i;

}







No final das contas, ele será compilado em uma solicitação (ou várias, mas seu número não dependerá da quantidade de dados) e será executado muito rapidamente, e todos os eventos / restrições / agregações também serão executados / verificados / recalculados por um número de solicitações (novamente, independente da quantidade de dados).

O mesmo se aplica ao mecanismo para alterar / excluir uma grande quantidade de dados / objetos:





FOR sum(DiscountCard d) > 10000 DO

    vip (d) ← TRUE;

FOR sum(DiscountCard d) > 10000 DO

    DELETE d;





Compilará para:

sum(DiscountCard d) ← TRUE  WHERE sum(d) > 10000;

DELETE DiscountCard d WHERE sum(d) > 10000;





E, novamente, ele será executado em uma solicitação.





( ) 1, . :







  1. ( MS SQL).
  2. Repeatable Read Serializable.
  3. , .
  4. .


lsFusion. , 1 ( ) lsFusion:







  • , ( , ),
  • , , « ».




lsFusion — , / .







:



Ao contrário de 1C em lsFusion, o fluxo de execução é o mesmo para o servidor e para o cliente. Esta unidade simplifica muito a interação com o dispositivo usuário / cliente em termos do processo de desenvolvimento. Portanto, o exemplo no artigo sobre 1C é escrito na linguagem lsFusion e, portanto, tem a seguinte aparência:





f() <- someData(); //       myForm

DIALOG myForm OBJECTS a INPUT DO // , 

 - 

     IF isSomething(a) DO //          - 

 

         DIALOG otherForm OBJECTS b = a DO { // ,  

       b

             g(b) <- someInput(b); //    b

             APPLY//    

         }





Até certo ponto, o lsFusion usa a abordagem de formas convencionais em 1C, mas o torna muito mais escalonável e produtivo. Na verdade, toda a magia da assincronia permanece sob o capô, e o desenvolvedor pode se concentrar estritamente na solução de problemas de negócios e não pensar sobre onde e como o código que ele escreve deve ser executado.

, lsFusion ( /). , lsFusion CLIENT INTERNAL, . Java, - — JavaScript. “ ” , .









- ( ) “” ( , , ). (, ), , , 1 ( , async / await, ).







lsFusion , , , , .







WYSIWYG:



, 1 , ( ), 2 :







  • - , / ().
  • .


1 . lsFusion , , , «Excel-style» , , , , , . ( lsFusion) « » — / . , .







/



No lsFusion, ao definir propriedades, filtros e outros elementos em um formulário, você pode acessar todos os objetos de uma vez, mesmo se eles aparecerem em listas diferentes (ou outras visualizações). Ao mesmo tempo, a própria plataforma monitora as alterações nos objetos (bem como as alterações nos dados) e atualiza automaticamente os dados do formulário usando esses objetos. Por exemplo, se você criar o seguinte formulário:





FORM balance

    OBJECTS st = Stock, sk = Sku

    PROPERTIES (st) name

    PROPERTIES name(sk), currentBalance(st, sk)

    FILTERS currentBalance(st, sk)

;





Quando você move o registro atual na lista superior (depósitos), a lista inferior (produtos que estão no depósito selecionado) será atualizada automaticamente.



Níveis redundantes de abstração



O princípio principal ao criar o lsFusion foi e continua sendo o princípio - a pureza e integridade de todas as abstrações criadas. Então:







  • lsFusion . — . , .
  • ( ) , , , ( ).
    :




, lsFusion 1. 1 lsFusion:







  • /


lsFusion ( ) . , ( , ..) , «» ( ).







  • /


, 1 - lsFusion ( , ).







  • /


lsFusion , . - « » lsFusion . , . - , , ( ). lsFusion .







  • / / (BI)


. , / lsFusion ( ). , ( , ) lsFusion :







  • , JasperReports, Java. pixel-perfect , .
  • , , , .

  • — «» , , « » ( ).
  • , ( ) JSON, XML, XLSX, DBF .


lsFusion — . , , . , , / .









lsFusion , lsFusion , / ( 1). lsFusion — , . , , , ( ). - .







:







  1. ( BI).
  2. (, )
  3. .




PS: « » ( ) « 1?» , , , , . , , .







Conforme mencionado na seção anterior, o mapeamento da lógica de dados em lsFusion para um banco de dados relacional é transparente e pode ser completamente controlado pelo desenvolvedor. Junto com materializações em geral e índices, um desenvolvedor (e até mesmo um administrador) pode atingir quase qualquer desempenho, mesmo em grandes quantidades de dados. Além disso, uma vez que a própria plataforma monitora as mudanças no modelo físico e atualiza a estrutura do banco de dados sem quaisquer migrações adicionais, o processo de otimização de desempenho pode (e deve) ser executado em um banco de dados em execução quando as estatísticas e opções de uso desse banco de dados são conhecidas. Então, digamos que temos um exemplo simples:





date = DATA DATE (DocumentDetail)

barcode = DATA STRING (Sku);

sku = DATA Sku (DocumentDetail); 



barcode(DocumentDetail dd) = barcode(sku(dd));

count (STRING bc, DATE d) = GROUP SUM 1 IF date(DocumentDetail dd) > d AND barcode(dd) = bc;

FORM x

        OBJECTS bc = STRING PANEL, d = DATE PANEL

        PROPERTIES count(bc, d), VALUE (bc), VALUE(d)

;





Ao executar este formulário, será gerado um pedido no qual será:

  1. JOIN com a tabela de produtos, o código de barras na tabela SKU corresponde ao especificado;
  2. contando o número de linhas do documento para todas as datas superiores à especificada.


Neste caso, o servidor SQL terá duas opções: executar pelo índice por datas na tabela de linhas ou pelo índice por códigos de barras na tabela de mercadorias, encontrar mercadorias e, em seguida, executar pelo índice por Sku no tabela de linhas. Em ambos os casos, o desempenho deixará muito a desejar (se houver muitos movimentos de um produto e muitos produtos). No lsFusion, para resolver este problema, basta alterar / adicionar as seguintes linhas:





barcode(DocumentDetail dd) = barcode(sku(d)) MATERIALIZED// ,  

   

INDEX barcode(DocumentDetail dd), date(dd);//   





Após essa otimização, o servidor SQL poderá começar a usar o índice composto construído e o desempenho será máximo.



Fontes fechadas e licenças



- . Microsoft, , .Net, Linux.







, , — ERP-, , : — . , .







lsFusion LGPL v3 , , ( ), . GitHub. Maven-, Maven: compile, install, package .. , , GitHub Projects. , .









. lsFusion . , ( ), ( ).







( ), , ( ).







lsFusion , tutorial, , .









lsFusion . ( ), . , ( ) .







, , , , , . :





invoice (InvoiceDetail id) = DATA Invoice;

sum = GROUP SUM sum(InvoiceDetail id) BY invoice(id) //  sum   

  Invoice (    invoce,    - Invoice)



FORM myForm

    OBJECTS myObject = MyClass

;

filtered = FILTER myForm.myObject ; //  filtered      

MyClass (    myObject  myForm)









, , - , custom-made . , , . , / «», .







lsFusion . :







  1. ( , — ) — - . , , , , / .
  2. — . - - (, ).
  3. — , ( ). , - ( «» / , ).
  4. , ( ). , this, , lsFusion , - «».
  5. — , , - ( )


, , , lsFusion ( ), lsFusion / , .







, «» lsFusion — ( ) , , . ( , ), ( ).









, , Everything as code . lsFusion.







, , lsFusion . , , ( ). lsFusion IDEA : , , , .. -, , .









, , , — 1, ERP-. , , , :







  1. .
  2. , , , .


lsFusion : - , - . - , .







, lsFusion:
  1. . “ - ”. Java . , 1, lsFusion . , , , . , . . , .







    , lsFusion — lsFusion ANTLR, IDEA Grammar-Kit (), JFlex ().





  2. UI. - Java SE (Swing, Web Start), , . , , -, - .







    - lsFusion :





    • GWT — Java (), . , , , , GWT , . GWT JavaScript, JavaScript







      , GWT , TypeScript . :







      ) - TypeScript - ;







      ) lsFusion GWT , , .







      - TypeScript, , .





    • Full Calendar, Leaflet — “” ( ).
    • Spring Security, MVC, DI — , , (, ).
  3. BI — “” lsFusion “ ”. :





    • pivot-table, subtotal — BI, ( ),
    • plotly — ,
    • tableToExcel — Excel ( , collapsible ..).


    , ( , ), open-source, - — .





  4. . lsFusion — JasperReports.







    . 1 , , , , :







    ) , , , 4 ;







    ) “”, pixel-perfect .







    lsFusion : ( renderer’, , . .), . BI ( , . .), ( ).





  5. IDE. IDE, IDEA (Eclipse ), IDEA . , , IDEA , . IDEA ( IntelliJ Platform) IDE, , lsFusion ( , lsFusion ). stub index’, chameleon element' lsFusion (, , ).
  6. . Everything as code , , , Git. , Subversion (, , ).
  7. / . EaC / Java, Maven ( lsFusion repo.lsfusion.org).







    Maven- pom.xml :







    <repositories>
            <repository>
                <id>lsfusion</id>
                <name>lsFusion Public Repository</name>
                <url>http://repo.lsfusion.org</url>
            </repository>
    </repositories>
    
          
          





    , Maven Java . , , Maven , pom.xml.







    <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.2</version>
    </dependency>
    
          
          





    IDE, .





  8. . JDBC, / . Postgres ( Docker, yum ..)







    Java Spring, .











, lsFusion LGPL v3.0, , , , lsFusion . , lsFusion , , . , lsFusion , , , , / , . -? , «-» , , , — , -. , ( , , «as is», «to be»). , , , «», , :







  • — , , . «», — .
  • ,


, lsFusion (- / lsFusion, ), (, , ).







, , . , , / , , , .







. , ( - ), ( / ). ( IT) , , , ( ). MyCompany. , , , , , , .









, , - — . , . , , , :







  1. - ( ), , / . .
  2. , , , ( , , ). , , , , . , 30 3000 , - .


, , . , lsFusion , 1 ERP-.







, :

«» ( )



( , ) , / .









( ), , , - . . . .







( Google docs)



, ( , , , ).









, ( ). , .









1, , . ( ), , , , , ( ). , :







  1. , .
  2. , , , « » ( , ).


/



:







  • — , drag-drop .
  • — WYSIWYG , - ( ).
  • — > ( -> , ).
  • , — ( )


, ( -).







/



1 :







  • — , (, , Odoo lsFusion)
  • — renderer, / , , , «» js- ( , ).


( )



, :







  • ( )
  • ( / )
  • ..


1 «-» , 1 / , , .









, « 1», — - 1 lsFusion ( , ). , 1- , .










All Articles