Generics vs IoC [closed]

-2

Uno degli inconvenienti del pattern "Service Locator" è che un chiamante può essere ingannato riguardo alle dipendenze di un chiamato.

Ok, ma cosa succede se metto le dipendenze come parametri generici a livello di classe:

class Node<T> where T : ISomeInterface, new()
{
  ISomeInterface obj
  public Node()
  {
     obj = new T();
  }
}

Ho trovato un paio di opinioni qui. Ma voglio continuare una discussione .

Il controargomento più significativo è che l'iniezione di dipendenza mediante generici rende l'associazione tardiva non disponibile. Ma a chi importa nella maggior parte dei casi? Cosa succede se la mia app non ha bisogno di questa funzione?

Voglio trovare solidi argomenti contrari.

P.S. il nuovo vincolo () non è necessario, come hai capito.

    
posta EngineerSpock 01.10.2013 - 15:15
fonte

2 risposte

5

L'articolo collegato è un po 'fuorviante, secondo me. Sì, utilizzando i contenitori di Inversion of Control vengono visualizzati alcuni errori in fase di esecuzione anziché in fase di compilazione. E in generale, rende più fragile il processo di scrittura e mantenimento del codice. Questo vale per i localizzatori di servizio o per qualsiasi altro contenitore di oggetti della tecnologia dell'informazione nella mia esperienza. Questo non li rende anti-pattern.

La cosa fondamentale è che se non hai bisogno di quel tipo di comportamento del plug-in, allora non usarlo . Tutte le decisioni di progettazione sono un compromesso e, nel caso di IoC, quell'associazione tardiva (e la facilità di test) è ciò che ottieni e gli errori di runtime piuttosto che la compilazione del tempo (e la diminuzione della leggibilità / debug-abilità) è ciò che paghi.

In effetti, il tuo approccio predefinito dovrebbe essere semplicemente creare vecchi oggetti che prendono parametri nel loro costruttore. Una volta che è insufficiente, quindi iniziare a preoccuparti di trucchi fantasiosi.

    
risposta data 01.10.2013 - 15:37
fonte
2

Direi che la tua soluzione è in realtà peggiore dell'originale.

  1. Ti stai limitando a tipi con un costruttore predefinito. Cosa succede se si desidera utilizzare un tipo che richiede alcune configurazioni nel suo costruttore?
  2. Se si ha una dipendenza con una dipendenza con una dipendenza, si finisce con tipi orribili come Node<Foo<Bar<Baz>>> . Questo non ha molto senso, soprattutto perché nessuno dei membri del tipo in realtà dipende dai parametri del tipo.
  3. Devi specificare il tipo concreto di dipendenza al momento della compilazione. Questo rende il tuo codice molto meno flessibile e non puoi ad esempio cambiare la dipendenza semplicemente modificando un file di configurazione (che può essere utile).
  4. In che modo new Node<Foo>() è migliore di new Node(new Foo()) ?
risposta data 01.10.2013 - 15:59
fonte