Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Neues von XtendFlow - Flow-Design auf der JVM

45 views
Skip to first unread message

Denis

unread,
Apr 12, 2015, 3:52:26 PM4/12/15
to event-based...@googlegroups.com
Die XtendFlow-Bibliothek gibt es jetzt auf Maven-Central und Bintray. Dadurch lässt sie sich sehr einfach in eigene Projekte einbinden, wenn man Maven, Ivy oder Gradle benutzt. Zum Beispiel mit Gradle:
dependencies {
  compile
'de.grammarcraft:de.grammarcraft.xtend.flow:0.3.+'
  compile
'org.eclipse.xtend:org.eclipse.xtend.lib:2.8.+'
}

Das Interessantere hat sich allerdings bei der Flow-DSL selbst getan. Eine Funktionsplatine läßt sich jetzt vollständig deklarativ angeben. Z.B.
@FunctionBoard(
    inputPorts
= #[
       
@InputPort(name="input", type=String)
   
],
    outputPorts
= #[
       
@OutputPort(name="lower", type=String),
       
@OutputPort(name="upper", type=String)
   
]
)
class Normalize {
    val toLower
= new ToLower
    val toUpper
= new ToUpper
 
   
new() {
        toLower
.output -> lower
        toUpper
.output -> upper
        input
-> toLower
        input
-> toUpper
   
}
}
Der Konstruktor mit den Verbindungen der Ports ist neben der Instanziierung der Funktionseinheiten der einzige notwendige Code.

Das die Anstoßen eines Flows erfolgt jetzt über eine eigene intuitive Operation:

input <= "a input value"

Derselbe Operator wird auch innerhalb einer Funktionseinheit benutzt, um ein Berechnungsergebnis über einen Ausgabeport weiterzuleiten:

output <= [ if (index > 0) "a value" else "another value" ]

Das Konstrukt rechts von "<=" ist eine Closure (wie sie Xtend erlaubt), die den Ausgabewert berechnet, der über den Output-Port "output" weitergeleitet wird. Es kann aber wie beim Input-Port oben auch einfach ein Literal oder der Wert einer Variablen weitergeleitet werden.

Das ganze lässt sich noch mal im Detail im GitHub-Readme des Projektes nachlesen.
Ausführlicher habe ich die Implementierung in meinem Blog-Artikel dokumentiert.

Ich überlege gerade noch, ob ich nicht die Annotationen FunctionUnit und FunctionBoard in Operation oder FlowOperation und Integration oder FlowIntegration umbenenne, um Ralfs Nomenklatur in seiner IODA Architektur näher zu sein. Anmerkungen hierzu sind natürlich willkommen...

-----
Denis

Denis

unread,
Apr 12, 2015, 4:00:12 PM4/12/15
to event-based...@googlegroups.com
... Alles ging aus irgendeinem Grund nicht in den ersten Post.

Zur Zeit tendiere ich dazu den allgemeinen Namen "FlowUnit" zu verwenden, um daran die Port-Deklaration zu binden. Diese würden dann über zusätzliche Annotationen "Operation" und "Integration" spezialisiert werden. Dadurch könnte man auch leichter Interfaces deklarieren, was jetzt noch gar nicht geht. Also:

@FunctionUnit würde dann zu
@Operation @FlowUnit(@InputPorts=[], @OutputPorts=[]) class XXX {}

@FunctionBoard würde zu
@Integration @FlowUnit(@InputPorts=[], @OutputPorts=[]) class YYY {}


Zusätzlich ließe sich ein Interface einer Funktionseinheit deklarieren als
@FlowUnit(@InputPorts=[], @OutputPorts=[]) interface ZZZ {}


-----
Denis

Ralf Westphal

unread,
Apr 13, 2015, 2:23:08 AM4/13/15
to event-based...@googlegroups.com
Die DSL sieht ja nett aus (auch wenn ich nicht mit Gradle & Co arbeite ;-)
Und mit port <= ... eine Nachricht verschicken zu können, ist intuitiv.

Aber warum man zur DSL noch einen Klassendefinition für das Zusammenbauen des Flows braucht, verstehe ich nicht. Gerade das möchte ich mir ja sparen.

Vielleicht liegt es daran, dass du dich auf die Funktionseinheiten konzentrierst? Statt dich auch die Flows zu fokussieren.

Hier eine noch einfachere DSL, mit der natürlich nicht so viel geht:

produzent | konsument

Um diesen Flow herzustellen, würde ich gern nur Instanzen für produzent und konsument registrieren, z.B.

flowfx.Bind("produzent", new ReadFromFile("myfile.txt"));
flowfx.Bind("konsument", new OutputToConsole());

Und dann wird alles zusammengesetzt:

flowfx.Integrate();

Und dann ausgführt:

flowfx.Run();

Damit kann ich mich auf die Operationen konzentrieren. Die ganze Integration ist definiert in der DSL und wird von einer Runtime (oder einem Compiler) vorgenommen. Ich muss nur die Namen im Flow an konkrete Implementationen binden.

Das funktioniert. Kann man auch mit geschachtelten Flows machen. Hab ich mal für .NET gebaut: https://github.com/ralfw/NPantaRhei



--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.
Weitere Optionen finden Sie unter https://groups.google.com/d/optout.



--
Ralf Westphal - One Man Think Tank
Hans-Henny-Jahnn-Weg 44
D-22085 Hamburg
Germany
Tel 0170-3200458
Email in...@ralfw.de

Denis

unread,
Apr 15, 2015, 5:00:19 PM4/15/15
to event-based...@googlegroups.com
 
Aber warum man zur DSL noch einen Klassendefinition für das Zusammenbauen des Flows braucht, verstehe ich nicht. Gerade das möchte ich mir ja sparen

Mit einer Flow-Runtime geht das ja, da sie der Wirtssprache Ausführungssemantik hinzufügt. Aber XtendFlow ist keine Flow-Runtime. Sie ist eher mit dem ursprünglichen EBC-Ansatz zu vergleichen, nur dass statt der C#-Event-Operationen eben "schönere" DSL-Operationen verwendet werden, die der Notation der Flow-Runtime näher kommen.
Der EBC-Ansatz hatte gegenüber der Flow-Runtime den (einzigen) Vorteil, dass er typsicheres Flow-Design erlaubt. Dies halte ich bei größeren Projekten für einen Vorteil, da kann man jede Hilfe durch die Compilertypprüfung oder die IDE mit Autovervollständigung, QuickFixes und Typdeklarationshoovern gebrauchen. Warum das nicht mitnehmen...
 
Vielleicht liegt es daran, dass du dich auf die Funktionseinheiten konzentrierst? Statt dich auch die Flows zu fokussieren.
 
Ich hoffe nicht. Aber man kommt eben nicht so leicht weg vom Modul-Konzepten der Wirtssprache - war ja bei C#-EBC auch so.
Ausserdem war XtendFlow ursprünglich als erster Schritt hin zu einer Java-Flow-Runtime gedacht...
Aber ehrlich gesagt, stört mich an der Flow-Runtime die typfreie Notation der Flows etwas. Bei größeren Projekten könnte das schnell unübersichtlich werden. Ausserdem bezweifle ich ein bischen, dass der Durchnittsprogrammierer mit einer Notation zurechtkommt, die zur Compile-Zeit typfrei ist. Er benötigen doch meistens die Hilfe seiner IDE um einigemaßen effektiv zu coden/designen (ich nehme mich da gar nicht aus). Am Beispiel dynamischer Programmiersprachen sieht man immer wieder, wie schwer sich die Leute damit im Gegensatz zu typisierten Sprachen tun. Die meisten sind nur noch am googlen um Beispiellösungen zu finden.
 

Hier eine noch einfachere DSL, mit der natürlich nicht so viel geht:

produzent | konsument

Um diesen Flow herzustellen, würde ich gern nur Instanzen für produzent und konsument registrieren, z.B.

flowfx.Bind("produzent", new ReadFromFile("myfile.txt"));
flowfx.Bind("konsument", new OutputToConsole());

Und dann wird alles zusammengesetzt:

flowfx.Integrate();

Und dann ausgführt:

flowfx.Run();

Ich glaube nicht, dass dieses Beispiel in XtendFlow so viel anders aussehen würde:
class RunFlow {
 
def static void main(String[] args) {
     
     
// build
      val produzent
= new ReadFromFile("myfile.txt")
      val konsument
= new OutputToConsole()

     
// bind
     produzent
-> konsument

   
// run
    konsument
<= start // entspricht einem Signal wie '()'
 
}
}

Wirklich anders sind nur die Funktionseinheiten, die ich FunctionBoard genannt hatte, deren einzige Funktion es ist zu integrieren.
Das FunctionBoard Normalize aus meinen Beispiel hätte man in der Flow-Runtime-Notation glaube ich so spezifiziert:
Normalize:
.output, lower
.output, upper
input
, toLower
input
, toUpper

OK, das ist kürzer als im FunctionBoard, aber dafür ist das FuntionBoard schon zur Compile-Zeit typsicher und die IDE unterstützt einen mit Autovervollständigung.
Und man bekommt für jede Abstraktionsebene eines Systems ein eigenes Modul (FunctionBoard), das den Fluß auf dieser Ebene dokumentiert. Benötigt man detailiertere Informationen aus unteren Abstraktionsebenen, zoomt man sich pratkisch hinein, indem man eine der integrierten Klassen öffnet.

Außerdem liesen sich die FunctionBoards auch aus einer Flow-Runtime-Notation generieren, wenn man das Tool dazu hätte. Ich hatte so ein Tool schon mal angefangen, aber alles braucht seine Zeit...

Denis

Denis

unread,
Apr 15, 2015, 5:30:16 PM4/15/15
to event-based...@googlegroups.com
... Die Flow-Runtime-Spezifikation für das Normalize-Beispiel oben ist falsch. Richtig wäre:
Normalize:
.in, toLower
.in, toUpper
toLower
.out, .lower
toUpper
.out, .upper
Hier ist das Flow-Bild dazu: http://blog.grammarcraft.de/wp-content/uploads/2013/07/Bild3-Normalize-reingezoomt1.png
Denis

Ralf Westphal

unread,
Apr 16, 2015, 3:01:47 AM4/16/15
to event-based...@googlegroups.com
hm... ob Runtime, die eine DSL interpretiert oder ein Compiler in Eclipse: ein bisschen mehr Abstraktion bei der Definition hätte ich mir schon erwartet. Wie gesagt, es sieht für mich irgendwie doppeltgemoppelt aus, wenn man dies schreiben muss:

@FunctionBoard(
    inputPorts 
= #[
        
@InputPort(name="input", type=String)
    
],
    outputPorts 
= #[
        
@OutputPort(name="lower", type=String),
        
@OutputPort(name="upper", type=String)
    
]
)
class Normalize {
    val toLower 
= new ToLower
    val toUpper 
= new ToUpper
 
   
new() { 
        toLower
.output -> lower
        toUpper
.output -> upper
        input 
-> toLower
        input 
-> toUpper
    
}
}

Die Zuweisungen an die Felder ist das Binding von Funktionseinheiten im Flow an Implementationen. Ok.

Aber der Rest...?

Das FunctionBoard beschreibt Ports?

Und der ctor? Der beschreibt den Flow, da passiert Integration?

Hm...

Warum beschreibt die Klasse nicht selbst ihre Ports? Warum brauche ich dafür eine Annotation?
Oder umgekehrt: Warum findet die Integration nicht in einer DSL statt und ich kann die Klasse vergessen?

Du siehst, irgendwie wird es für mich nicht wirklich einfach. Vielleicht machst du mal einen größeren Flow, damit man die Vorteile besser sieht. Irgendwas bekanntes wie WordWrap oder CSV Viewer.



--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.
Weitere Optionen finden Sie unter https://groups.google.com/d/optout.

Denis

unread,
Apr 16, 2015, 6:40:30 PM4/16/15
to event-based...@googlegroups.com

hm... ob Runtime, die eine DSL interpretiert oder ein Compiler in Eclipse: ein bisschen mehr Abstraktion bei der Definition hätte ich mir schon erwartet. Wie gesagt, es sieht für mich irgendwie doppeltgemoppelt aus,


Es ist schon ein Unterschied, ob man ein interne DSL in einer Wirtssprache hat, oder eine externe DSL, wie bei der Flow-Runtime!
Es ist auch nicht ganz fair, XtendFlow mit der Flow-Runtime zu vergleichen. Dies ist, als ob man die Flow-Runtime mit dem EBC-Ansatz vergleichen würde. Die XtendFlow und EBC haben denselben Ansatz - einer vorhanden Sprache eine interne DSL mit spezieller Semantik hinzufügen. Bei Xtend geht das etwas besser als bei C#, aber der grundsätzliche Ansatz ist gleich. Die Flow-Runtime geht einen anderen Weg und einen Schritt weiter.

Deswegen macht es Sinn, EBC und XtendFlow gegenüberzustellen.
Ich habe mal versucht, die Normalize-Funktionseinheit in EBC nachzuimplementieren. Im Sinne von IODA sollten Integrationseinheiten ja auch mit EBC realsiert werden können:
    public class Normalize
     
{
         
private Action<string> _toLower, _toUpper;
 
         
public void input(string inpt)
         
{
             _toLower
(inpt);
             _toUpper
(inpt);
         
}
 
         
public event Action<string> lower;
         
public event Action<string> upper;
 
 
         
// build
         
ToLower toLower = new ToLower();
         
ToUpper toUpper = new ToUpper();
 
         
public Normalize ()
         
{
             _toLower
= toLower.input;
             _toUpper
= toUpper.input;
             toLower
.output += o => this.lower (o);
             toUpper
.output += o => this.upper (o);
         
}
     
}

Zum besseren Verständnis der Notationssemantik von XtendFlow habe ich mal beide Implementierungen nebeneinander gestellt und äquivalenten Bedeutungsträger miteinander verbunden:

https://lh3.googleusercontent.com/-qyEvGsU0-JU/VTAxaUUbvII/AAAAAAAABIU/T2vaEGIEsRE/s1600/Gegen%C3%BCberstellung-XtendFlow-EBC-Normalize.jpg

Dies macht Notation in XtendFlow hoffentlich klarer.

Das FunctionBoard beschreibt Ports?

Ja, es deklariert typisierte Ports. Die Annotationschreibweise ist etwas sehr gesprächig, aber da bin ich an die Wirtssprache gebunden.
Das ist auch eine echte Deklaration der Portnamen. Ohne diese würde es die Ports unten im Konstruktor bei der Flow-Spezifikation sprachtechnisch gar nicht geben.
Lies das einfach als
functionboard Normalize
   inputport
String input
   outputport
String lower
   outputport
String upper
{ ... }



Und der ctor? Der beschreibt den Flow, da passiert Integration?

Genau. Das ist von der Notation her fast identisch zur Notation der Flow-Runtime, nur eben typisiert.
 

Hm...

Warum beschreibt die Klasse nicht selbst ihre Ports? Warum brauche ich dafür eine Annotation?

Die Annotation wird benötigt, weil es in Xtend (und Java) das Sprachkonzept der Events nicht gibt. Ohne die Annotation, mit direkter Deklaration der Ports als irgendwie geartete Member der Klasse wäre der Deklarationsaufwand signifikant höher und damit der Code wesentlich umfangreicher. Der eigentliche Zweck - Deklaration eines Ports - wäre kaum noch wiederzuerkennen (siehe z.B. der Realsierungsversuch bei jEBC für Java). Die Lesbarkeit würde stark leiden.
Die Xtend-Annotation ist keine Annotation wie in Java oder Attribute in C#. Xtend-Annotationen können eine Klasse um zusätzliche Memberelemente anreichern. Genau das wird hier getan, um Infrastruktur für die fehlenden Events nachzubilden und die interne DSL etwas reicher zu machen.
Wegen der etwas reicheren DSL ist die Implementierung in Xtend am Ende auch kürzer als in C#.


Du siehst, irgendwie wird es für mich nicht wirklich einfach. Vielleicht machst du mal einen größeren Flow, damit man die Vorteile besser sieht. Irgendwas bekanntes wie WordWrap oder CSV Viewer.

Ja, das hatte ich sowieso noch vor.


Denis

Ralf Westphal

unread,
Apr 17, 2015, 3:09:41 AM4/17/15
to event-based...@googlegroups.com
Hm... Ich glaube, ich sehe nun ein Missverständnis: IODA (oder die dahinter stehenden Prinzipien IOSP und PoMO) verlangen eben keine EBC! Das ist mir sehr wichtig.

EBC war der Anfang von Flow Design. Aber EBC sind nicht das Ende und ich benutze EBC nur noch sehr selten. Sie Übersetzung einer Flow Funktionseinheit in eine EBC macht manchmal Sinn - viel häufiger ist sie aber viel zu umständlich. Das Normalize-Beispiel ist schon so ein Fall. Ohne EBC sähe das für mich so aus:

void Normalize(string input, Action<string> lowercased, Action<string> uppercased) {
  lowercased(s1.ToLower(input));
  uppercased(s2.ToUpper(input));
}

Wo die Funktionen ToLower()/ToUpper() herkommen, ist egal. Ich habe mal zwei Dienstobjekte s1 und s2 angenommen. Sie können aber auch auf demselben Objekt oder statisch oder sonstwie definiert sein.

Jedenfalls ist das alles, was nötig ist, um einen Flow zu verdrahten, der einen Input durch zwei Funktionseinheiten fließen lässt und zwei Outputs erzeugt.


--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.
Weitere Optionen finden Sie unter https://groups.google.com/d/optout.

Denis

unread,
Apr 17, 2015, 5:38:21 PM4/17/15
to event-based...@googlegroups.com
Am Freitag, 17. April 2015 09:09:41 UTC+2 schrieb Ralf Westphal:
Hm... Ich glaube, ich sehe nun ein Missverständnis: IODA (oder die dahinter stehenden Prinzipien IOSP und PoMO) verlangen eben keine EBC! Das ist mir sehr wichtig.

Na, das habe ich ja auch nicht behauptet und folge Dir da ganz und gar. Ich meinte nur, dass IODA ja allgemeingültig ist, und deswegen müssen sich  in XtendFlow wie in EBC Komponenten realsieren lassen, deren einzige Funktion die der Integration ist. Und da beide sich in ihren Konzepten sehr nahe sind (schließlich hatte ich mit EBC als Vorlage für ScalaFlow angefangen, und über ScalaFlow bin ich dann zu XtendFlow gekommen), wollte ich an einem EBC-Beispiel die Notationssemantik von XtendFlow klarmachen. Nur deswegen habe ich zu EBC gegriffen...
 

EBC war der Anfang von Flow Design. Aber EBC sind nicht das Ende und ich benutze EBC nur noch sehr selten. Sie Übersetzung einer Flow Funktionseinheit in eine EBC macht manchmal Sinn - viel häufiger ist sie aber viel zu umständlich. Das Normalize-Beispiel ist schon so ein Fall. Ohne EBC sähe das für mich so aus:

void Normalize(string input, Action<string> lowercased, Action<string> uppercased) {
  lowercased(s1.ToLower(input));
  uppercased(s2.ToUpper(input));
}

Wo die Funktionen ToLower()/ToUpper() herkommen, ist egal. Ich habe mal zwei Dienstobjekte s1 und s2 angenommen. Sie können aber auch auf demselben Objekt oder statisch oder sonstwie definiert sein.

Unterschätze die Ausdruckskraft von Schemata nicht! Und Sprachkonstrukte mit Schlüsselwörtern sind am Ende Schemata an die Sprachsemantik oder konzeptionelle Semantik gebunden wird. Design- und Code-Patterns funktionieren ähnlich haben aber eine wesentlich schwächeren Wiedererkennungswert als Sprachkonstrukte.
Dein Beispiel oben würde ich eher einem Code-Pattern zuordnen. Aber in umfangreicherem Code wäre dies nur eine Funktion von vielen. Wie außer an ihrer Struktur eine integrierenden Funktionseinheit eines Flows wiedererkennen? OK, der Action-Typ könnte einen Hinweis liefern. Aber der ist nur ein notwendiges Kriterium, aber kein hinreichendes. Action könnten auch in Nicht-Flow-Funktionen verwendet werden.
Folgendes wäre da, glaube ich, viel besser wiederzuerkennen (über Namen und deren Länge lässt sich natürlich streiten)?

[FunctionBoard]
void Normalize([InputPort] string input, [OutputPort] Action<string> lowercased, [OutputPort] Action<string> uppercased) {
  lowercased
(s1.ToLower(input));
  uppercased
(s2.ToUpper(input));
}

Und ich denke, Semantik über Schemata wiederzuerkennen ist wichtig, um Code effektiv lesen zu können. Je einfacher das geht, um so besser. Schließlich lesen wir mehr Code als das wir ihn schreiben. Und nicht umsonst gibt es Sprachen, die bestimmte Paradigmen bedienen. Man könnte auch in C objektorientiert programmieren - aber es tut keiner, weil es "bequemere" objektorientierte Sprachen gibt, in denen sich ein objektorientiertes Modell prägnanter und kürzer und mit höherem Wiedererkennungswert umsetzen lässt.
XtendFlow stellt solche Sprachkonstrukte zur Verfügung um Wiedererkennung zu vereinfachen. Das ist nicht ideal, aber eben so gut es in Xtend geht. (...Und es geht ganz schön gut, finde ich.)

Flow-Design ist ein Paradigma - es braucht auch seine eigene paradigmengerechte Programmiersprache! (Ich meine damit nicht, das XtendFlow das wäre!) Vielleicht ist es dafür noch zu früh, aber ich denke, dass die Existenz einer Flow-Design-Sprache ein Notwendigkeit ist, damit sich Flow-Design als Paradigma durchsetzen kann und angenommen wird. Was denkst Du?
 

Jedenfalls ist das alles, was nötig ist, um einen Flow zu verdrahten, der einen Input durch zwei Funktionseinheiten fließen lässt und zwei Outputs erzeugt.

Syntactic Sugar ist nicht unbedingt notwendig, man kann es auch spartanischer haben. Aber wie bei kulinarischen Süßigkeiten kann es helfen andere (im guten Sinne) zu verführen...
 


Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-components+unsub...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.

Ralf Westphal

unread,
Apr 18, 2015, 2:40:23 AM4/18/15
to event-based...@googlegroups.com
Ich geb dir Recht, eine Konvention ist schwächer als Syntax. Am Anfang war Objektorientierung nur eine Konvention - der erste C++ Compiler mit dem ich 1990 gearbeitet habe, hat noch C++ in C Quellcode nach solcher Konvention übersetzt -, aber dann gab es Sprachen, die die Konvention formalisiert haben.

Funktionale Sprachen bieten schon etwas Syntax für Flows, z.B. F#:

x |> f |> g

In anderen Sprachen versucht man es mit Fluent Interfaces verschiedener Frameworks (z.B. Linq, Rx, TPL Dataflow).

Allen gemein ist jedoch, dass die Trennung von Integration und Operation darin nur eine Konvention ist.

Um einen großen Schritt voranzukommen wäre es nötig, genau diese Unterscheidung aber zu formalisieren. Die Trennung darf nicht optional sein. Das sehe ich aber nur mit einer DSL für Flows als möglich, die extern ist. Ob die von einer Runtime interpretiert wird oder von einem Compiler nach C# oder IL übersetzt wird, ist egal.

Mit NPantaRhei gab es diese DSL. Aber die Verzahnung mit C# war wieder nur reine Konvention. Das müsste natürlich auch besser werden.

Wenn man ein Programm mit der Flow DSL (FDSL) schreibt, muss man wie in C# Projekten anderen Code referenzieren können. Der steht dann passend zur Verfügung. Der Compiler (oder gar die IDE) prüft sofort, ob der Flow syntaktisch korrekt zusammengesteckt ist.

Das sollte auch nicht nur für EBC funktionieren, sondern ebenso für Funktionseinheiten, die als normale Funktionen realisiert sind.

Das Problem bei einer textuellen Sprache für Flows bleiben jedoch 2D-Flows. Die kennen selbst die FPler ja nicht wirklich, weil sie sie nicht vernünftig in ihrer Sprache ausdrücken können.

Also ist Flow Design am Ende eh nur wirklich expressiv mit einer visuellen DSL möglich. Die braucht eine textuelle Entsprechung zur Serialisierung. Doch die müsste dann nicht mehr auf Lesbarkeit für Menschen optimiert sein.

NoFlo/FlowHub scheint mir da im Moment das, was am dichtesten rankommt: https://flowhub.io


Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.



--
Ralf Westphal - One Man Think Tank
Hans-Henny-Jahnn-Weg 44
D-22085 Hamburg
Germany
Tel 0170-3200458
Email in...@ralfw.de

--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.

Denis

unread,
Apr 20, 2015, 5:32:43 PM4/20/15
to event-based...@googlegroups.com
Am Samstag, 18. April 2015 08:40:23 UTC+2 schrieb Ralf Westphal:
Ich geb dir Recht, eine Konvention ist schwächer als Syntax. [...]
In anderen Sprachen versucht man es mit Fluent Interfaces verschiedener Frameworks (z.B. Linq, Rx, TPL Dataflow).

Allen gemein ist jedoch, dass die Trennung von Integration und Operation darin nur eine Konvention ist.

Um einen großen Schritt voranzukommen wäre es nötig, genau diese Unterscheidung aber zu formalisieren. Die Trennung darf nicht optional sein. Das sehe ich aber nur mit einer DSL für Flows als möglich, die extern ist. Ob die von einer Runtime interpretiert wird oder von einem Compiler nach C# oder IL übersetzt wird, ist egal.

Ja, der Meinung bin ich auch, deswegen hatte ich eine einfache DSL (mit Xtext) angefangen. Die Idee war, eine Sprache ähnliche Deiner Notation für die FlowRuntime zu haben, nur dass die Verbindungen typsicher sind, Zyklen im Flow erkannt werden und Operationen aus externen Klassen (implementiert oder nicht) nahtlos in diese Flows integriert (mit IDE-Unterstützung) werden können. Zunächst sollte dann daraus entweder Integrationseinheiten für XtendFlow- oder ScalaFlow erzeugt werden.
Das Projekt war schon recht weit gediehen: https://github.com/kuniss/FlowPlugin. Allerdings hatte ich die Fertigstellung zurückgestellt, um XtendFlow über MavenCentral zur Verfügung zu stellen und ein paar kleinere Xtend-Probleme zu lösen. Beim Grübeln über die kleineren Probleme fiel mir dann auf, dass man die interne Flow-DSL noch vervollständigen und wesentlich komfortabler, Deiner Notation ähnlicher machen könnte. Na und dann kam eins zum anderen und es zog sich etwas hin. Kann mich leider nicht werktagsüber damit beschäftigen...
 
Wenn man ein Programm mit der Flow DSL (FDSL) schreibt, muss man wie in C# Projekten anderen Code referenzieren können. Der steht dann passend zur Verfügung. Der Compiler (oder gar die IDE) prüft sofort, ob der Flow syntaktisch korrekt zusammengesteckt ist.  

Das sollte auch nicht nur für EBC funktionieren, sondern ebenso für Funktionseinheiten, die als normale Funktionen realisiert sind.

Für C# geht das leider mit dem von mir angefangen Eclipse-Plugin nicht so einfach, weil es eben erst mal auf die JVM-Welt beschränkt ist. Aber XtendFlow-annotierte Operationen lassen sich nahtlose integrieren. Ähnliches wäre in einem zweiten Schritt sicher auch für entsprechend annotierte Funktionan a la
void Normalize([InputPort] string input, [OutputPort] Action<string> lowercased, [OutputPort] Action<string> uppercased)
denkbar.
Immerhin könnte demnächst mein Plugin neben Eclipse auch für IntelliJ IDEA (einer in der Java-Welt recht verbreitete IDE) bereitstehen, da das Xtext-Team gerade einer Portierung dafür vornimmt. So dass es nicht zu stark auf Eclipse-Benutzer beschränkt wäre.
 

Das Problem bei einer textuellen Sprache für Flows bleiben jedoch 2D-Flows. Die kennen selbst die FPler ja nicht wirklich, weil sie sie nicht vernünftig in ihrer Sprache ausdrücken können.

Also ist Flow Design am Ende eh nur wirklich expressiv mit einer visuellen DSL möglich. Die braucht eine textuelle Entsprechung zur Serialisierung. Doch die müsste dann nicht mehr auf Lesbarkeit für Menschen optimiert sein.

Ich weiß nicht, meine Erfahrungen mit grafischen Editier-Tools ist die, dass man damit meistens viel zu langsam in der Bedienung selbiger ist. Zumindest langsamer als wenn man das Design in einer formalen Notationen niederschreibt. Was ich mir dann aber vorstellen könnte, ist eine automatische grafische Visualisierung des Flows - sozusagen nicht WYSIWYG sondern paralleles Rendering mit Rückverlinkung (also wenn ich ein grafisches Element selektiere springt der Texteditor zum zugehörigen textuellen Element), ähnlich vielen Markdown-Editoren.
Das Ganze ist einfacher zu realisieren und, behaupte ich mal, im Durchschnitt auch schneller zu bedienen.
Aber das hängt sicher stark vom Geschmack und eigenen Fertigkeiten und am Ende von den Fähigkeiten des Tools ab.


NoFlo/FlowHub scheint mir da im Moment das, was am dichtesten rankommt: https://flowhub.io


Ich habe mir das mal angesehen. Aber der Sprung vom Programmieren mit IDE zu flowhub scheint mir echt weit zu sein...
Ich habe leider auch nicht viel Dokumentation gefunden, nur die Blog-Einträge vom Erfinder.
War mir jetzt insgesamt nicht so eingängig und auch irgendwie sehr kommerziell fokusiert. Aber vielleicht bin ich auch einfach nicht durchgestiegen. Immerhin habe ich Operationen mit Ports wiedererkannt, Integrationen nicht so recht.

Denis
 

Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-components+unsub...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.



--
Ralf Westphal - One Man Think Tank
Hans-Henny-Jahnn-Weg 44
D-22085 Hamburg
Germany
Tel 0170-3200458
Email in...@ralfw.de

--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-components+unsub...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.

Ralf Westphal

unread,
Apr 21, 2015, 1:11:51 AM4/21/15
to event-based...@googlegroups.com


Ich weiß nicht, meine Erfahrungen mit grafischen Editier-Tools ist die, dass man damit meistens viel zu langsam in der Bedienung selbiger ist. Zumindest langsamer als wenn man das Design in einer formalen Notationen niederschreibt.

Mit der Maus rumzurühren, ist nicht schnell. Klar. Aber ich denke, das ginge auch anders. Ich habe mal ein bisschen experimentiert. Da bin ich auf ein "Kachelmodell" gekommen. Man zeichnet nicht auf einem weißen Blatt, sondern auf einer "Kachelwand". In jeder Kachel sitzt eine Funktionseinheit oder ein Pfeil(segment).
Mit der Tastatur kann man sich über die Kacheln schnell bewegen und einfügen/löschen.
Das hab ich mal experimentell implementiert. Bin dann aber steckengeblieben, weil ich kein GUI-Spezi bin.

 
Was ich mir dann aber vorstellen könnte, ist eine automatische grafische Visualisierung des Flows - sozusagen nicht WYSIWYG sondern paralleles Rendering mit Rückverlinkung (also wenn ich ein grafisches Element selektiere springt der Texteditor zum zugehörigen textuellen Element), ähnlich vielen Markdown-Editoren.
Das Ganze ist einfacher zu realisieren und, behaupte ich mal, im Durchschnitt auch schneller zu bedienen.
Aber das hängt sicher stark vom Geschmack und eigenen Fertigkeiten und am Ende von den Fähigkeiten des Tools ab.

Einen solchen dualen Editor hab ich für die Flow-Design-DSL von NPantaRhei mal gebaut. Gerendert wurde mit Graphviz. Das funktionierte ganz ordentlich. Aber ich hab es nicht weiter verfolgt, weil ich die DSL und die Runtime nicht weiter verfolgt habe. Die Einschränkungen waren mit zu groß gegenüber einer freieren Notation und Übersetzung von Flows.

 
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.



--
Ralf Westphal - One Man Think Tank
Hans-Henny-Jahnn-Weg 44
D-22085 Hamburg
Germany
Tel 0170-3200458
Email in...@ralfw.de

--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.



--
Ralf Westphal - One Man Think Tank
Hans-Henny-Jahnn-Weg 44
D-22085 Hamburg
Germany
Tel 0170-3200458
Email in...@ralfw.de

--
Sie erhalten diese Nachricht, weil Sie in Google Groups E-Mails von der Gruppe "Event based Components" abonniert haben.
Wenn Sie sich von dieser Gruppe abmelden und keine E-Mails mehr von dieser Gruppe erhalten möchten, senden Sie eine E-Mail an event-based-compo...@googlegroups.com.

Weitere Optionen finden Sie unter https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages