È una cattiva progettazione per specificare i bind predefiniti quando si utilizzano i contenitori di Inversion of Control (IOC) e l'iniezione di dipendenza (DI)?

3

Sto usando Ninject , ma questa non è una domanda specifica per Ninject. Mi chiedo se le funzionalità avanzate e flessibili del contenitore IoC mi stiano dando abbastanza corda per impiccarmi con un cattivo design dell'applicazione.

Ho un'interfaccia di servizio:

public interface IBuilderService {
    IBuilder Create(string category, string clientID);
}

e apprezzo l'estensione di fabbrica di Ninject ToFactory() per creare quello che immagino tu " d chiama un'implementazione proxy in fase di runtime.

Ho associazioni IBuilder come questa:

kernel.Bind<IBuilder>().To<NullObjectBuilder>(); // for unbound categories
kernel.Bind<IBuilder>().To<CatOneBuilder>();
kernel.Bind<IBuilder>().To<CatTwoBuilder>();
kernel.Bind<IBuilder>().To<CatThreeBuilder>();
kernel.Bind<IBuilder>().To<CatOneBuilder_ClientA>();
kernel.Bind<IBuilder>().To<CatOneBuilder_DefaultClient>(); // for unbound clients
// etc...

Ho sperimentato fornitori di istanze personalizzate e generatori di binding con Ninject (suppongo che altri contenitori IoC possano avere costrutti simili per ignorare il comportamento di base degli attacchi), ma ho due obiettivi di scenario vincolanti distinti :

  1. se una categoria di associazione non può essere risolta dall'argomento IBuilderService.Create category , allora una NullObjectBuilder dovrebbe essere risolta - questa è l'associazione predefinita in questo caso.
  2. se non è possibile risolvere un ID cliente di un'associazione, è necessario risolvere un'implementazione client predefinita come CatOneBuilder_DefaultClient per una category di CatOne - questo è predefinito vincolante in questo caso.

Questa è una situazione in cui le richieste di categoria sconosciute sono previste , quindi sembra un peccato usare una costosa gestione delle eccezioni per qualcosa che so succederà molto spesso. Voglio che ci sia un comportamento di fallback per " gestire il non gestito " in un modo molto semplice - in questo caso, sarebbe NullObjectBulder per le categorie sconosciute e *_DefaultClient per sconosciuto client di categorie conosciute - due comportamenti di fallback distinti per due diversi tipi di comportamento sconosciuto.

Ho difficoltà a mantenere i due comportamenti di fallback mappati ai loro rispettivi scenari, ma mi ha dato una pausa per pensare all'attrito che mi sento nel ritagliare questo progetto ...

È un design difettoso avere i collegamenti predefiniti e la logica utilizzata per determinare quando è necessario contenuta nelle implementazioni personalizzate IoC, piuttosto che un'eccezione generata? Si tratta di un cattivo utilizzo dei contenitori IoC?

    
posta Jeff 15.04.2013 - 20:56
fonte

1 risposta

3

Non è un uso improprio ... ma non è necessariamente un buon design.

Dipende davvero dal contesto.

  • Se lo scopo è quello di consentire di creare configurazioni semplici in un modo meno dettagliato, e le impostazioni predefinite sono tali da raggiungere tale obiettivo ... quindi questo suggerirebbe che questo è un buon progetto.

  • Se lo scopo è quello di consentire di essere incurante senza ottenere eccezioni e / o l'impostazione predefinita rischia di generare configurazioni che potrebbero non essere corrette (rispetto a ciò che intendevi) ... che suggerirebbe un design scadente .

L'uso (o meno) del default è un compromesso tra la "bontà" di rendere le cose esplicite e la "cattiveria" dell'essere prolissi. Hai davvero bisogno di decidere da te cosa funzionerà meglio per te nel contesto del tuo problema.

O un altro modo di guardarlo è dire che dovresti essere selettivo in quali "punti di iniezione" definisci i valori predefiniti.

    
risposta data 16.04.2013 - 01:05
fonte