Qual è un buon esempio pratico che dimostra un vantaggio architettonico nell'integrazione delle dipendenze dell'interfaccia

0

Ho bisogno di aiuto (preferibilmente per mezzo di un esempio pratico) per capire perché / se la seguente implementazione di IoC / DI (in questo caso usando Ninject) fornisce un vantaggio architettonico:

using (IKernel kernel = new StandardKernel())
{
    kernel.Bind<ITaxCalculator>()
          .To<TaxCalculator>()
          .WithConstructorArgument("rate", .2M);

    var tc = kernel.Get<ITaxCalculator>();
    Assert.Equal(20M, tc.CalculateTax(100M));
}

Per quanto posso vedere, il pattern in realtà non garantisce una maggiore probabilità di riutilizzo dell'interfaccia usando l'interfaccia come DI. Potremmo facilmente ottenere una garanzia di riutilizzo delle interfacce semplicemente ereditando l'interfaccia all'interno di una classe "TaxCalculator", e avremmo quindi un modo più semplice e leggibile di chiamare un "metodo CalculateTax".

Al momento non mi interessa l'unità o i benefici del test di integrazione del modello, solo un esempio tangibile o anche una giustificazione astratta di come il modello sopra può aiutare a ottenere qualsiasi beneficio (ad esempio l'accoppiamento libero) in un modo che non può essere raggiunto senza usare DI.

    
posta Johnny 03.02.2015 - 08:28
fonte

1 risposta

3

Ottieni alcune cose usando IoC e DI:

1. Sostituzione più semplice dell'implementazione sottostante:

Ciò che intendo è che è possibile modificare l'implementazione in un unico punto e quindi presumere che tutto ciò che sta iniettando l'interfaccia utilizzi invece la nuova implementazione.

Oggi hai

kernel.Bind<ITaxCalculator>().To<TaxCalculator>()

Domani potresti avere

kernel.Bind<ITaxCalculator>().To<BetterTaxCalculator>()

Usando IoC, devi semplicemente cambiare questa riga e tutto il resto verrà iniettato nella nuova implementazione. Senza di esso, devi passare tutto il codice e modificare tutte le classi che utilizzano TaxCalculator in BetterTaxCalculator .

Questo non è sempre qualcosa che vorresti fare ovviamente, ma potrebbero esserci delle volte in cui dovresti farlo (specialmente se stai facendo le tue iniezioni via XML e vuoi cambiare le strategie senza cambiare il codice).

2. MOLTO più facile gestione delle interdipendenze.

Più facile da spiegare con un esempio. Diciamo che oggi questa è la tua classe:

public class TaxCalculator 
{
    public TaxCalculator() { }
}

Senza l'iniezione delle dipendenze, si crea un'istanza come questa:

var taxCalculator = new TaxCalculator();

Con:

kernel.Get<ITaxCalculator>();

Implementazione di domani:

public class TaxCalculator 
{
    public TaxCalculator(IAdder adder, ISubstractor substractor) { }
}

Senza l'iniezione delle dipendenze, si crea un'istanza come questa:

var taxCalculator = new TaxCalculator(new Adder(), new Substractor());

Con:

kernel.Get<ITaxCalculator>(); // it's the same!!!! :-o

Potrebbe essere difficile da apprezzare, ma in app più grandi con molti livelli di gerarchia, questa è una vera manna! Ciò significa che gli utenti del mio ITaxCalculator non hanno bisogno di sapere quali interfacce sono necessarie per creare un'istanza di TaxCalculator che significa, se decido di aggiungere un nuovo IMultiplier al mio costruttore in una settimana, io non è necessario toccare il codice per gli utenti della mia API. L'unica cosa che devono cambiare è la parte in cui impostano il loro DI (iniettando un IMultiplier).

Molto probabilmente avrai solo un posto nel tuo intero codice che inietta le tue interfacce ma potrebbe avere un sacco di posti che necessitano di un ITaxCalculator che avrebbe avuto bisogno di essere cambiato se non stavi usando un DIF.

3. Gestione del ciclo di vita dei tuoi oggetti.  Con la maggior parte dei framework DI, è molto facile definire se vuoi che i tuoi oggetti siano di breve durata, singleton globali o, massimo% di istanze din o qualsiasi altro comportamento di fantasia che desideri.

Sono sicuro che ce ne sono altri, ma questi erano quelli a cui potevo pensare per ora.

    
risposta data 03.02.2015 - 10:23
fonte