Progettazione / Architettura per il passaggio dei parametri di taglio trasversale tramite costruttori a radici di composizione?

2

Abbiamo un'applicazione ASP.NET MVC e un mucchio di librerie che vengono utilizzate dall'applicazione. Esistono preoccupazioni trasversali e dipendenze come logger, repository, token utente ecc. Che quasi tutte queste librerie devono funzionare. Alcune librerie dipendono da altre librerie e così via.

Ad esempio -

                                  MVC Application 
                                         |
                 ----------------------------------------------
                 |                       |                    |
        AccountingEngine Lib      FileParser Lib        Another Lib1      
               /                                      
       AnotherLib2 etc

Nel progetto corrente, l'applicazione MVC passa le dipendenze alle librerie tramite i parametri del costruttore, il che significa che i costruttori delle radici di composizione delle librerie tendono tutte a assumere forme simili a (CCC = preoccupazione di taglio incrociato) -

public AccountingEngine(IPrincipalToken principalToken, IRepository repository, 
    ILogger logger, IOtherCCC1 ccc1, IOtherCCC2 ccc2, IOtherCCC2 ccc2) { ... }

public FileParser(IPrincipalToken principalToken, IRepository repository, 
    ILogger logger, IOtherCCC1 cc1, IOtherCCC2 cc2, IOtherCCC2 cc2) { ... }

etc..

I controller nell'applicazione MVC usano ninject per ottenere alcune delle dipendenze e passarle nelle librerie.

Credo che questo sembra raggiungere il DI di un povero uomo e assicura che le dipendenze siano esplicite. È un buon design? Per prima cosa, ci sono molti parametri del costruttore (che a quanto pare sono un odore di codice anche se in questo caso i parametri non sono molti a causa di una violazione di SRP) e per un altro, quasi tutte le classi (anche non root) finiscono con tutto questi parametri. Potrebbero esserci più problemi con questo modello di quanto non ne sia a conoscenza.

Esistono pratiche / modelli standard consigliati per questo scenario e problemi associati?

    
posta Achilles 31.01.2017 - 18:37
fonte

1 risposta

2

Alcuni punti che vorrei prendere in considerazione:

  1. Non è normale che ci siano un sacco di argomenti del costruttore in un progetto basato su DI. Ci vuole un po 'per abituarsi, ma niente di cui preoccuparsi troppo.

  2. In generale è meglio iniettare una fabbrica di un'istanza specifica. Ciò consentirà al componente che riceve l'iniezione di specificare eventuali parametri aggiuntivi per la costruzione, ad es. se passi ICustomerFactory , il componente può utilizzarlo per ottenere l'istanza specifica del cliente necessaria (ad esempio var c = ((ICustomerFactory)factory).GetCustomer(customerID) ).

  3. Invece di iniettare un IPrincipalToken , passa un oggetto di tipo "contesto" (ad es. AuthenticationContext ) che può essere usato per recuperare il token. Questo può ridurre il numero di iniezioni necessarie se, per esempio, il componente richiede non solo il token ma anche l'ID e il nome dell'utente. Renderà più semplice anche lo stub, poiché sarebbe necessaria solo una stub.

  4. Dovresti davvero passare all'utilizzo di un contenitore IoC (come AutoFac) per risolvere i tuoi riferimenti. Non è tanto lavoro, e renderà più semplice per i tuoi sviluppatori capire e modificare il codice.

risposta data 21.02.2017 - 03:45
fonte

Leggi altre domande sui tag