Wir haben gerade geändert, wie unsere AS3-Anwendung mit unserem Back-End kommuniziert, und wir sind dabei, ein REST-System zu implementieren, das unser altes ersetzt.
Leider befindet sich der Entwickler, der mit der Arbeit begonnen hat, jetzt im langfristigen Krankenstand und wurde mir übergeben. Ich arbeite seit ungefähr einer Woche damit und verstehe das System, aber eines hat mich beunruhigt. Es scheint viel Funktionsübergabe in Funktionen zu geben. Zum Beispiel übernimmt unsere Klasse, die den Aufruf an unsere Server vornimmt, eine Funktion, die dann ein Objekt aufruft und an dieses übergibt, wenn der Vorgang abgeschlossen ist und Fehler behandelt wurden usw.
Es gibt mir das "schlechte Gefühl", wo ich das Gefühl habe, dass es eine schreckliche Übung ist, und ich kann mir einige Gründe vorstellen, warum, aber ich möchte eine Bestätigung, bevor ich eine Überarbeitung des Systems vorschlage. Ich habe mich gefragt, ob jemand Erfahrung mit diesem möglichen Problem hat.
quelle
Antworten:
Das ist kein Problem.
Es ist eine bekannte Technik. Dies sind Funktionen höherer Ordnung (Funktionen, die Funktionen als Parameter annehmen).
Diese Art von Funktion ist auch ein grundlegender Baustein in der funktionalen Programmierung und wird häufig in funktionalen Sprachen wie Haskell verwendet .
Solche Funktionen sind nicht schlecht oder gut - wenn Sie noch nie auf den Begriff und die Technik gestoßen sind, können sie zunächst schwer zu erfassen sein, aber sie können sehr leistungsfähig sein und sind ein gutes Werkzeug für Ihren Werkzeuggürtel.
quelle
Sie dienen nicht nur der funktionalen Programmierung. Sie können auch als Rückrufe bezeichnet werden :
Denken Sie eine Sekunde lang an asynchronen Code. Sie übergeben eine Funktion, die beispielsweise Daten an den Benutzer sendet. Erst wenn der Code vollständig ist, rufen Sie diese Funktion mit dem Ergebnis der Antwort auf, mit der die Funktion die Daten an den Benutzer zurücksendet. Es ist eine Änderung der Denkweise.
Ich habe eine Bibliothek geschrieben, die Torrent-Daten aus Ihrer Seedbox abruft. Sie verwenden eine nicht blockierende Ereignisschleife, um diese Bibliothek auszuführen und Daten abzurufen. Anschließend geben Sie sie an den Benutzer zurück (z. B. in einem Websocket-Kontext). Stellen Sie sich vor, Sie haben 5 Personen in dieser Ereignisschleife verbunden und eine der Anfragen, um die Torrent-Daten von jemandem abzurufen. Das wird die ganze Schleife blockieren. Sie müssen also asynchron denken und Rückrufe verwenden - die Schleife läuft weiter und das "Zurückgeben der Daten an den Benutzer" wird nur ausgeführt, wenn die Ausführung der Funktion abgeschlossen ist, sodass Sie nicht darauf warten müssen. Feuer und vergessen.
quelle
Das ist keine schlechte Sache. In der Tat ist es eine sehr gute Sache.
Die Übergabe von Funktionen an Funktionen ist für die Programmierung so wichtig, dass wir Lambda-Funktionen als Kurzform erfunden haben . Zum Beispiel kann man Lambdas mit C ++ - Algorithmen verwenden , um sehr kompakten und dennoch aussagekräftigen Code zu schreiben, der es einem generischen Algorithmus ermöglicht, lokale Variablen und andere Zustände zu verwenden, um Dinge wie Suchen und Sortieren durchzuführen.
Objektorientierte Bibliotheken können auch Callbacks haben, die im Wesentlichen Schnittstellen sind, die eine kleine Anzahl von Funktionen spezifizieren (idealerweise eine, aber nicht immer). Man kann dann eine einfache Klasse erstellen, die diese Schnittstelle implementiert und ein Objekt dieser Klasse an eine Funktion weiterleitet. Dies ist ein Eckpfeiler der ereignisgesteuerten Programmierung , bei der Code auf Framework-Ebene (möglicherweise sogar in einem anderen Thread) ein Objekt aufrufen muss, um den Status als Reaktion auf eine Benutzeraktion zu ändern. Die ActionListener- Oberfläche von Java ist ein gutes Beispiel dafür.
Technisch gesehen ist ein C ++ - Funktor auch eine Art Rückrufobjekt, das syntaktischen Zucker nutzt
operator()()
, um dasselbe zu tun.Schließlich gibt es Funktionszeiger im C-Stil, die nur in C verwendet werden sollten. Der Vollständigkeit halber möchte ich hier nicht auf Details eingehen. Die anderen oben erwähnten Abstraktionen sind weit überlegen und sollten in Sprachen verwendet werden, in denen sie vorkommen.
Andere haben die funktionale Programmierung erwähnt und wie selbstverständlich die Weitergabe von Funktionen in diesen Sprachen ist. Lambdas und Callbacks sind die Art und Weise, wie Verfahrens- und OOP-Sprachen dies imitieren, und sie sind sehr mächtig und nützlich.
quelle
Wie schon gesagt, ist es keine schlechte Übung. Es ist lediglich ein Weg, die Verantwortung zu entkoppeln und zu trennen. In OOP würden Sie beispielsweise Folgendes tun:
Die generische Methode delegiert eine bestimmte Aufgabe, von der sie nichts weiß, an ein anderes Objekt, das eine Schnittstelle implementiert. Die generische Methode kennt nur diese Schnittstelle. In Ihrem Fall wäre diese Schnittstelle eine aufzurufende Funktion.
quelle
Im Allgemeinen ist es nicht falsch, Funktionen an andere Funktionen zu übergeben. Wenn Sie asynchrone Anrufe tätigen und mit dem Ergebnis etwas anfangen möchten, benötigen Sie eine Art Rückrufmechanismus.
Es gibt jedoch einige mögliche Nachteile einfacher Rückrufe:
Mit einfachen Webservices funktioniert das einwandfrei, aber es wird umständlich, wenn Sie eine komplexere Abfolge von Anrufen benötigen. Es gibt jedoch einige Alternativen. Bei JavaScript hat sich zum Beispiel die Verwendung von Versprechungen verschoben ( Was ist so toll an Javascript-Versprechungen? ).
Sie beinhalten immer noch die Übergabe von Funktionen an andere Funktionen, aber asynchrone Aufrufe geben einen Wert zurück, der einen Rückruf entgegennimmt, anstatt einen Rückruf direkt selbst entgegenzunehmen. Dies bietet mehr Flexibilität beim Zusammenstellen dieser Anrufe. So etwas kann ziemlich einfach in ActionScript implementiert werden.
quelle