2012-10-02 20 views
5

Sto lavorando all'interno di un framework Javascript + BackboneJS (un framework MVC) + RequireJS, ma questa domanda è in qualche modo OO generica.Iniezione delle dipendenze rispetto alle dipendenze gestite rispetto all'oggetto globale

Vorrei iniziare spiegando che in Backbone, le vostre opinioni sono un mix di Vista e controller tradizionali, ed i vostri modelli HTML sono i tradizionali Visualizzazioni MVC

tormentando la mia testa su questo per un po 'e io sono non sono sicuro di quale dovrebbe essere l'approccio giusto/pragmatico.

Ho un oggetto Utente che contiene le preferenze dell'utente (come sistema di unità, selezione della lingua, qualsiasi altra cosa) da cui dipende molto codice.

Alcune delle mie viste eseguono la maggior parte del lavoro senza l'uso di modelli (utilizzando librerie di terze parti, come le librerie Mapping and Graphing) e, come tali, hanno una dipendenza dall'oggetto Utente per occuparsi della conversione delle unità, per esempio. Attualmente sto usando RequireJS per gestire questa dipendenza senza rompere troppo l'incapsulamento.

Alcune delle mie viste funzionano da sole e trasmettono solo i dati del modello ai miei template/template di template, che svolgono il lavoro e hanno una dipendenza dall'oggetto User, ancora, per cose come la conversione delle unità. L'unico modo per passare questa dipendenza al modello è iniettarlo nel modello e passare il modello nel motore di template.

La mia domanda è: come gestire al meglio una dipendenza così necessaria? - Creare un riferimento a livello di applicazione/oggetto globale accessibile ovunque? (YUK) - Utilizza le dipendenze gestite da RequireJS, anche se generalmente è consigliabile utilizzare solo il caricamento delle dipendenze gestite per le definizioni di classe/oggetto piuttosto che gli oggetti concreti. - O, usa sempre l'iniezione di dipendenza e passa manualmente tale dipendenza in tutto ciò che ne ha bisogno?

risposta

4

Da un punto di vista puramente tecnico, direi che le variabili globali commutabili (le variabili globali che possono cambiare), specialmente in javascript, sono pericolose e sbagliate. Soprattutto perché javascript è pieno di parti di codice che vengono eseguite in modo asincrono. Si consideri il seguente codice:

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

Ora, se addSomeStuffToLoggedinUser() esegue in modo asincrono da qualche parte (ad esempio, lo fa una chiamata AJAX, e poi un'altra chiamata ajax quando il primo finisce), potrebbe benissimo essere l'aggiunta di roba per il nuovo loggedInUser ("Sam"), quando arriva alla seconda chiamata ajax. Chiaramente non è quello che vuoi.

Detto questo, sono ancora meno un sostenitore di avere qualche oggetto utente che passiamo tutto il tempo dalla funzione alla funzione, all'infinito.

Personalmente, dovendo scegliere tra questi due mali, sceglierei uno scopo globale per cose che "molto raramente cambiano" --- a meno che forse stavo costruendo una centrale nucleare o qualcosa del genere. Quindi, tendo a rendere l'utente connesso disponibile a livello globale nella mia app, correndo il rischio che se in qualche modo alcune chiamate vengano eseguite molto tardi, e ho una situazione in cui un utente si disconnette e l'altro accede direttamente, qualcosa può succedere qualcosa di strano (poi di nuovo, se una meteora si schianta contro il datacenter che ospita la mia app, potrebbe anche accadere qualcosa di strano ... non mi sto nemmeno proteggendo da questo). In realtà una possibile soluzione sarebbe quella di ricaricare l'intera app non appena qualcuno si disconnette.

Quindi, immagino dipenda tutto dalla tua app. Una cosa che lo rende migliore (e ti fa sentire come si sta ancora ricevendo alcuni punti OO karma) è quello di nascondere i dati in qualche Singleton namespace:

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

al posto di

doSomethingCoolWith(window.loggedinuser); 

anche se è praticamente la stessa cosa alla fine ...

+0

Per quello che vale, è possibile trovare alcuni ottimi modelli per mitigare questo problema utilizzando i differenziali per sedersi di fronte a variabili globali commutabili che potrebbero essere modificate in modo asincrono –

1

Penso che tu abbia già risposto alla tua stessa domanda, vuoi solo che qualcun altro lo dica per te:) Usa DI, ma in realtà non stai "manualmente" passando tale dipendenza in ogni cosa poiché devi fare riferimento ad essa per usare comunque.

1

Considerando l'approccio TDD, come testarlo? DI è la soluzione migliore per un nuovo progetto, ma JS offre opzioni flessibili per gestire dipendenze globali concrete durante il test, ovvero: costruzione del contesto. Tornando indietro, Yahoo ha tracciato un modello di modulo in cui tutti i moduli erano strettamente accoppiati e non dipendenti l'uno dall'altro, ma che era giusto avere un contesto globale. Questo contesto globale può rendere la tua costruzione di app più pragmatica per cose che vengono costantemente riutilizzate. È solo che devi applicarlo con giudizio/con parsimonia e ci devono essere casi molto forti perché quelle cose siano dinamiche.

Problemi correlati