Ho due interfacce, una con e una senza parametri di tipo generico. L'interfaccia non generica viene utilizzata internamente in modo da poter memorizzare le istanze dell'interfaccia generica in una raccolta. Tutto andrebbe bene, tranne per il fatto che C # non genera firme di metodo basate sul tipo di ritorno. Ho un metodo in ogni interfaccia chiamata GetItems. Uno restituisce un IList l'altro un ILIST & Tt; Dal momento che non posso dare loro entrambi lo stesso nome, ho bisogno di inventare due nomi diversi che trasmettono entrambi quello che fanno. Ecco le interfacce:
public interface IBatchProcessingStorage {
void Enqueue(object o);
void Enqueue(IEnumerable items);
void Dequeue(object o);
void Dequeue(IEnumerable items);
IList GetItems(int maxItems);
}
public interface IBatchProcessingStorage<T> : IBatchProcessingStorage {
void Enqueue(T item);
void Enqueue(IEnumerable<T> item);
void Dequeue(T item);
void Dequeue(IEnumerable<T> item);
IList<T> GetItems(int maxItems);
}
Esiste un'attività che viene eseguita ogni tanto che ottiene elementi dall'archivio di elaborazione batch, li passa a una risorsa esterna e, se vengono elaborati dalla risorsa esterna, vengono rimossi dallo store. L'attività richiede l'interfaccia non generica, che è l'unica ragione per cui esiste. Ho creato una classe astratta che implementa entrambi e reindirizza le chiamate nell'interfaccia non generica a quelle generiche e quelle generiche sono astratte in questo modo:
public abstract class BatchProcessingStorage<T>
: IBatchProcessingStorage<T>
, IBatchProcessingStorage {
void IBatchProcessingStorage.Enqueue(object o) { Enqueue((T)o); }
void IBatchProcessingStorage.Enqueue(IEnumerable items) {
Enqueue((IEnumerable<T>)items); }
void IBatchProcessingStorage.Dequeue(object o) {
Dequeue((T)o); }
void IBatchProcessingStorage.Dequeue(IEnumerable items) {
Dequeue((IEnumerable<T>)items); }
IList IBatchProcessingStorage.GetItems(int maxItems) {
return this.GetItems(maxItems).ToArray(); }
public abstract void Enqueue(T item);
public abstract void Enqueue(IEnumerable<T> item);
public abstract void Dequeue(T item);
public abstract void Dequeue(IEnumerable<T> item);
public abstract IList<T> GetItems(int maxItems);
}
Questa dovrebbe essere la classe da cui i clienti erediteranno, ma non ho intenzione di forzarli nella nostra gerarchia ereditaria. Quindi potrebbero dover implementare entrambe le interfacce. Questo è il motivo della mia grande preoccupazione per i nomi. Non voglio che la nostra API abbia nomi di metodi crap. Quindi, che cosa dovrei chiamare GetItem in ogni classe che trasmette un significato senza sembrare che io stia lavorando intorno ai limiti della lingua?
Aggiornamento:
Per quelli di voi che pensano che io stia analizzando questo: abbiamo imparato molto sulla nostra API pubblica negli ultimi 5 anni. Ho una possibilità di ottenere questo nuovo giusto. Dopo di ciò siamo bloccati con ciò che viene rilasciato. Questa non è la tua applicazione software interna media. È una piattaforma software che è molto estensibile. È usato da alcune delle aziende più conosciute al mondo. Sarà molto difficile per loro onestamente salire sul palco delle nostre conferenze e promuovere l'utilità della nostra piattaforma software, se ha un'API schifosa. Questo non è eccessivamente complesso o troppo astratto. È progettato per soddisfare esigenze aziendali specifiche. I nostri clienti avranno bisogno di questo, meglio ancora, lo fanno già attraverso un'API con un nome molto basso e un sistema troppo complesso che ti fa saltare attraverso i cerchi per fare le cose (il senno di poi è sempre 20/20).