Warum lsFusion und nicht 1C?





Vorheriger Artikel "Warum nicht 1C?" kam vor mehr als einem Jahr heraus und erregte großes Interesse (nur ein bisschen weniger als 100.000 Aufrufe und 2.000 Kommentare). Wie erwartet stellte sich jedoch so manche vernĂŒnftige Frage: "Wenn nicht er, wer dann?" NatĂŒrlich wurde dieser Artikel, wie viele verstanden haben, nicht einfach so geschrieben, sondern um einen weiteren Artikel danach zu veröffentlichen, in dem erklĂ€rt wird, wie die im ersten Artikel beschriebenen Probleme gelöst werden können und sollten. Aus verschiedenen GrĂŒnden verzögerte sich die Veröffentlichung dieses "Antwort" -Artikels jedoch sehr lange. Aber wie sie sagen, besser spĂ€t als nie.







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







« 1?» ( ):









1 , lsFusion.







: , ..



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







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




Da lsFusion versucht, den SQL-Server und nicht den Anwendungsserver optimal zu nutzen, um die Berechnungslogik auszufĂŒhren (und dies durch Gruppieren von Abfragen so weit wie möglich, um sie so wenig wie möglich auszufĂŒhren), ist der Vorgang des Lesens eines Ganzen Objekt in lsFusion existiert prinzipiell nicht. Infolgedessen sind sowohl das N + 1-Problem als auch das Überleseproblem in lsFusion Ă€ußerst selten. Zum Beispiel die folgende Aktion:





fillSum(Invoice i) {

    FOR invoice(InvoiceDetail id) = i DO

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

}





Es wird in einem Schritt kompiliert:

fillSum(Invoice i) {

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

}





Was wiederum mit einer Abfrage ausgefĂŒhrt wird, in der nur die verwendeten Zeilen / Spalten gelesen / geschrieben werden.



Tabellen / Ansichten: Register



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

//  ..





Und in den nĂ€chsten Versionen wird ein solcher syntaktischer Zucker höchstwahrscheinlich auftreten. Eine andere Sache ist, dass Register in komplexen Projekten meistens eine komplexere Struktur haben (zum Beispiel erben sie voneinander, denormalisieren Daten fĂŒr zusammengesetzte Indizes, erweitern in verschiedenen Modulen usw.), so dass ein solcher Zucker nur fĂŒr wichtig sein kann RAD-Entwicklung (und genauer Prototyping), die in der modernen IT-Welt nicht mehr so ​​relevant ist.



Register werden in ganz besonderen FĂ€llen unterstĂŒtzt



Wie oben erwĂ€hnt, sind Register in lsFusion kein einziger großer MĂ€hdrescher, sondern mehrere verschiedene Mechanismen, deren SchlĂŒssel möglicherweise der Materialisierungsmechanismus ist (Aufzeichnung und automatische Aktualisierung berechneter Daten in Tabellen).







1, lsFusion , . , lsFusion :







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




lsFusion unterstĂŒtzt EinschrĂ€nkungen und Ereignisse im Allgemeinen, einschließlich berechneter nicht materialisierter Daten. Um beispielsweise eine EinschrĂ€nkung zu erstellen, dass der Rest (der mit einer beliebigen Anzahl unterschiedlicher Daten / Operatoren berechnet werden kann) grĂ¶ĂŸer als 0 sein muss, reicht es aus, nur eine Zeile zu schreiben:





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





Dementsprechend wird die Plattform selbst so effizient wie möglich (unter Verwendung inkrementeller Berechnungen) prĂŒfen, ob keine Änderung (z. B. eine Änderung im Lager des Belegs oder der Verbrauchsmenge) gegen diese EinschrĂ€nkung verstĂ¶ĂŸt.

Auf die gleiche Weise können Sie beispielsweise Benachrichtigungen ĂŒber Änderungen von Daten, einschließlich berechneter Daten, erstellen:





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

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

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





In virtuellen Tabellenparametern können nur Konstanten verwendet werden



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





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





Die Plattform ĂŒbertrĂ€gt automatisch die Bedingung fĂŒr den einschrĂ€nkenden Namen (und als Folge des Datums, an dem der Rest berechnet wird) in die Unterabfrage (und alle Unterabfragen innerhalb dieser Unterabfrage) und fĂŒhrt so die PrĂ€dikat- Pushdown-Optimierung durch . DarĂŒber hinaus kann die Plattform im Gegensatz zu demselben SQL diese Optimierung nicht nur fĂŒr Gruppierungen, sondern auch fĂŒr Partitionen und sogar fĂŒr Rekursionen durchfĂŒhren. Dies ist jedoch ein Thema fĂŒr einen separaten Artikel, auf den wir hier nicht nĂ€her eingehen werden.



Anfragen



, lsFusion SQL ( ), , . , , .









lsFusion, :







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


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









LsFusion verfĂŒgt intern ĂŒber eine sehr leistungsstarke Engine zur Abfrageoptimierung, die in vielen FĂ€llen Optimierungen durchfĂŒhrt, die selbst teure kommerzielle DBMS (geschweige denn PostgreSQL) nicht können. Alle Leistungsprobleme, die im Artikel "Warum nicht SQL" beschrieben sind , können von lsFusion unabhĂ€ngig gelöst werden, ohne dass der Entwickler zusĂ€tzliche Maßnahmen ergreifen muss, der sich dementsprechend auf die Lösung von GeschĂ€ftsproblemen konzentrieren kann und nicht darĂŒber nachdenkt, wie Schreiben Sie eine Abfrage korrekt und / oder in welche temporĂ€re Tabelle das Ergebnis gestellt werden soll.







Ein Beispiel aus einem Artikel ĂŒber 1C in lsFusion sieht also folgendermaßen aus:







Beispiel aus dem Artikel

    .,
    .

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

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

}





Dementsprechend muss keine "Nomenklatur IN (SELECT Nomenclature FROM Document.Invoice.Content WHERE Reference = & Document)" in lsFusion nicht geschrieben werden.



SQL



SQL-92, ( SQL — ), lsFusion :







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


lsFusion - ( GROUP BY ).









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







In derselben 1C werden Abfragen jedoch nur fĂŒr DatenlesevorgĂ€nge unterstĂŒtzt. Zum Schreiben mĂŒssen Sie noch ORM-Mechanismen verwenden, deren Leistung zu wĂŒnschen ĂŒbrig lĂ€sst. In lsFusion gibt es kein solches Problem, und alle VorgĂ€nge, einschließlich der Erstellung von Objekten, können auf dem Datenbankserver und mit einer Anforderung ausgefĂŒhrt werden. Zum Beispiel:





generateCards() {

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

            number(d) â† â€˜Card:’+i;

}







Letztendlich wird es zu einer Anfrage (oder mehreren) kompiliert, aber ihre Anzahl hĂ€ngt nicht von der Datenmenge ab. Es wird sehr schnell ausgefĂŒhrt, und alle Ereignisse / EinschrĂ€nkungen / Aggregationen werden auch von einer begrenzten Anzahl ausgefĂŒhrt / geprĂŒft / neu berechnet Anzahl der Anfragen (wiederum unabhĂ€ngig von der Datenmenge).

Gleiches gilt fĂŒr den Mechanismus zum Ändern / Löschen einer großen Menge von Daten / Objekten:





FOR sum(DiscountCard d) > 10000 DO

    vip (d) â† TRUE;

FOR sum(DiscountCard d) > 10000 DO

    DELETE d;





Wird kompiliert zu:

sum(DiscountCard d) â† TRUE  WHERE sum(d) > 10000;

DELETE DiscountCard d WHERE sum(d) > 10000;





Und wieder wird es in einer Anfrage ausgefĂŒhrt.





( ) 1, . :







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


lsFusion. , 1 ( ) lsFusion:







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




lsFusion — , / .







:



Im Gegensatz zu 1C in lsFusion ist der AusfĂŒhrungsfluss sowohl fĂŒr den Server als auch fĂŒr den Client gleich. Diese Einheit vereinfacht die Interaktion mit dem Benutzer / Client-GerĂ€t im Hinblick auf den Entwicklungsprozess erheblich. Das Beispiel in dem Artikel ĂŒber 1C ist also in der Sprache lsFusion geschrieben und sieht dementsprechend folgendermaßen aus:





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

         }





Bis zu einem gewissen Grad verwendet lsFusion den Ansatz herkömmlicher Formen in 1C, macht es jedoch viel skalierbarer und produktiver. TatsĂ€chlich bleibt die ganze Magie der AsynchronitĂ€t unter der Haube, und der Entwickler kann sich streng auf die Lösung von GeschĂ€ftsproblemen konzentrieren und nicht darĂŒber nachdenken, wo und wie der von ihm geschriebene Code ausgefĂŒhrt werden soll.

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









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







lsFusion , , , , .







WYSIWYG:



, 1 , ( ), 2 :







  • - , / ().
  • .


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







/



In lsFusion können Sie beim Festlegen von Eigenschaften, Filtern und anderen Elementen in einem Formular auf alle Objekte gleichzeitig zugreifen, auch wenn sie in verschiedenen Listen (oder anderen Ansichten) angezeigt werden. Gleichzeitig ĂŒberwacht die Plattform selbst Änderungen an Objekten (sowie Änderungen an Daten) und aktualisiert Formulardaten mithilfe dieser Objekte automatisch. Wenn Sie beispielsweise das folgende Formular erstellen:





FORM balance

    OBJECTS st = Stock, sk = Sku

    PROPERTIES (st) name

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

    FILTERS currentBalance(st, sk)

;





Wenn Sie den aktuellen Datensatz in die obere Liste (Lager) verschieben, wird die untere Liste (Produkte, die sich im ausgewÀhlten Lager befinden) automatisch aktualisiert.



Redundante Abstraktionsebenen



Das Hauptprinzip bei der Erstellung von lsFusion war und ist das Prinzip - die Reinheit und VollstÀndigkeit aller erstellten Abstraktionen. So:







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







Wie im vorherigen Abschnitt erwĂ€hnt, ist die Zuordnung der Datenlogik in lsFusion zu einer relationalen Datenbank transparent und kann vom Entwickler vollstĂ€ndig gesteuert werden. Zusammen mit Materialisierungen im Allgemeinen und Indizes kann ein Entwickler (und sogar ein Administrator) nahezu jede Leistung erzielen, selbst bei großen Datenmengen. Da die Plattform selbst Änderungen im physischen Modell ĂŒberwacht und die Datenbankstruktur ohne zusĂ€tzliche Migrationen aktualisiert, kann (und sollte) der Prozess zur Leistungsoptimierung fĂŒr eine laufende Datenbank durchgefĂŒhrt werden, wenn die Statistiken und Optionen fĂŒr die Verwendung dieser Datenbank bekannt sind. Nehmen wir also an, wir haben ein einfaches Beispiel:





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)

;





Bei der AusfĂŒhrung dieses Formulars wird eine Anfrage generiert, in der es sich um Folgendes handelt:

  1. Verbinden Sie sich mit der Produkttabelle. Der Barcode in der SKU-Tabelle stimmt mit dem angegebenen ĂŒberein.
  2. ZĂ€hlen der Anzahl der Dokumentzeilen fĂŒr alle Daten, die grĂ¶ĂŸer als die angegebene sind.


In diesem Fall verfĂŒgt der SQL Server ĂŒber zwei Optionen: Entweder nach dem Index nach Datum in der Zeilentabelle oder nach dem Index nach Barcodes in der Warentabelle, nach Waren suchen und dann nach dem Index von Sku in der Tabelle Zeilentabelle. In beiden FĂ€llen lĂ€sst die Leistung zu wĂŒnschen ĂŒbrig (wenn es viele Bewegungen eines Produkts und viele Produkte gibt). In lsFusion reicht es aus, die folgenden Zeilen zu Ă€ndern / hinzuzufĂŒgen, um dieses Problem zu lösen:





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

   

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





Nach einer solchen Optimierung kann der SQL Server den erstellten zusammengesetzten Index verwenden und die Leistung ist maximal.



Geschlossene Quellen und Lizenzen



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