Ich möchte wissen, ob es eine Möglichkeit gibt, idiomatisch Probleme mit zirkulären Abhängigkeiten von require
von Node.js während der Verwendung von CoffeeScript-Klassen und super
zu vermeiden. Angesichts der folgenden vereinfachten CoffeeScript-Dateien:
a.coffee:
%Vor%b.coffee:
%Vor% Das erste offensichtliche Problem hier ist, dass es eine zirkuläre Abhängigkeit zwischen A und B gibt. Was immer zuerst ausgewertet wird, wird {}
als Referenz auf die andere haben. Um dies im allgemeinen Fall zu lösen, könnte ich versuchen, so etwas auf jedem zu tun:
a.coffee:
%Vor% Dies ist ein bisschen wie ein Hack, aber es scheint eine übliche Methode zu sein, zirkuläre Abhängigkeiten aufzulösen, indem man die module.exports
vor der require
für die Abhängigkeit B verschiebt. Seit CoffeeScript-Klassen können nicht wieder geöffnet werden , sie verwenden dann einen extend
-Aufruf einer bestimmten Sorte (dies könnte eine beliebige Methode zum Kopieren von Eigenschaften und Methoden sein) auf A.prototype
(aka A::
) um die Klasse zu beenden. Das Problem dabei ist, dass super
nur im Kontext der Klassendeklaration korrekt funktioniert, daher wird dieser Code nicht kompiliert. Ich suche nach einer Möglichkeit, super
und andere CoffeScript-Klassenfunktionen zu erhalten.
Es gibt mehrere kanonische Möglichkeiten, damit umzugehen. Keiner von ihnen, meiner Meinung nach, besonders ausgezeichnet. (Node wirklich muss unterstützen, das temporäre Objekt im ursprünglichen Kontext mit dem exportierten Objekt in zyklischen Situationen zu ersetzen. Die Vorteile davon sind es wert, einige hässliche, hacky V8 zu tun Trickerei, IMO. / rant)
Sie könnten ein "übergeordnetes" Modul haben, vielleicht das Einstiegsmodul Ihrer Bibliothek, das die endgültige Einrichtung von gegenseitig abhängigen Dingen vornimmt:
%Vor%Schrecklich, weil: Sie haben jetzt Probleme im übergeordneten Modul zusammengeführt und diesen Setup-Code aus dem Kontext entfernt, in dem er sinnvoll ist (und in dem er hoffentlich beibehalten wird). ) Gute Möglichkeit, Dinge aus der Synchronisation zu sehen.
Wir können das Obige verbessern, indem wir das Setup zurück in die jeweiligen einzelnen Submodule verschieben und nur das Abhängigkeitsmanagement in die übergeordnete Datei entfernen. Die Abhängigkeiten werden vom übergeordneten Modul (ohne Zyklen) erfasst und dann bei Bedarf weitergegeben:
%Vor% Schrecklich, weil: Nun, abgesehen davon, dass es in diesem speziellen Szenario (!!?!) absolut hässlich ist, hast du gerade das Lösen des Abhängigkeitsproblems "den Stapel hoch" gedrückt. zu einem Verbraucher. In dieser Situation ist dieser Verbraucher immer noch du selbst, was okay ist ... aber was passiert jetzt, wenn du A
allein über require('my_library/a')
anzeigen willst? Jetzt müssen Sie dem Verbraucher dokumentieren, dass er Ihre Submodule mit X-, Y- und Z-Abhängigkeiten parametrisieren muss ... und blah, blah, blah. Das Kaninchenloch runter.
Um das oben Gesagte zu wiederholen, können wir einige dieser Abhängigkeiten vom Konsumenten abstrahieren, indem wir sie direkt auf die Klasse anwenden (und somit auch lokale Probleme berücksichtigen):
%Vor% Schrecklich, weil: Dies fügt Ihrer API leider immer noch einen konzeptionellen Aufwand hinzu: "Stellen Sie sicher, dass Sie A.finish()
immer aufrufen, bevor Sie A
!" verwenden . In ähnlicher Weise kann es zu merkwürdigen, schwer zu wartenden Bug-Abhängigkeiten zwischen Ihren Submodulen kommen: jetzt kann A Elemente von B verwenden ... außer Teilen von B, die von A abhängen. (Und welche Teile diese sind wahrscheinlich während der Entwicklung nicht offensichtlich.)
Ich kann diesen Teil nicht für dich schreiben, aber es ist die einzige nicht-schreckliche Lösung; und es ist die kanonische, mit der jeder Node-Programmierer bei dir kommen wird, wenn du ihnen diese Frage bringst. Ich habe das obige im Sinne der Stack-Overflow-Annahme bereitgestellt, dass Sie wissen, was Sie tun (und sehr guten Grund haben, zyklische Abhängigkeiten zu haben, und das Entfernen von ihnen wäre nicht trivial und mehr) schädlich für Ihr Projekt als irgendwelche der oben genannten Nachteile) ... aber in aller Realität ist die wahrscheinlichste Situation, dass Sie nur Ihre Architektur neu gestalten müssen, um zyklische Abhängigkeiten zu vermeiden. (Ja, ich weiß, dass dieser Rat saugt.)
Viel Glück! (=
Tags und Links javascript coffeescript node.js circular-dependency require