Termine tecnico per indicare l'opposto dell'iniezione di dipendenza?


12

Questa è più una nomenclatura (scrittura tecnica) piuttosto che una domanda puramente tecnica. Sto cercando di scrivere una proposta di refactoring (e farmi assegnare a me stesso) incentrata sull'espansione dell'iniezione di dipendenza nella nostra applicazione. Mentre usiamo Spring per i bean autowiring, ci sono ancora istanze che utilizzano istanze dei bean MyClass obj = new MyClass(...), che potrebbero essere totalmente iniettate. Vorrei fare in modo che la mia proposta utilizzasse una nomenclatura elegante e fare riferimento al modello di progettazione opposto a DI con un termine appropriato.

"Accoppiamento stretto" è un termine adeguato che si pone come un inno a DI?


1
Sì, l' accoppiamento descrive sia l'atto di usare nomi di classe espliciti in altre classi sia lo stato risultante di una base di codice.
Kilian Foth,

11
No, l'accoppiamento stretto descrive solo la proprietà del codice risultante, non il contrario di DI. Puoi usare DI e avere ancora un accoppiamento stretto per ragioni completamente diverse.
Doc Brown,


@EricKing in mostra. +1 a proposito.
candied_orange,

1
"Aspirazione di dipendenza" .
SeldomNeedy,

Risposte:


30

No. L'accoppiamento stretto è molto più di quello di cui si occupa l'iniezione di dipendenza.

L'iniezione di dipendenza esternalizza una decisione di attuazione. Questo fa molto per disaccoppiare, ma l'accoppiamento è molto più di questo.

Un buon inno per l'iniezione di dipendenza è la codifica dura di una dipendenza . Quando costruisci (usa nuovo o usa direttamente qualche factory) all'interno di un oggetto comportamentale hai confuso due preoccupazioni diverse. Un localizzatore di servizi aiuta a disaccoppiare ma ti lascia accoppiato al localizzatore di servizi stesso.

L'accoppiamento è molto più che separare costruzione e comportamento. Se ho 101 metodi che devono essere chiamati in un ordine particolare dalla classe A alla classe B, sono strettamente accoppiati. Non importa quanto siano meravigliosamente separate la costruzione e il comportamento.

L'accoppiamento è una misura dell'interdipendenza dei due oggetti. Tutto ciò che contribuisce a rendere difficile apportare modifiche in uno senza influire sull'altro sta contribuendo all'accoppiamento. L'iniezione di dipendenza aiuta in questo, ma non è tutto.


Sì, la codifica rigida (una dipendenza), invece di iniettarla (in fase di esecuzione) è esattamente ciò che stavo per suggerire, tu eri solo un po 'più veloce di me.
Doc Brown,

7
@DocBrown A volte vorrei che questo posto non ponesse così tanta enfasi sull'essere veloce. Mi piacerebbe sapere come l'avresti messo.
candied_orange,

Buona risposta: l'iniezione di dipendenza non implica il disaccoppiamento. Credere altrimenti porta su una brutta strada
Ant P

1
@CandiedOrange Forse qualcuno dovrebbe suggerire in meta che le risposte rimangano nascoste per un periodo di tempo. E / o che i voti siano nascosti alla vista del pubblico per Nore ... O fino a quando non viene selezionata una risposta. So di non essere del tutto obiettivo quando una risposta ha già 10 voti e le altre 5 non ne hanno!
svidgen,

1
@svidgen cerca "la pistola più veloce in Occidente" su meta. Il problema ha già una lunga storia.
candied_orange,

6

A rigor di termini, l' iniezione di dipendenza si oppone davvero NON a iniezione di dipendenza - e quindi a qualsiasi strategia di gestione delle dipendenze che non sia iniezione di dipendenza.

L'accoppiamento [indesiderato], sebbene non esattamente un problema ortogonale, può verificarsi o essere mitigato in entrambi i modi. Entrambi sono accoppiati a DependencyClass:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructorè accoppiato a un particolare DependencyClassin questo caso. Ma sono entrambi accoppiati a DependencyClass. Il vero male, se ce n'è uno qui, non è necessariamente l'accoppiamento, è che DependencyLookupConstructordeve cambiare se DependencyClassimprovvisamente ha bisogno delle sue dipendenze iniettate 1 .

Tuttavia, questo costruttore / classe è ancora più liberamente accoppiato:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

Se lavori in C #, quanto sopra ti consentirà ServiceLocatordi restituire qualsiasi cosa quando GetMyDoer()viene invocata, a patto che abbia do()ciò che DependencyLocatingConstructorha do(). Ottieni il vantaggio della convalida della firma in fase di compilazione senza nemmeno essere accoppiato a un'interfaccia completa 2 .

Quindi, scegli il tuo veleno.

Ma fondamentalmente, se esiste un "opposto" concreto dell'iniezione di dipendenza, sarebbe qualcos'altro nel regno delle "strategie di gestione delle dipendenze". Tra l'altro, se hai usato uno dei seguenti argomenti nella conversazione, lo riconoscerei come NON Iniezione di dipendenza:

  • Pattern di localizzazione di servizio
  • Localizzatore / posizione delle dipendenze
  • Costruzione diretta di oggetti / dipendenze
  • Dipendenza nascosta
  • "Iniezione non dipendente"

1. Ironia della sorte, alcuni dei problemi che DI risolve ai livelli più alti sono una sorta di risultato di [over-] utilizzo di DI nei livelli inferiori. Ho avuto il piacere di lavorare su basi di codice con complessità inutile dappertutto a causa dell'accoglienza di una manciata di posti in cui quella complessità ha effettivamente aiutato ... Sono certamente influenzato da una cattiva esposizione.

2. L'utilizzo dell'ubicazione del servizio consente inoltre di specificare facilmente dipendenze diverse dello stesso tipo in base al loro ruolo funzionale rispetto al codice di invocazione , pur essendo in gran parte agnostico su come viene costruita la dipendenza. Supponiamo di dover risolvere Usero IUserper scopi diversi: ad esempio, Locator.GetAdministrator()contro Locator.GetAuthor()- o qualsiasi altra cosa. Il mio codice può chiedere di cosa ha bisogno funzionalmente senza nemmeno sapere quali interfacce supporta.


2
La salvezza DependencyInjectedConstructor(DependencyClass dep)è che DependencyClass potrebbe essere un'interfaccia o una classe astratta. Questo è il motivo per cui mi rattrista che i programmatori C # utilizzino un prefisso di interfaccia, come in IDependency. Come cliente, in realtà non è affar mio ciò che è questa dipendenza. Finché non lo costruisco, tutto quello che devo sapere è come parlarci. Qual è il problema di qualcun altro.
candied_orange,

A conti fatti, DI ti accoppia ancora a quell'interfaccia, e non richiede affatto che DependencyClasssia un'interfaccia astratta. Richiede solo che la logica di costruzione / configurazione / posizione esista "altrove". ... Bene, e più pertinentemente alla domanda, il punto è che DI non è "l'opposto dell'accoppiamento stretto" :)
svidgen

In realtà ... Potrei essere leggermente fuori dai limiti nel dire che DI ti accoppia necessariamente a un'interfaccia, anche in C #. Tuttavia, li ho evitati in C #, ho l'impressione di poter accettare anche i dynamicparametri. (Ma non varparametri, se la memoria serve.) Quindi, con DI in C #, penso che dovrei o codificare contro un'interfaccia, o devo rinunciare totalmente alla validazione in fase di compilazione.
svidgen,

Gli oggetti sono accoppiati alle interfacce. Se si utilizza o meno la parola chiave dell'interfaccia. Ecco cos'è un'interfaccia corretta. Tutto quello che DEVI essere accoppiato. Ciò che bolle sono i dettagli di implementazione e le cose extra che non ti servono. Possiamo formalizzare questo utilizzando la parola chiave dell'interfaccia per consentire al cliente di dire al mondo "Tutto ciò di cui ho bisogno è questo". Ma non dobbiamo. Diamine, possiamo scrivere l'anatra, bene in alcune lingue.
candied_orange,

Non sono sicuro che siamo in totale disaccordo. Ma, per chiarire ... Gli oggetti sono internamente accoppiati alle proprie interfacce, sì. Tuttavia, l'interfaccia stessa impone l'accoppiamento delle dipendenze solo se l'interfaccia viene esplicitamente denominata. In C #, usando dynamico vare ottenendo un oggetto da un localizzatore, ignoriamo l'interfaccia e utilizziamo qualsiasi classe in grado di fare do()ciò di cui hai bisogno, indipendentemente dal fatto che quella classe implementi qualche IDoerinterfaccia. In altre parole, se abbiamo A-> B <-C, DI disaccoppia A da C, ma richiede che A e C siano accoppiati a B e impedisce l'uso di D, anche se D lo farà do().
svidgen,

2

Non so che esiste una terminologia specifica e ampiamente accettata del settore, ma le alternative che vengono in mente includono la creazione di istanze interne , la creazione di dipendenze interne , le dipendenze locali o le dipendenze localmente .


2
mi piace instance creationma non è abbastanza specifico. DI crea istanze ma tramite controller e non a livello di applicazione. forseinternal instance creation
anfibio,

1

Vorrei andare con l' incapsulamento delle dipendenze . Questo esprime la dipendenza è bloccata piuttosto che visitare e lasciare di nuovo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.