Il principio di inversione delle dipendenze riguarda più le dipendenze tra moduli / progetti / pacchetti / librerie che tra classi.
Modulo / Dominio del progetto
public interface IRepository
{
void Save(object data);
}
public class Order
{
private readonly IRepository _repository;
public Order(IRepository repository) => _repository = repository;
public void Save(object data) => _repository.Save(data)
}
Modulo / Database del progetto
using Domain;
public class SqlServerRepository : IRepository
{
public void Save(object data)
{
// SqlConnection, SqlCommand, Execute ...
}
}
L'applicazione avrà solo un modulo "principale" - Punto di ingresso, che conoscerà tutti gli altri moduli.
Il modulo del punto di ingresso sarà responsabile della compilazione del grafico dell'oggetto richiesto per la tua applicazione (istanziare e iniettare le implementazioni corrette)
-------------------------- ------------------------
| **Domain** | | **Database** |
| | <-------------- | |
| IRepository | | |
-------------------------- ------------------------
^ ^
| |
| |
| ----------------------- |
| | **Main** | |
|------------| |-----------|
| |
-----------------------
Punto di ingresso
using Domain;
using Database;
public class Program
{
public static void Main()
{
var sqlServerRepository = new SqlServerRepository();
var order = new Order(sqlServerRepository);
Run(order); // Run appliciation
}
}
Come puoi vedere, il modulo Dominio non è in grado di creare un'istanza di SqlServerRepository
.
Il principio di inversione delle dipendenze applicato per i moduli impedirà al modulo Dominio di istanziare le istanze del modulo Database solo perché il modulo Dominio non conoscerà l'esistenza del modulo Database.
L'idea del principio Dependency Inversion è di cambiare la direzione di dipendenza che abbiamo in fase di esecuzione durante la fase di progettazione.
Direzione dipendenza runtime
Order -> SqlServerRepository
Direzione dipendenza dal tempo di progettazione
SqlServerRepository -> Order
Uno dei vantaggi è la riduzione dei tempi di costruzione dei grandi progetti quando si apportano modifiche in moduli di basso livello.
Ad esempio: posso apportare modifiche al modulo Database senza dover ricostruire il modulo Dominio.
L'inversione della dipendenza all'interno di un modulo non ha molto senso, dal momento che le classi già sanno l'una dell'altra e il cambiamento in una classe richiederà la ricostruzione di un modulo.
Non è necessario scrivere contro l'interfaccia all'interno di un modulo, a meno che non si disponga di implementazioni diverse per un'astrazione.