Attualmente sto lavorando con la seguente astrazione.
public interface IFileRepository
{
void Save(string identifier, byte[] content);
Task SaveAsync(string identifier, byte[] content);
string GetUri(string identifier);
}
I servizi applicativi utilizzerebbero questa interfaccia per salvare i file su una posizione basata su un determinato identificatore e anche per recuperare un Uri in base a tale identificativo.
Questo costringe già alcuni clienti a sapere più del necessario. Ad esempio, un client che recupera e prepara un elenco di prodotti per mostrarlo in una pagina HTML non deve sapere come salvare un'immagine di un prodotto, ma solo come accedere a quell'immagine tramite un dato Uri
.
Allo stesso modo alcune implementazioni potrebbero supportare il modello di programmazione async/await
che impone i metodi a Task
signature. Non solo questo è un dettaglio di implementazione, ma anche alcune implementazioni inizieranno a lanciare NotImplementedException
poiché potrebbero non supportare il modello async/await
. Mentre la prima violazione dell'ISP potrebbe non fare molto male, la seconda penso che raddoppierà quasi alcune interfacce solo perché un'implementazione supporta il modello di programmazione asincrona / attendi.
Come crei in modo efficiente questi tipi di astrazione in modo da essere sempre in linea con i principi SOLID?
Il mio primo pensiero è
public interface IFileRepository
{
void Save(string identifier, byte[] content);
string GetUri(string identifier);
}
public interface IAsyncFileRepository : IFileRepository
{
Task SaveAsync(string identifier, byte[] content);
}
Ma temo di finire nello stesso buco.