callback auf funktion außerhalb des scopes

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Ich begreife das Prinzip sehr wohl und setze das Publisher/Subscriber-Entwurfsmuster auch ein. Allerdings da wo es wirklich sinnvoll ist, und nicht einfach überall. Du kommst mit diesem `EventBroker` ja andauernd um die Ecke.

Eine *zusätzliche Indirektion* kann per Definition schon nicht einfacher sein. Es ist eine zusätzliche Schicht. Auf die man in diesem Fall sehr gut verzichten kann. So ziemlich jedes Programm verzichtet darauf, denn so gut wie kein Programm nutzt für die Kommunikation zwischen allen Objekten so eine Zwischenschicht. Nachrichten zwischen Objekten verschicken ist schon der normale Methodenaufruf. Das geht auch ohne zusätzlichen Vermittler der ausser Komplexität nichts bietet und in Deinem Fall das ganze sogar nicht unflexibler macht, weil das schon wieder globaler Zustand ist.
Also, ich komme nicht dauernd damit um die Ecke, Ich habe das vorgeschlagen, wo es eine Lösung sein könnte. Ich weiß ja nicht, ob so eine Verbindung, wie Du sie vorgeschlagen hast, genügt. Reicht es, dass damit die obersten Klassen in der Hierarchie verbunden sind oder gibt es auch Klassen darunter, die auch mit etwas im anderen Modul kommunizieren müssen? In diesem Fall wäre ein Hangeln durch die Klassenhierarchie mit vielen Parameterweitergaben eine Verkomplifizierung und eine immense Indirektion. Da wäre der Eventbroker keine *zusätzliche Indirektion* sondern geradezu eine entflechtende *Direktion*. Ich kann natürlich den vorliegenden Fall nicht beurteilen, weil ich die Einzelheiten nicht kenne. Aber sicher ist es nicht verkehrt dass der Anwender auch diese Möglichkeit kennt
BlackJack hat geschrieben:Der „Anruf aus Amerika“-Vergleich hinkt ganz gewaltig. Mit Spezialist ist der Telefontechniker gemeint, der das System verändern, warten, und Fehler suchen muss. Den interessiert es tatsächlich worüber die Anrufe unter welchen Umständen und mit welchen Parametern laufen.
Wenn ein Fehler in Buxtehude im Telefonnetz auftaucht, braucht man sicherlich nicht unbedingt zu wissen, wie das Telefonnetz in Aserbeidschan funktioniert, weil bei einem Anruf auch von dort der Fehler passiert ist.
BlackJack hat geschrieben:Du zwingst Deine Ideen auf, in dem Du sie nicht nur einmal zum Diskutieren in *einem* Thema vorstellst, sondern den gleichen Kram immer und immer wieder in Themen rein drückst, obwohl Du eigentlich gemerkt haben solltest wie das ankommt und welche, immer gleichen Diskussionen sich darauf hin im Kreis drehen. Und das bei Fragen von nichtsahnenden Neulingen, die mit Deinem Code und der Diskussion in der Regel nichts anfangen können.
Ich zwinge überhaupt niemand etwas auf. Ich stelle nur kurz eine Idee vor. Und Du und andere zwingen dann mir endlose Diskussionen deswegen auf.
BlackJack hat geschrieben:Warum das Stuss ist wurde bereits an anderer Stelle zur Genüge durchgekaut. Es wird nicht besser oder anders wenn Du da in jedem Theme wieder aufs neue drüber diskutieren möchtest. Es nervt. Nur wenn keiner was sagt, dann ”gewinnst” Du in dem Du das immer und immer wieder wiederholst.
Sorry, ich will da gar nichts zur Genüge durchkauen und ich möchte auch gar nichts immer wieder aufs Neue darüber diskutieren. Ich hatte nur gedacht dem Anwender könnte es vielleicht nützen, was ich aber nicht beurteilen kann. Und mich nervt es gewaltig, wenn man mir dann immer wieder endlose Diskussionen aufzwingt.
BlackJack hat geschrieben: Ich denke da muss man langsam mal mit Moderationsmitteln dran arbeiten…
Es wäre nicht schlecht, wenn es in diesem Forum auch endlich so etwas wie einen Moderator gäbe. Damit meine ich jemanden, der auch weiß, was ein Moderator ist. Moderare heißt ja mäßigen. Das wäre jemand, der lenkend eingreift, wenn eine Diskussion zu hitzig wird, damit sie nicht aus den Fugen gerät und alles in gezügelten Bahnen läuft.

Aber hier im Forum scheinen ja gewisse Personen ihr Unwesen zu treiben, indem sie User vergraulen, sie zur Schnecke machen und beleidigen. Eine kleine Notiz wäre etwa das:

viewtopic.php?f=18&t=38748&start=60#p313454

Aber es sind auch andere, die sich gar nicht mehr rühren und mit diesem Forum nichts mehr zu tun haben wollen. Manche Subforen sind schon regelrecht tot. Wenn es so etwas wie Moderatoren hier gäbe, könnte das ein sehr lebendiges Forum sein, in dem viele ihre Meinungen austauschen könnten oder Ideen, die andere beflügeln.

So aber rührt sich leider sehr wenig.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1231
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Jemand, der jetzt nicht unbedingt aus der Softwareentwicklung kommt, stellt eine einfache Frage.
Die Frage wurde einfach beantwortet.

Dann kommst du mit einer Antwort, die den Rahmen sprengt und die Struktur weiter verkompliziert.
Würdest du dafür deine Hand ins Feuer legen, dass der TO nach einem Jahr noch weiß, was er da gemacht hat ohne den Code komplett zu lesen?
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Alfons Mittelmeyer hat geschrieben:Ich kann natürlich den vorliegenden Fall nicht beurteilen, weil ich die Einzelheiten nicht kenne. (...) Ich hatte nur gedacht dem Anwender könnte es vielleicht nützen, was ich aber nicht beurteilen kann.
Genau das ist der Punkt: Deine gutgemeinten Ratschläge sind oftmals unangebracht in der jeweiligen Situation. Oder zumindest ist in dem Moment, wo du dein Schema F bringst, überhaupt noch nicht klar ob ein "Komplexitätsmonster" hilfreich ist. Du knallst es einfach bei jeder Gelegenheit raus ohne den Anwendungsfall ernsthaft beurteilt zu haben. Du würdest wahrscheinlich immer einen Bagger nehmen, egal ob du ein Haus baust oder eine Blume pflanzt.

EDIT:
Und wenn du grundsätzlich irgendwelche Fälle abdecken willst, die in ferner Zukunft in einem Paralleluniversum eventuell mal auftreten könnten, dann ist die durch Python gelebte Philosophie nicht so wirklich auf dich zugeschnitten...
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@chwin: Du musst dem `Intern`-Exemplar das `Datenbank`-Exemplar bekannt machen, also beispielsweise beim Erstellen als Argument übergeben. Also rein technisch, ohne jetzt darauf einzugehen ob die Aufteilung oder die Namensgebung Sinn macht:
Ja tolle Idee! Und zuerst muss dann wohl das eine Modul bekannt geben, dass das andere dazu eine Klasse Intern aufrufen soll und worüber, gibt sie das wieder bekannt.

Außerdem ist das nur noch eine Zunahme der wohl eh schon bestehenden vielen Verflechtungen.

Zu klären wäre der Ablauf und ob sich daraus eine Aufrufreihenfolge ergibt

Am Besten beginnt man mit vier Modulen:

Datenempfang
Datenverarbeitung und Logik, evtl. Anbindung an GUI
Datenspeicherung
Gemeinsame Systemroutinen

Wenn das System nur auf den Empfang von Daten reagiert, würde der Datenempfang in der Aufrufreihenfolge oben stehen. Zu klären wäre aber noch, ob da nicht noch eine Bedieneroberfläche mit hinein muss und ob das eine GUI ist.

Gemeinsame Systemroutinen wären Grundfunktionen des Systems, die eventuell von allen anderen Modulen genutzt werden. Und dieses Modul ruft keinesfalls etwas von anderen Modulen auf. Eventuell wird das auch gar nicht benötigt. Zur Zeit ist alles in diesem Modul und es gilt, dieses Modul zu leeren und auf die anderen Module aufzuteilen.

Außer Aufrufen dieser Systemroutinen Routinen soll der Datenempfang nur die Datenverarbeitung aufrufen und die Datenverarbeitung nur die Datenspeicherung.

Zu klären wäre aber, ob der Datenempfang rein von außen kommt, oder auch von der Logik abhängt, sodass die Logik Einstellungen für den Datenempfang setzt. Sollte das so sein, dann bräuchte man auf alleroberter oberster Ebene noch ein Modul, mit dem solche Einstellungen vorgenommen werden können.

Dann wohl so:

[codebox=text file=Unbenannt.txt]Einstellungen mit Einstellogik und Anbindung an GUI
| | |
Datenempfang | |
| | |
Datenverarbeitung |
| |
Datenspeicherung
| | | |
Eventuelle System Grundfunktionen (aufrufbar für alle)[/code]

Wenn man dabei aber keine hart kodierten Aufrufe in anderen Modulen vornehmen will, oder sich auch nicht sicher ist, ob man funktionale Einheiten später nicht weiter in einzelne Module unterteilen möchte, geht auch das nur mit Messages. Ansonsten bekommt man immer einen unnötigen Aufwand für Erweiterungen, Umstrukturierungen, Wartung und Pflege
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: schön, dass Du die Basics kennst, Eingabe-Verarbeitung-Ausgabe, dafür gibts auch schon einen Wikipediaartikel. Und dann machst Du diese schöne Herleitung wieder durch Dein Message-System kaputt. Umstruktrierungen, Erweiterungen, Wartung und Pflege gehören zu jedem Projekt dazu. Jetzt mußt Du nur noch erkennen, dass Deine Messages nichts an den ganzen Punkten verbessern, sondern nur zusätzliche Komplexität dazupackt, so dass Wartung und Pflege unnötig umständlich macht.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Und noch eines. Nach unten hin kann man ja Aufrufe machen und auch Rückgabewerte bekommen. Aber nach oben hin darf das nicht geschehen. Globale Variablen, damit man von oben Zustände pollen kann oder Callbacks in die unteren Layers reinmatschen widerspricht jeder gesunden Programmierphilosophie. Man möchte ja in der GUI eventuell anzeigen, welche Art von Daten empfangen wurden oder wie weit deren Verarbeitung ist. Zustände werden üblicherweise durch Signale gemeldet und nicht durch sonstige Programmverflechtungen zwischen Software Layers und gar durch Aufrufe von unten nach oben. Wer meint, dass man das aber doch so machen sollte, und dann das auch noch auf Teufel komm raus verteidigt, dem ist wohl kaum mehr zu helfen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Callbacks der GUI die aus der Datenschicht aufgerufen sind böse(TM), aber callbacks die man in deiner globalen Callbackschleuder registriert sind gut(TM). Is klar.

Es ist ja schon ausreichend belegt, dass dir das nachdenken über globalen Zustand, und wie man ihn möglichst vermeidet, nicht gegeben ist. Muss ja nicht.

Nur dieses bestimmte Bessergewisse immer....
Benutzeravatar
kbr
User
Beiträge: 1506
Registriert: Mittwoch 15. Oktober 2008, 09:27

@chwin: bevor Du hier völlig den Durchblick verlierst: Für die Aussenwelt kannst Du verschiedene Receiver anlegen, gleiches gilt für die Datenbank. Solange beide die gleichen Schnittstellen aufweisen (receive(), store()), brauchst Du den Processor nicht zu ändern.
Das sieht ähnlich dem was BlackJack schon zeigte, als Python-Pseudocode etwa so aus:

Code: Alles auswählen

class Receiver:

    def receive(self):
        # wait for data and return them
        return data
    

class Database:

    def store(self, data)
        # store the data


class Processor:

    def __init__(self, database, receiver):
        self.db = database
        self.receiver = receiver
        
    def process(self, data):
        # do something with the data and return the result
        return result
        
    def run(self):
        while True:
            data = self.receiver.receive()
            result = self.process(data)
            self.db.store(result)


def main():
    database = Database()    
    receiver = Receiver()
    processor = Processor(database, receiver)
    processor.run()
Mehr brauchst Du erst einmal nicht.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

__deets__ hat geschrieben:Callbacks der GUI die aus der Datenschicht aufgerufen sind böse(TM), aber callbacks die man in deiner globalen Callbackschleuder registriert sind gut(TM). Is klar.
Es ist ein Unterschied, ob man aufruft publish(ID,parameter) oder ob man zuerst alle möglichen Callbacks in ein Modul reinmatscht, und dann die Funktionsreferenzen in allerlei Variablen oder Attributen speichert. Außerdem ist auch denkbar, dass später noch andere auch diese Info haben wollen. Ist doch einfacher, wenn man die Funktionsreferenzen nicht an vielen Stelle zwischenspeichern muss und dann ist es überhaupt nicht OK, dass man dazu auch noch diverse Methoden in diesem Modul aufrufen muss, um die Funktionsreferenzen zu übergeben.

Es reicht, wenn die unteren Layer ein publish machen und die oberen einfach ein bind oder connect - sicher davon schon etwas gehört - oder hier war es dann subscribe genannt. Ein connect oder bind empfindest Du dann seltsamerweise nicht als globale Datenscheuder, oder wie ist es damit?

Wie kommst Du jetzt auf globale Datenschleuder? Wenn es über einen lokalen Rahmen hinausgeht, dann soll man auch nicht für alles denselben Eventbroker nehmen. Für meinen GuiDesigner habe ich vielleicht nur 20 Messages gebraucht oder auch bis zu dreißig Messages. Auch bis zu hundert sollten noch übersichtlich sein, passen ja auf zwei Blatt Papier. Das kann man vergleichen mit einem lokalen Ortsnetz, sozusagen ein Minidorf. Für hundert solcher Dörfer nimmt man dann even hundert Eventbroker und einen als Fernnetz. Wenn es mehr wird, nimmt man noch international mit hundert solch kleiner Länder. Hat man hundert Länder mit hundert Gemeinden mit je bis zu hundert Messages sagen wir mal je ein Eventbroker für bis zu zehn Module. Dann hat man insgesamt bis zu hunderttausend Module mit bis zu einer Million Messages mit bis zu 10101 Eventbroker. Da hat man dann doch einen guten Überblick und kein Eventbroker ist global. Da macht man die Signale einfach mit bis zu drei IDs und dann noch das nationale oder internationale Amt, etwa '0' oder '00'. Damit ist es übersichtlich strukturiert.

Es spricht auch nichts dagegen, dass jedes Modul einen eigenen Eventbroker mit eigener Vorwahl hat.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und wenn man jedem Event seinen eigenen Broker gibt, dann heisst das "Observable Pattern" und findet sich zB in der Gestalt von Signal/Slots in Qt. Und dann wird deine "Vorwahl" einfach nur das Objekt selbst, und du bist endlich da angekommen, wo der Rest sein Mitte der 90er schon war.

Und da wird auch nicht "gematscht" wie du so schoen herablassend sagst (aber spaeter wieder Beschweren ueber die Formulierungen anderer), sondern ein sauberes loose-coupling erreicht, bei dem Objekte einer Schicht die einer anderen ueber diverse Zustandsaenderungen informieren. Das *muss* aber nicht besser sein als das man periodisch (oder aufgrund anderer Ereignisse) einfach *abfragt*, was denn so Phase ist.

Denn das Observable-Pattern hat so seine Tuecken, wenn man implizit Code schreibt, der sich auf eine eigentlich nirgends klar definierte Ereignisreihenfolge verlaesst. Ist also nicht so ganz simpel.

Ja, Events sind ein hilfreiches Ding. Manchmal. Mit globalem Broker (wie du sie hier immer propagierst, anderslautendes ist immer nur Gerede, noch nie gesehen) aber nur fuer sehr, sehr eingeschraenkte Zwecke. Und darum bei weitem nicht das von dir propagierte Allheilmittel.
chwin
User
Beiträge: 16
Registriert: Freitag 4. Juli 2014, 15:07

Hallo

oh mann, da teste ich die ersten zwei Antworten und komme nach einen Tag zurück...
Damit hätte ich jetzt nicht gerechnet. :shock:

@kbr Das sieht in etwas so aus wie ich es jetzt plane. Ich bin aber gerade am überlegen ob ich mich nicht einfach nach einer anderen AMQP Library umsehen. Das ganze Problem ist ja nur entstanden weil AMQPStorm zwingend einen Callback will.

Mir wäre es viel lieber ich könnte pollen.

Evtl denke ich ja total falsch und zäume das Pferd von hinten auf.

Aber, mein Wunsch ist es die Kontrolle selber zu behalten.
Ich möchte eine Nachricht abrufen, und diese Schritt für Schritt per funktion-call und return-value verarbeiten.
So dass ich viele kleine eigenständige Funktionen habe für die ich einfach Tests schreiben kann.

Leider dreht diese Callback Geschichte alles um.

Der Callback ruft meine Verarbeitsungsfunktion auf und und die Nachricht hangelt sich durch einen Funktionsbaum. Am Ende wird ein "OK" und das ACK den Baum zurück nach oben geschickt.

So habe ich viele Funktionen die voneinander abhängen und für dich ich nicht so einfach Tests schreiben kann.

Im Prinzip ist die AMQP Lib jetzt der kontrollierende, zentrale Punkt des Programms.

Ich werde dieses mal mehr Zeit in die Planung investieren.
Die logik steht und Funktioniert. Ich brauche nur ein neues Gerüst.


auch wenn ich den tieferen Hintergrund eures Streits nicht nachvollziehen kann
vielen Dank für die Mühe
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe da jetzt eigentlich keinen Widerspruch.

Das ein AMPQ-System einen Callback erwartet ist jetzt nicht weiter verwunderlich. Der Natur nach handelt es sich ja um Ereignisse, die bekommt man ueblicherweise so.

Das deren Verarbeitung dann aber komplizierter ist, weil es aus einem Callback kommt - das leuchtet mir nicht ein.

Du kannst doch deinen gewuenschten sequentiellen Ablauf programmieren, mit beliebigen Transformationen etc

Code: Alles auswählen

def process(event):
      a = transform(event)
      b = transform_more(a)
      ...
Jede der beteiligten Funktionen ist einzeln testbar. Nur die gesamte process Funktion wird dann halt statt vom Test aufzurufen in der AMPQ als Callback registiert.

Wie stellst du dir das anders vor?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

__deets__ hat geschrieben:Und wenn man jedem Event seinen eigenen Broker gibt, dann heisst das "Observable Pattern" und findet sich zB in der Gestalt von Signal/Slots in Qt. Und dann wird deine "Vorwahl" einfach nur das Objekt selbst, und du bist endlich da angekommen, wo der Rest sein Mitte der 90er schon war.
Nö, vielleicht ist da endlich der Rest da angekommen, dass ich nichts Außergewöhnliches und Unerhörtes gebracht hatte, sondern nur etwas völlig Normales, das seit Mitte der 90er in sehr vielen Bereichen eingesetzt wird.
__deets__ hat geschrieben:Und da wird auch nicht "gematscht" wie du so schoen herablassend sagst (aber spaeter wieder Beschweren ueber die Formulierungen anderer), sondern ein sauberes loose-coupling erreicht, bei dem Objekte einer Schicht die einer anderen ueber diverse Zustandsaenderungen informieren. Das *muss* aber nicht besser sein als das man periodisch (oder aufgrund anderer Ereignisse) einfach *abfragt*, was denn so Phase ist.
Natürlich wird da nichts gematscht, sondern man hält sich an die bereits vorhandenen sauberen Schnittstellen. Kein Mensch käme auf die Idee in den Source Code von Qt seine Callbacks für eine Anwendung hineinzumantschen. Das wäre nämlich gematscht und für so ähnliches woanders bin ich auch nicht dafür.

[quote="__deets__"Denn das Observable-Pattern hat so seine Tuecken, wenn man implizit Code schreibt, der sich auf eine eigentlich nirgends klar definierte Ereignisreihenfolge verlaesst. Ist also nicht so ganz simpel.[/quote]Man muß eben gewohnt sein, ereignisorientiert zu programmieren und darf nicht erwarten, dass nach Senden von etwas dann gleich unmittelbar auch schon das Ergebnis da ist. Im Normalfall laufen Events auch über eine Queue
__deets__ hat geschrieben:Ja, Events sind ein hilfreiches Ding. Manchmal. Mit globalem Broker (wie du sie hier immer propagierst, anderslautendes ist immer nur Gerede, noch nie gesehen) aber nur fuer sehr, sehr eingeschraenkte Zwecke. Und darum bei weitem nicht das von dir propagierte Allheilmittel.
Ob etwas global ist kommt darauf an, ob man nur einen Knoten hat, also nur Ortsnetz oder viele. Für kleine Anwendungen von ein paar Modulen reicht wohl ein Eventbroker vollständig aus. Und mit Messages wird überall gearbeitet, die ganzen Systeme im Automotiv Bereich im Militärischen Bereich in luft und Raumfahrt arbeiten damit, da gibt es verschioedene Busse, wie etwa CAN, MOST, Flexray über die dann Signale übertragen werden. Die haben dann auch einen Physikalischen Layer und Protokollstacks und arbeiten mit Qeues. Ich hatte hier nur einen ganz simplen mit indirektem Funktionsaufruf gezeigt, denn eine Qeue und weitere Features erleichtern nicht das Verständnis. Hast ja gelesen, dass jemand die Zwei Zeilen Code, nämlich Funktionsdefinition mit Parametern und dann Aufruf über Dictionary bereits als Komplexitätsmonster bezeichnet hat.

Und ein Allheilmittel ist so etwas keineswegs. Man kann dann zwar den Code leicht in andere Module verteilen. Ob er dabei aber übersichtlicher wird ist fraglich.

Da sollte man vielleicht doch anders vorgehen. Zuerst einmal in der Source verschiedene Bereiche machen und dort hineinmoven, was zu diesem Bereich gehört. Und wenn man dann damit letztendlich zufrieden ist, kann man die Auslagerung vorbereiten.

Und eine solche Vorbereitung sähe dann im Mainscript so aus:

Code: Alles auswählen

# import empfang
# import speichern
import verarbeitung

verarbeitung.init(verarbeitung = verarbeitung,
                  empfang = verarbeitung,
                  speichern = verarbeitung)
Und wenn man diese Werte dann in globalen Variablen speichert, kann man schon einmal die Aufrufe richtig benennen. Und wenn sie richtig benannt sind, kann man dann aufteilen.

Ob der Code dann schon schön ist, ist immer noch fraglich. Aber es schadet nichts über Messages nachzudenken. Nicht unbedingt, dass man das implementieren soll. Aber es wäre gut über sinnvolle Schnittstellen und sinnvolle Benennungen nachzudenken. Und kann solche sinnvollen Schnittstellen dann ja auch als Mehodeninterfaces implementieren.
Benutzeravatar
kbr
User
Beiträge: 1506
Registriert: Mittwoch 15. Oktober 2008, 09:27

@chwin: Ein Callback ist aber auch leicht zu handhaben:

Code: Alles auswählen

class Database:

    def store(self, data):
        # store the data
        
        
class Processor:

    def process(self, message):
        # process message and return the result
        return result


class MessageHandler:

    def __init__(self, processor, database):
        self.processor = processor
        self.database = database
        
    def __call__(self, message):
        result = self.processor.process(message)
        self.database.store(result)
und gemäß https://github.com/eandersson/amqpstorm ... onsumer.py in Zeile 41:

Code: Alles auswählen

...
#channel.basic.consume(on_message, 'simple_queue', no_ack=False)
message_handler = MessageHandler(Processor(), Database())
channel.basic.consume(message_handler, 'simple_queue', no_ack=False)
...
Processor und Database können auch hier leicht ausgetauscht werden, solange die Methoden process und store vorhanden bleiben. Falls es die Komplexität der Aufgabe nicht erfordert, könnten Processor und Database auch durch Funktionen ersetzt werden. Oder auch der MessageHandler, wie bei __deets__. Testen ist gleichfalls kein Problem.
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wobei mir das immer noch zu sehr Java wäre. Warum nicht einfach Funktionen verwenden?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

snafu hat geschrieben:Wobei mir das immer noch zu sehr Java wäre. Warum nicht einfach Funktionen verwenden?
Im vorliegenden Fall wurde das mit Funktionen oder Methoden gemacht. Das ist aber nicht immer sinnvoll. Ich hatte nämlich auch mal so etwas gemacht mit Empfang, Verarbeitung und Speichern. Dabei konnte man auch etwa Videodateien - auch 2 GB kein Problem - vom PC auf das Smartphone übertragen. Klar dass man vom PC keine Funktion auf dem Smartphone aufrufen kann. Ebenso aber hatte ich die Software in Threads aufgegliedert. Der Empfang soll ja nicht zuerst die Videodatei in den Hauptspeicher schreiben - außerdem hat mein Smartphone eh nicht soviel -, während die anderen warten. Und wenn dann die Daten in ein File geschrieben werden, soll natürlich der Empfang nicht warten. Daher schrieb der Empfang die Daten in eine Queue und triggerte dann die Verarbeitung. Der Empfang schrieb dann weiter in die Queue bis zu einer Obergrenze und legte sich dann schlafen. Bei Erreichung einer Untergrenze in der Queue wurde der Empfang dann wieder aufgeweckt und forderte weitere Daten vom PC an. Natürlich wurde auch da nicht erst angefangen, wieder aus einer Datei zu lesen, sondern auch da war man nicht untätig und hatte die Daten bereits in einer Queue gebuffert. Alle Komponenten sollten arbeiten, wenn es was zu tun gab und auf andere sollte dabei nicht gewartet werden, damit das System optimal läuft.

Und bei Threads ruft man nicht einfach Funktionen in anderen Threads auf. Daher einfach Message gesandt. Und die triggerte dann das Event im anderen Thread. Da brauchte man dann gar nicht extra ein Eventhandling programmieren, das das bereits im Eventbroker integriert war.

Also: Callbackaufruf auf einem Tablet in China bekommt man mit Funktionsaufruf einfach nicht hin.
Zuletzt geändert von Alfons Mittelmeyer am Freitag 1. September 2017, 20:40, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: was hat jetzt dieser Beitrag, dass Du auch bei anderen Problemen viel zu komplizierte Lösungen hast, mit dem eigentlichen Thema zu tun?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: was hat jetzt dieser Beitrag, dass Du auch bei anderen Problemen viel zu komplizierte Lösungen hast, mit dem eigentlichen Thema zu tun?
Es hat damit etwas zu tun, dass die Software in nur einem Thread zu haben, nicht immer eine optimale Lösung ist. Mit Messages ist man auch davon unabhängig.

Und außerdem war das keine komplizierte Lösung, die ich geschildert hatte sondern eine optimale. Ein schlechte Lösung ist in manchen Fällen, wenn der Empfang nicht empfangen kann, während die Daten gespeichert werden.

Es kommt eben darauf an, um welche Daten es sich handelt und was damit geschehen soll. Ist es ein Temperaturwert von einem Thermometer Nullo Problemo. Ist es ein Gigabyte und soll das kompiliert werden mit einer Compilierzeit von 30 Stunden, dann sieht es ganz anders aus.
chwin
User
Beiträge: 16
Registriert: Freitag 4. Juli 2014, 15:07

Hallo

ich muss zugeben, Eure Diskussion ist recht weit außerhalb meines Verständnisbereichs, daher gehe ich da auch nicht drauf ein.
Evtl hilft Euch ja die genauere Beschreibung meines Problems Euch auf den "richtigen" Weg zu einigen :D

Bei meiner Anwendung geht es um Fileserver, die ich betreue.

Wir haben inzwischen so viele Files, das ein Treewalk um die Daten die zu sichern sind zu identifizieren nicht mehr funktioniert. Die Laufzeit eines Treewalks liegt bei etwa 30h. Wir sprechen hier von 350+Mio Files. Meine Aufgabe ist es das Backup sicherzustellen.

Also hatte ich mir überlegt, das der Filer ja eine Debug Schnittstelle hat, über die ich alle Filesystem Events bekomme hat.

Ich protokolliere alle Filezugriffe mit, führe in einer Datenbank ein virtuelles Dateisystem und weiss permanent, welche Files sich geändert haben. Einfach durch eine Datenbankabfrage.
Das ganze funktioniert und läuft.
Zzt haben wir max. 3000 Events pro Sekunde. Im Mittel (8-19Uhr) liegen wir bei 250/s
Die einzelnen Nachrichten haben eine Größe von etwa 1 bis 2 k. Einige wenige sind aber auch bis zu 5k groß.

Mir ist jetzt aber eingefallen, das ich mit all den Daten noch viel mehr machen kann.
Ich wollte also das ganze erweitern. Dabei ist alles zusammengebrochen.
Jede Zeile Code hing irgendwie mit jeder anderen zusammen.

Daher will ich es jetzt in Module zerlegen.
Der Wechsel von MySQL auf SQLite hat den Ausschlag gegeben. Das war ein riesen Akt.

Jetzt will ich die Daten noch nach anderen Gesichtspunkten auswerten und im Verarbeitsungsmodul sozusagen Plugins anstöpseln können.

Die ersten Hinweise, die ich bekommen haben waren schon sehr hilfreich. Ich werde den Ansatz ohne Message Broker verfolgen, einfach weil ich ihn gedanklich besser nachvollziehen kann.

Bis der Umbau fertig ist, wird es aber noch ein wenig dauern.



Vielen Dank für die viele Zeit
Antworten