Sto lavorando su un'applicazione in cui ho progettato classi per adattarsi a diversi gruppi:
- Immutabile: inizializzato tramite costruttori, utilizza l'idioma copy-and-swap (inc. move), può copiare in profondità (cioè clone), ha solo "getter" (non "setter") e implementa operatori di confronto (==,! =);
- Servizi: classi stateless che hanno metodi che accettano immutabili e / o servizi per eseguire le funzioni desiderate;
- Costruttori: fabbriche ecc. per costruire immutables.
Il test delle unità sui miei immutables è stato semplice. Posso usare l'iniezione di dipendenza attraverso i costruttori. Ciò significa che posso scambiare le classi di test per assicurarmi di essere un test unitario (al contrario dei test di integrazione). Posso usare i costruttori per costruire i miei oggetti di produzione. Questo elemento del mio design mi soddisfa in termini di test e produzione.
Tuttavia, sui miei servizi mi sembra di essere in grado di mantenere queste classi stateless e testabili dell'unità usando l'integrazione delle dipendenze tramite gli argomenti del metodo.
Per i miei servizi, una funzione di esempio cambia da:
virtual unsigned long foo() const override final;
... a:
virtual unsigned long foo(const ISomeInterface & dependency) const override final;
Questo significa che le mie classi di servizio sono testabili, ma ora devo istanziare le dipendenze al di fuori della classe quando si utilizza il codice in produzione. Ad esempio:
// without dependency injection
Service service;
return service.foo();
// with dependency injection
Service service;
Dependency dependency;
return service.foo(dependency);
Questo ha portato a un gran numero di mie classi di servizio che ora richiedono almeno 1 argomento in più per ogni metodo di classe. Nota: questo è l'approccio che sto attualmente utilizzando nel mio codice.
La mia domanda è questa:
Quali alternative ho a questa forma di iniezione delle dipendenze che mi permette di:
- unit test delle classi stateless (senza le dipendenze)
- mantieni queste classi senza stato
- riduci / nascondi il codice che crea un'istanza delle dipendenze (in particolare se un oggetto ha più dipendenze)
Nota - Sto anche eseguendo test di integrazione, che testano le reali dipendenze tra gli oggetti.