Secondo SOLID, non solo dovresti creare l'interfaccia, e non solo dovrebbe essere in un file diverso, dovrebbe essere in un altro assembly.
Perché? Poiché qualsiasi modifica a un file di origine che viene compilato in un assieme richiede la ricompilazione dell'assieme e qualsiasi modifica a un assieme richiede la ricompilazione di qualsiasi assembly dipendente. Quindi, se il tuo obiettivo, basato su SOLID, è di essere in grado di sostituire un'implementazione A con un'implementazione B, mentre la classe C dipendente dall'interfaccia I non deve conoscere la differenza, devi assicurarti che l'assembly con I in esso non cambia, proteggendo così gli usi.
"Ma è solo una ricompensa" ti sento protestare. Beh, potrebbe essere, ma nella tua app per smartphone, che è più facile sulla larghezza di banda dei dati degli utenti; scaricare un file binario modificato o scaricare quel file binario e altri cinque con codice che dipende da esso? Non tutti i programmi sono scritti per essere consumati dai computer desktop su una LAN. Anche in questo caso, dove la larghezza di banda e la memoria sono economiche, le patch release più piccole possono avere valore perché sono banali da esportare all'intera LAN tramite Active Directory o livelli simili di gestione dei domini; i tuoi utenti attenderanno solo pochi secondi per essere applicati la prossima volta che accederanno invece di pochi minuti per la reinstallazione del tutto. Senza contare che, meno componenti devono essere ricompilati durante la creazione di un progetto, più veloce sarà il suo sviluppo, rendendoti più produttivo perché trascorri meno tempo rimanendo in attesa di 50 assemblaggi da compilare per ogni modifica apportata.
Ora, il disclaimer: questo non è sempre possibile o fattibile. Il modo più semplice per farlo è creare un progetto di "interfacce" centralizzato. Questo ha i suoi lati negativi; il codice diventa meno riutilizzabile perché il progetto di interfaccia AND il progetto di implementazione devono essere referenziati in altre app riutilizzando il livello di persistenza o altri componenti chiave della tua app. È possibile superare questo problema suddividendo le interfacce in assiemi più strettamente accoppiati, ma in tal caso si hanno più progetti nell'app che rendono molto complessa la creazione completa. La chiave è il bilanciamento e il mantenimento del design liberamente accoppiato; di solito puoi spostare i file in base alle necessità, così quando vedi che una classe avrà bisogno di molte modifiche, o che le nuove implementazioni di un'interfaccia saranno necessarie regolarmente (magari per interfacciarti con le nuove versioni supportate di altri software, o tipi di file, ecc. ) puoi separarlo dalla sua interfaccia e proteggere gli usi dalla conoscenza di tali cambiamenti.