In che modo le cose diverse dai servizi si adattano al modello di Iniezione di dipendenza?

3

Wikipedia spiega:

A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it.

Ma studiando l'implementazione DI di AngularJS, ho notato che include molte strutture differenti da iniettare come:

  • servizi
  • Valore
  • fabbrica
  • fornitore
  • costante

In che modo queste cose diverse dai "servizi" si adattano al modello dell'iniezione delle dipendenze?

    
posta Viziionary 27.09.2015 - 17:10
fonte

3 risposte

5

Tutto si inserisce nel modello di iniezione delle dipendenze.

Quando ol 'Wirth stava proclamando che ogni programma Pascal dovrebbe iniziare con

PROGRAM ProgramName(INPUT,OUTPUT)

era un'iniezione di dipendenza che aveva in mente, anche se in una forma molto rudimentale, e non avevamo ancora nemmeno una parola per farlo, quindi le generazioni su generazioni di programmatori non l'avevano mai capita, e invece la copiavano da programma a programma come alcune parole apocrife che dovevano essere scritte in questo modo per far funzionare la magia.

Il passaggio in modo esplicito del flusso di input e del flusso di output al programma invece di affidarsi al programma su alcune entità predeterminate, fisse e disponibili a livello globale è, in un certo senso, un'iniezione di dipendenza.

Presumibilmente per comodità, i linguaggi moderni offrono molte funzionalità disponibili a livello globale che sono a tua disposizione semplicemente con un'istruzione #include o using o import . Queste istruzioni di importazione non importano solo interfacce e costanti primitive; importano anche interi sottosistemi dichiarati come public static , pronti per essere usati da chiunque.

A volte la routine di ordinamento diventa noiosa durante l'ordinamento e si sente la necessità di controllare il proprio account Facebook? Basta avere la tua routine di ordinamento import del pacchetto io.net dall'SDK e ora può accedere a qualsiasi pettegolezzo su tutto il pianeta.

I tuoi servizi web ritengono che il loro lavoro sia poco brillante e preferirebbero fare qualcosa di più affascinante aspettando che l'host remoto risponda? Possono solo import java.awt dall'SDK e visualizzare alcuni grafici 2D chiari per il divertimento di chiunque accada a piedi dalla console del server in quel momento.

Tutta questa follia esiste perché il concetto di iniezione di dipendenza non ha ancora ottenuto la trazione che merita.

Tutto potrebbe e, a mio avviso, dovrebbe essere fatto usando un'iniezione di dipendenza; invece che il punto di ingresso dell'applicazione della tua console è

int main( String args[] )

potrebbe essere

void main( ConsoleRuntimeEnvironment environment )

nel qual caso invochereste l'ambiente per ottenere i vostri argomenti, e invocandolo di nuovo per uscire restituendo un codice di risultato.

Se la tua applicazione è un'applicazione grafica, potrebbe essere

void main( Graphical2DRuntimeEnvironment environment )

Se si tratta di un servizio Web potrebbe essere

void main( WebServiceRuntimeEnviroment environment )

... e così via e così via.

Indipendentemente dai servizi, dalle funzionalità, dalle librerie, chiamali come preferisci, dovresti essere in grado di ottenerli chiedendo loro l'ambiente e la combinazione di parole chiave public static dovrebbe essere proibita solo per i primitivi.

Ma mentre nessuno impone questo stile di cose, niente ti impedisce di farlo volontariamente. Puoi iniettare qualsiasi cosa come dipendenza. Vuoi alcuni esempi che puoi utilizzare in questo momento nelle applicazioni che si trovano attualmente nel tuo disco rigido?

Crea un'interfaccia Logger e passa a tutte le tue classi invece di utilizzare magicamente una funzione di registrazione onnipresente, onnipotente e, in definitiva, malvagia e staticamente disponibile.

Crea un'interfaccia Clock e passa a qualsiasi codice che ha bisogno dell'ora corrente, in modo che tu non ottenga il tempo corrente usando new Instance() , rendendo così il tuo codice dipendente dal tempo verificabile .

Crea un'interfaccia FileSystem e passa a qualsiasi tuo codice che deve gestire i file, in modo che non utilizzi l'operatore new per creare istanze direttamente da java.io . In questo modo, il codice di manipolazione dei file può essere testato utilizzando un filesystem implementato in memoria, quindi i tuoi test possono essere molto più veloci.

E l'elenco continua.

    
risposta data 27.09.2015 - 19:51
fonte
2

A Dipendenza è qualsiasi parte di logica da cui dipende il tuo codice. La sua inversione di controllo perché il metodo alternativo di implementazione della logica sarebbe

dependency.Logic(myObject)

vs

myObject.Logic(dependency)

il primo richiede che la dipendenza conosca e abbia accesso alle proprietà di myObject, dove il secondo consente di costruire e utilizzare myObject in modo OOP e mantenere la logica di dipendenza in una classe separata

    
risposta data 27.09.2015 - 18:26
fonte
2

Qualsiasi oggetto può essere registrato con DI. I vari tipi di metodi di registrazione in angolare sono semplicemente convenzioni. .service non ha davvero bisogno di registrare un servizio. Né .controller deve registrare un controller. Angular è mirato all'interfaccia utente, quindi i suoi metodi di registrazione sono mirati a tipi predefiniti di componenti che sono comunemente usati in ambito angolare.

Tutti questi metodi registrano solo una funzione / oggetto e non importa se un servizio è realmente registrato con .service . Le uniche differenze tra loro (generalmente) sono:

  • Se l'oggetto è nuovo ogni volta (chiamato durata dell'oggetto qui)
  • Come viene creato l'oggetto

Lifetime

Quindi un oggetto registrato con .service viene creato nuovo solo una volta durante l'intera applicazione. Quello stesso oggetto è tenuto in memoria (con tutti i suoi valori correnti) e iniettato ogni volta che un altro componente lo richiede. Le modifiche apportate da ComponentA possono essere viste da ComponentB e viceversa.

Ma un oggetto .controller viene creato nuovo ogni volta prima di essere iniettato. ComponentA e ComponentB ottengono le proprie copie dell'oggetto. Se ComponentA imposta un valore sul controller, tali modifiche appartengono solo a ComponentA. ComponentB non li vedrà mai.

Questa è la differenza nelle vite. (In altri quadri ci sono vite aggiuntive. Non sono sicuro se l'angolare ha più di questi due.)

Creazione oggetto

.service e .factory sono entrambi "nuovi solo una volta", ma si differenziano per la modalità di creazione dell'oggetto. Per un servizio, il framework angolare utilizza new per creare l'oggetto.

var createdObject = new MyService();

Ma una fabbrica è chiamata come metodo.

var createdObject = FactoryFunction();

Altri framework

Molti altri contenitori DI sono usati in modo più generico. Invece di avere diversi metodi di registrazione per specificare una combinazione di durata e creazione, ti consentono di fornirli discretamente quando registri l'oggetto. Considera quanto segue.

public class WarriorModule : NinjectModule
{
    public override void Load() 
    {
        // IWeapon will be created with: new Sword()
        // the same Sword will be used for every IWeapon requested
        // similar to angular's .service registration
        this.Bind<IWeapon>().To<Sword>().InSingletonScope();

        // will be created by calling a function
        // similar to .factory registration
        this.Bind<IWeapon>().ToMethod(context => new Sword()).InSingletonScope();

        // new sword created every time it is injected for IWeapon
        // similar to .controller registration
        this.Bind<IWeapon>().To<Sword>();
    }
}
    
risposta data 28.09.2015 - 00:22
fonte

Leggi altre domande sui tag