2012-10-02 23 views
5

Ich arbeite in einem Javascript + Backbone.js (eine MVC-Framework) + RequireJS Rahmen, aber diese Frage ist etwas OO generisch.Dependency Injection vs. Managed Abhängigkeiten vs. globales Objekt

mich mit der Erklärung, dass in Backbone Lassen Sie beginnen, sind Ihre Ansichten eine Mischung aus traditionellen Ansichten und Controller und Ihre HTML-Templates sind die traditionellen MVC Ansichten

worden meinen Kopf über diese für eine Weile Abstich und ich bin nicht sicher, was der richtige/pragmatische Ansatz sein sollte.

Ich habe ein User-Objekt, die Benutzereinstellungen enthält (wie Einheitensystem, Sprachauswahl, etwas anderes), dass eine Menge Code abhängt.

Einige meiner Ansichten machen die meiste Arbeit ohne die Verwendung von Templates (durch die Verwendung von 3rd-Party-Bibliotheken wie Mapping und Graphing-Bibliotheken) und als solche haben sie eine Abhängigkeit vom User-Objekt, um die Konvertierung der Einheiten zu kümmern. beispielsweise. Ich verwende derzeit RequireJS, um diese Abhängigkeit zu verwalten, ohne die Kapselung zu stark zu unterbrechen.

Einige meiner Ansichten arbeiten selbst sehr wenig und geben nur Modelldaten an meine Vorlagen/Vorlagen weiter, die die Arbeit erledigen und auch wieder eine Abhängigkeit vom Benutzerobjekt haben, etwa bei der Einheitenumrechnung. Die einzige Möglichkeit, diese Abhängigkeit in die Vorlage zu übertragen, besteht darin, sie in das Modell einzufügen und das Modell in die Vorlagenmaschine zu übergeben.

Meine Frage ist, wie man am besten handhaben, eine solche weit benötigt Abhängigkeit? - Erstellen Sie eine App-weite Referenz/globales Objekt, das überall zugänglich ist? (Igitt) - Verwenden Sie RequireJS Abhängigkeiten verwaltet werden, obwohl ist es in der Regel nur verwaltete Abhängigkeit Laden für Klassen-/Objektdefinitionen verwenden empfohlen, anstatt konkrete Objekte. - Oder verwenden Sie immer nur Abhängigkeitsinjektion und übergeben Sie diese Abhängigkeit manuell in alles, was sie benötigt?

Antwort

4

Aus rein technischer Sicht würde ich das commutable Globals (Globals, die sich ändern kann) argumentieren, vor allem in JavaScript aktivieren, sind gefährlich und falsch. Zumal javascript voll von Teilen des Codes ist, die asynchron ausgeführt werden. Betrachten Sie den folgenden Code ein:

window.loggedinuser = Users.get("Paul"); 
addSomeStuffToLoggedinUser(); 
window.loggedinuser = Users.get("Sam"); 
doSomeOtherStuffToLoggedinUser(); 

Nun, wenn addSomeStuffToLoggedinUser() asynchron irgendwo ausführt (zB es macht einen Ajax-Aufruf, und dann, wenn eine andere Ajax-Aufruf die erste beendet ist), es kann sehr gut sein Zeug zum neuen loggedinuser Zugabe ("Sam"), bis es zum zweiten Ajax-Ruf kommt. Offensichtlich nicht was du willst.

Having said that, ich bin noch weniger ein Fan einiges Benutzerobjekt zu haben, dass wir die ganze Zeit von Funktion zu Funktion, ad infinitum Hand um.

Persönlich, zwischen diesen zwei Übeln wählen zu müssen, würde ich einen globalen Spielraum für Dinge wählen, die "sich sehr selten ändern" --- außer vielleicht baute ich ein Kernkraftwerk oder etwas. Also tendiere ich dazu, den angemeldeten Benutzer global in meiner App verfügbar zu machen, wobei das Risiko besteht, dass, wenn irgendwie aus irgendeinem Grund ein Anruf sehr spät abläuft und ich einen Fall habe, in dem sich ein Benutzer abmeldet und sich der andere direkt anmeldet seltsam kann passieren. (Wenn ein Meteor in das Datencenter stürzt, das meine App hostet, kann auch etwas Seltsames passieren ... ich wehre mich auch nicht davor). Eigentlich wäre eine mögliche Lösung, die gesamte App neu zu laden, sobald sich jemand abmeldet.

Also, ich denke, es hängt alles von Ihrer App ab. Eine Sache, die macht es besser (und fühlen Sie sich wie Sie immer noch einige OO Karmapunkte bekommen) sind Ihre Daten in einigen Namespaced Singleton zu verstecken:

var myuser = MyApp.domain.LoggedinDomain.getLoggedinUser(); 
doSomethingCoolWith(myuser); 

anstelle von

doSomethingCoolWith(window.loggedinuser); 

obwohl es ist am Ende ziemlich das selbe ...

+0

Für das, was es wert ist, können Sie einige gute Muster finden, um dieses Problem zu mildern, indem Sie defereds verwenden, um vor austauschbaren globalen Variablen zu sitzen, die möglicherweise asynchron geändert werden –

1

Ich denke, Sie haben bereits Ihre eigene Frage beantwortet, Sie wollen nur jemand anderes, um es für Sie zu sagen:) Verwenden Sie DI, aber Sie sind nicht wirklich "manuell" diese Abhängigkeit in alles übergeben, da Sie es verwenden müssen es sowieso.

1

Betrachtet man den TDD-Ansatz, wie würdest du das testen? DI eignet sich am besten für ein neues Projekt, aber JS bietet Ihnen flexible Optionen, um beim Testen auf konkrete globale Abhängigkeiten zu reagieren, dh: Kontexterstellung. Auf dem Rückweg hat Yahoo ein Modulmuster entworfen, in dem alle Module lose gekoppelt waren und nicht voneinander abhängig waren, aber es war in Ordnung, einen globalen Kontext zu haben. Dieser globale Kontext kann Ihre App-Konstruktion für Dinge, die ständig wiederverwendet werden, pragmatischer gestalten. Es ist nur, dass Sie das vernünftig/sparsam anwenden müssen, und es muss sehr starke Fälle geben, damit diese Dinge dynamisch sind.