Version 2 ist mir sympatischer, da die Abhaengigkeit zwischen den Modulen hier etwas kleiner ist.
Inzwischen habe ich mir die Abfragen weiter angesehen und ich denke, dass beide Vor- und Nachteile haben, und man vielleicht die Vorteile von beiden nutzen kann. Letztlich soll die ID ja zwei Dinge erfüllen: A. Zuordnung einer Antwort zu dem logischen Device, das die Anfrage gestellt hat (mittels Dispatch / Parse), B. eindeutige Zuordnung der Antwort zu einer Anfrage innerhalb des logischen Device. Um A zu erreichen, macht es Sinn, den Namen des Device als Teil der ID zu benutzen, um diesen dann in Parse abzufragen. Dafür bräuchte es Methode 2 aus dem letzten Post, d.h. das logische Modul gibt den Device-Namen mit. Wenn man allerdings die Verwaltung von (innerhalb einer Session) eindeutigen IDs für Anfragen dem logischen Modul überlässt, muss man diese ggf. mehrfach implementieren, wenn man ein weiteres logisches Modul haben möchte, das auf das gleiche physikalische Gerät zugreift. Außerdem muss das physikalische Modul auch für seine eigenen Anfragen (Login, Session-Status, ggf. "list" als Information, welche Funktionen unterstützt werden) eine eindeutige ID erzeugen und verwalten. Das sowohl im physikalischen als auch im logischen Modul zu implementieren erscheint mir etwas nach doppeltem Aufwand.
Letzteres erscheint mir sinnvoll, weil "call" und "subscribe" zwei recht unterschiedlich strukturierte Anfrage-Antwort Modelle sind, die beide über die gleiche Schnittstelle laufen. Bei call kommt auf eine Anfrage eine Antwort mit der gleichen ID (Polling). Bei "subscribe" dagegen kommen Events
ohne ID und man braucht wiederum eine andere Methode, um herauszufinden, wer die Anfrage gestellt hat...
Meine Idee wäre: Das logische Modul übergibt den Namen des aufrufenden Device mittels IOWrite, damit das physikalische Modul diesen in der ID unterbringen kann. Das physikalische Modul baut diesen in die ID ein und stellt sicher, dass IDs eindeutig sind. Write gibt die eindeutige ID an das logische Modul zurück.
Das Problem mit dem Antwort zurueckschicken habe ich leider nicht wirklich verstanden.
Vielleicht hilft etwas Pseudo-Code:
sub Phys_Write
{
my $id = createID();
if(USE_ASYNC_METHOD)
{
sendRequest($id);
}
else
{
$ret = execProgram();
Dispatch($id . ":" . $ret);
}
return $id;
}
sub Phys_Read
{
Dispatch($ret_containing_id);
}
sub Log_Parse
{
# Find device which asked for $id
}
sub Log_sendRequest
{
$id = IOWrite(...)
$some_table{id} = $hash->{NAME} # Remember who asked.
}
Wenn das physikalische Gerät Anfragen asynchron behandelt (z.B. über HTTP), gibt obiger Code kein Problem:
Anfrage stellen: Log_sendRequest - > IOWrite -> Phys_Write -> sendRequest; die $id wird an Log_sendRequest zurückgegeben und gespeichert. Wenn die Antwort kommt: Phys_Read -> Dispatch -> Log_Parse und letzteres vergleicht mit der gespeicherten ID.
Wenn die Anfrage synchron erfolgt (z.B. über ein Kommandozeilen-Programm), passiert aber folgendes:
Log_sendRequest - > IOWrite -> Phys_Write -> execProgram, Dispatch -> Parse; jetzt wird Parse aufgerufen und die ID übergeben, bevor Write die ID als Rückgabewert an das logische Modul zurückgegeben hat und letzteres sie sich merken konnte. Parse kann die ID also nicht finden.
Aber auch ohne dieses ID-Problem ist es wohl keine gute Idee, Dispatch direkt in Write aufzurufen, vermute ich mal. Wenn nun das logische Modul als Folge von Parse eine weitere Anfrage stellen möchte und erneut IOWrite aufruft, kommt es dann nicht zu einer Rekursions-Schleife, wenn sich beide ständig gegenseitig aufrufen? Ich habe den synchronen Fall jetzt so "entschärft", dass Write nicht direkt Dispatch aufruft, sondern einen InternalTimer von 1 Sekunde setzt, der dann Dispatch aufruft.
Könnte man alternativ auch direkt in Write die Antwort zurückgeben? Dann müsste aber das logische Modul unterscheiden können, ob es von IOWrite gerade die komplette Antwort bekommen hat, oder nur eine ID, mit der es später via Parse die Antwort bekommt.