¿Por qué lsFusion y no 1C?





Artículo anterior "¿Por qué no 1C?" salió hace más de un año y despertó un gran interés (solo un poco menos de 100 mil visitas y 2 mil comentarios). Sin embargo, como era de esperar, surgieron muchas preguntas razonables: "Si no es él, ¿quién?". Por supuesto, como muchos han entendido, ese artículo no fue escrito así, sino para lanzar otro después, donde se le diga cómo se pueden y se deben resolver los problemas descritos en el primer artículo. Sin embargo, por varias razones, la publicación de este artículo de "respuesta" se retrasó durante mucho tiempo. Pero como dicen, más vale tarde que nunca.







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







« 1?» ( ):









1 , lsFusion.







: , ..



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







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




Dado que lsFusion intenta aprovechar al máximo el servidor SQL y no el servidor de aplicaciones para ejecutar la lógica de cálculo (y lo hace agrupando las consultas tanto como sea posible para ejecutarlas lo menos posible), la operación de leer un El objeto en lsFusion no existe en principio. Como consecuencia, tanto el problema N + 1 como el problema de sobrelectura en lsFusion son extremadamente raros. Por ejemplo, la siguiente acción:





fillSum(Invoice i) {

    FOR invoice(InvoiceDetail id) = i DO

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

}





Se compilará en un solo paso:

fillSum(Invoice i) {

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

}





El cual, a su vez, se ejecutará con una consulta, en la que solo se leerán / escribirán las filas / columnas utilizadas.



Tablas / Vistas: 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) -     

//  ..





Y en las próximas versiones, lo más probable es que aparezca ese azúcar sintáctico. Otra cosa es que, con mayor frecuencia, en proyectos complejos, los registros tienen una estructura más compleja (por ejemplo, se heredan entre sí, desnormalizan datos para índices compuestos, se expanden en diferentes módulos, etc.), por lo que dicho azúcar puede ser importante solo para Desarrollo RAD (y más precisamente, creación de prototipos), que ya no es tan relevante en el mundo moderno de la TI.



Los registros se admiten en casos muy especiales



Como se mencionó anteriormente, los registros en lsFusion no son una gran combinación, sino varios mecanismos diferentes, cuya clave, quizás, es el mecanismo de materialización (registro y actualización automática de datos calculados en tablas).







1, lsFusion , . , lsFusion :







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




lsFusion admite restricciones y eventos en general, incluidos los datos no materializados calculados. Entonces, por ejemplo, para crear una restricción de que el resto (que se puede calcular usando cualquier número de datos / operadores diferentes) debe ser mayor que 0, es suficiente escribir solo una línea:





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





En consecuencia, la propia plataforma, de la manera más eficiente posible (utilizando cálculos incrementales), comprobará que ningún cambio (por ejemplo, un cambio en el almacén del recibo o la cantidad de consumo) violará esta limitación.

Además, de la misma manera, puede crear, por ejemplo, notificaciones sobre cambios de cualquier dato, incluidos los calculados:





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

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

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





Solo se pueden usar constantes en los parámetros de la tabla virtual



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





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





La plataforma enviará automáticamente la condición de nombre restrictivo (y como consecuencia de la fecha en la que se calculará el resto) en la subconsulta (y todas las subconsultas dentro de esta subconsulta), realizando así la optimización de empuje hacia abajo de predicado . Además, a diferencia del mismo SQL, la plataforma es capaz de realizar esta optimización no solo para agrupaciones, sino también para particiones e incluso para recursiones. Sin embargo, este es un tema para un artículo separado, no nos detendremos en él en detalle aquí.



Consultas



, lsFusion SQL ( ), , . , , .









lsFusion, :







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


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









LsFusion tiene un motor de optimización de consultas muy poderoso internamente, en muchos casos realizando optimizaciones que incluso los costosos DBMS comerciales (y mucho menos PostgreSQL) no pueden hacer. Entonces, todos los problemas de rendimiento descritos en el artículo "¿Por qué no SQL?" , LsFusion puede resolverlos de forma independiente sin acciones adicionales por parte del desarrollador, quien, en consecuencia, puede concentrarse en resolver problemas comerciales y no pensar en cómo escribir una consulta correctamente y / o en que tabla temporal poner su resultado.







Entonces, un ejemplo de un artículo sobre 1C en lsFusion se verá así:







Ejemplo del artículo

    .,
    .

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

    . = & 
    (. < . 
        .  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);

}





En consecuencia, no es necesario escribir una "Nomenclatura EN (SELECCIONE Nomenclatura DE Document.Invoice.Content WHERE Reference = & Document)" en lsFusion.



SQL



SQL-92, ( SQL — ), lsFusion :







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


lsFusion - ( GROUP BY ).









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







Sin embargo, en el mismo 1C, las consultas son compatibles solo para operaciones de lectura de datos; para escribir, aún debe usar mecanismos ORM, cuyo rendimiento deja mucho que desear. En lsFusion, no existe tal problema, y ​​todas las operaciones, incluida la creación de objetos, se pueden realizar en el servidor de la base de datos y con una sola solicitud. Por ejemplo:





generateCards() {

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

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

}







En última instancia, se compilará en una solicitud (o varias, pero su número no dependerá de la cantidad de datos) y se ejecutará muy rápidamente, y todos los eventos / restricciones / agregaciones también serán ejecutados / verificados / recalculados por un limitado número de solicitudes (de nuevo, independientemente de la cantidad de datos).

Lo mismo se aplica al mecanismo para cambiar / eliminar una gran cantidad de datos / objetos:





FOR sum(DiscountCard d) > 10000 DO

    vip (d) ← TRUE;

FOR sum(DiscountCard d) > 10000 DO

    DELETE d;





Se compilará para:

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

DELETE DiscountCard d WHERE sum(d) > 10000;





Y nuevamente, se ejecutará en una solicitud.





( ) 1, . :







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


lsFusion. , 1 ( ) lsFusion:







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




lsFusion — , / .







:



A diferencia de 1C en lsFusion, el flujo de ejecución es el mismo tanto para el servidor como para el cliente. Esta unidad simplifica enormemente la interacción con el dispositivo usuario / cliente en términos del proceso de desarrollo. Entonces, el ejemplo en el artículo sobre 1C está escrito en el lenguaje lsFusion y, en consecuencia, se ve así:





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//    

         }





Hasta cierto punto, lsFusion utiliza el enfoque de las formas convencionales en 1C, solo que lo hace mucho más escalable y productivo. De hecho, toda la magia de la asincronía permanece oculta, y el desarrollador puede concentrarse estrictamente en resolver problemas comerciales y no pensar en dónde y cómo se debe ejecutar el código que escribe.

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









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







lsFusion , , , , .







WYSIWYG:



, 1 , ( ), 2 :







  • - , / ().
  • .


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







/



En lsFusion, al configurar propiedades, filtros y otros elementos en un formulario, puede acceder a todos los objetos a la vez, incluso si aparecen en diferentes listas (u otras vistas). Al mismo tiempo, la propia plataforma monitorea los cambios en los objetos (así como los cambios en los datos) y actualiza automáticamente los datos del formulario utilizando estos objetos. Por ejemplo, si crea el siguiente formulario:





FORM balance

    OBJECTS st = Stock, sk = Sku

    PROPERTIES (st) name

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

    FILTERS currentBalance(st, sk)

;





Cuando mueva el registro actual en la lista superior (almacenes), la lista inferior (productos que están en el almacén seleccionado) se actualizará automáticamente.



Niveles redundantes de abstracción



El principio principal al crear lsFusion fue y sigue siendo el principio: la pureza y la integridad de todas las abstracciones creadas. Asi que:







  • 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?» , , , , . , , .







Como se mencionó en la sección anterior, el mapeo de la lógica de datos en lsFusion a una base de datos relacional es transparente y puede ser completamente controlado por el desarrollador. Junto con las materializaciones en general y los índices, un desarrollador (e incluso un administrador) puede lograr casi cualquier rendimiento, incluso con grandes cantidades de datos. Además, dado que la propia plataforma monitorea los cambios en el modelo físico y actualiza la estructura de la base de datos sin migraciones adicionales, el proceso de optimización del rendimiento puede (y debe) realizarse en una base de datos en ejecución cuando se conocen las estadísticas y opciones para usar esta base de datos. Digamos que tenemos un ejemplo simple:





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)

;





Al ejecutar este formulario se generará una solicitud en la que estará:

  1. UNIRSE con la tabla de productos, el código de barras en la tabla de SKU coincide con el especificado;
  2. contando el número de líneas de documento para todas las fechas superiores a la especificada.


En este caso, el servidor SQL tendrá dos opciones: ejecutar por el índice por fechas en la tabla de filas, o por el índice por códigos de barras en la tabla de bienes, buscar bienes y luego ejecutar por el índice por Sku en el tabla de filas. En ambos casos, el rendimiento dejará mucho que desear (si hay muchos movimientos de un producto y muchos productos). En lsFusion, para solucionar este problema, basta con cambiar / agregar las siguientes líneas:





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

   

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





Después de dicha optimización, el servidor SQL podrá comenzar a utilizar el índice compuesto construido y el rendimiento será máximo.



Licencias y fuentes cerradas



- . 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