In quale spazio dei nomi dovresti mettere le interfacce relative ai loro implementatori?

StackOverflow https://stackoverflow.com/questions/146777

  •  02-07-2019
  •  | 
  •  

Domanda

In particolare, quando si crea una coppia interfaccia / implementatore e non vi sono preoccupazioni organizzative prevalenti (come l'interfaccia dovrebbe andare in un assembly diverso, ad esempio, come raccomandato dall'architettura s #) si dispone di un modo predefinito di organizzare nel tuo spazio dei nomi / schema di denominazione?

Questa è ovviamente una domanda più basata sull'opinione, ma penso che alcune persone ci abbiano pensato di più e tutti noi possiamo trarre beneficio dalle loro conclusioni.

È stato utile?

Soluzione

La risposta dipende dalle tue intenzioni.

  • Se intendi che il consumatore dei tuoi spazi dei nomi utilizzi le interfacce sulle implementazioni concrete, consiglierei di avere le tue interfacce nello spazio dei nomi di livello superiore con le implementazioni in uno spazio dei nomi figlio
  • Se il consumatore deve usare entrambi, li hanno nello stesso spazio dei nomi.
  • Se l'interfaccia è principalmente per uso specializzato, come la creazione di nuove implementazioni, prendere in considerazione l'idea di averle in uno spazio dei nomi figlio come Design o ComponentModel.

Sono sicuro che ci sono anche altre opzioni, ma come per la maggior parte dei problemi relativi allo spazio dei nomi, dipende dai casi d'uso del progetto e dalle classi e dalle interfacce che contiene.

Altri suggerimenti

Di solito mantengo l'interfaccia nello stesso spazio dei tipi concreti.

Ma questa è solo la mia opinione e il layout dello spazio dei nomi è altamente soggettivo.

Animals
|
| - IAnimal
| - Dog
| - Cat
Plants
|
| - IPlant
| - Cactus

Non ottieni davvero nulla spostando uno o due tipi fuori dallo spazio dei nomi principale, ma aggiungi il requisito per un'istruzione using in più.

Quello che generalmente faccio è creare uno spazio dei nomi di Interfacce ad alto livello nella mia gerarchia e inserire tutte le interfacce (non mi preoccupo di nidificare altri spazi dei nomi lì come finirei con molti spazi dei nomi che contengono solo un'interfaccia ).

Interfaces
|--IAnimal
|--IVegetable
|--IMineral
MineralImplementor
Organisms
|--AnimalImplementor
|--VegetableImplementor

Questo è solo il modo in cui l'ho fatto in passato e non ho avuto molti problemi con esso, anche se, certamente, potrebbe essere fonte di confusione per gli altri seduti con i miei progetti. Sono molto curioso di vedere cosa fanno gli altri.

Preferisco mantenere le mie interfacce e le classi di implementazione nello stesso spazio dei nomi. Quando possibile, offro visibilità interna alle classi di implementazione e fornisco una fabbrica (di solito sotto forma di un metodo di fabbrica statica che delega a una classe di lavoro, con un metodo interno che consente a un'unità di test in un assieme amico di sostituire un lavoratore diverso che produce tronchetti). Certo, se la classe concreta deve essere pubblica - per esempio, se è una classe base astratta, allora va bene; Non vedo alcun motivo per mettere una ABC nel suo spazio dei nomi.

In una nota a margine, non mi piace molto la convenzione .NET di prefacciare i nomi delle interfacce con la lettera 'I.' La cosa i modelli di interfaccia (I) Foo non è un ifoo , è semplicemente un foo . Quindi perché non posso semplicemente chiamarlo Foo? Dico quindi le classi di implementazione specificatamente, ad esempio AbstractFoo, MemoryOptimizedFoo, SimpleFoo, StubFoo ecc.

(.Net) Tendo a mantenere le interfacce in un "comune" separato assembly in modo da poter utilizzare quell'interfaccia in diverse applicazioni e, più spesso, nei componenti server delle mie app.

Per quanto riguarda gli spazi dei nomi, li conservo in BusinessCommon.Interfaces.

Faccio questo per garantire che né io né i miei sviluppatori siamo tentati di fare riferimento direttamente alle implementazioni.

ODIO quando trovo interfacce e implementazioni nello stesso spazio dei nomi / assembly. Per favore, non farlo, se il progetto si evolve, è una seccatura nel refactoring.

Quando faccio riferimento a un'interfaccia, voglio implementarla, non per ottenere tutte le sue implementazioni.

Ciò che potrei essere ammissibile è mettere l'interfaccia con la sua classe di dipendenza ( classe che fa riferimento all'interfaccia ).

EDIT: @Josh, ho appena letto l'ultima mia frase, è confuso! ovviamente, sia la classe di dipendenza che quella che la implementano fanno riferimento all'interfaccia. Per chiarirmi, farò degli esempi:

Accettabile:

Interfaccia + implementazione:

namespace A;

   Interface IMyInterface
   {
       void MyMethod();
   }

namespace A;

   Interface MyDependentClass
   {
       private IMyInterface inject;

       public MyDependentClass(IMyInterface inject)
       {
           this.inject = inject;
       }

       public void DoJob()
       {
           //Bla bla
           inject.MyMethod();
       }
   }

Classe di esecuzione:

namespace B;

   Interface MyImplementing : IMyInterface
   {
       public void MyMethod()
       {
           Console.WriteLine("hello world");
       }
   }

NON ACCETTABILE:

namespace A;

   Interface IMyInterface
   {
       void MyMethod();
   }

namespace A;

   Interface MyImplementing : IMyInterface
   {
       public void MyMethod()
       {
           Console.WriteLine("hello world");
       }
   }

E per favore NON CREARE un progetto / immondizia per le tue interfacce! esempio: ShittyProject.Interfaces. Hai perso il punto!

Immagina di aver creato una DLL riservata alle tue interfacce (200 MB). Se dovessi aggiungere una singola interfaccia con due righe di codice, i tuoi utenti dovranno aggiornare 200 MB solo per due signori stupidi!

Separare le interfacce in qualche modo (progetti in Eclipse, ecc.) in modo che sia facile distribuire solo le interfacce. Ciò consente di fornire l'API esterna senza fornire implementazioni. Ciò consente ai progetti dipendenti di essere creati con un minimo di esterni. Ovviamente questo vale più per i progetti più grandi, ma il concetto è buono in tutti i casi.

Di solito li separo in due assiemi separati. Uno dei soliti motivi di un'interfaccia è che una serie di oggetti abbia lo stesso aspetto di alcuni sottosistemi del software. Ad esempio, ho tutti i miei rapporti che implementano le interfacce IReport. IReport viene utilizzato non solo nella stampa, ma per l'anteprima e la selezione di singole opzioni per ciascun rapporto. Finalmente ho una raccolta di IReport da usare nella finestra di dialogo in cui l'utente seleziona quali rapporti (e opzioni di configurazione) vogliono stampare.

I rapporti risiedono in un assieme separato e IReport, il motore di anteprima, il motore di stampa, le selezioni dei rapporti risiedono nel rispettivo assieme principale e / o assieme UI.

Se si utilizza la Classe di fabbrica per restituire un elenco di report disponibili nell'assieme di report, l'aggiornamento del software con un nuovo report diventa semplicemente una questione di copia del nuovo assieme di report sull'originale. È anche possibile utilizzare l'API di Reflection per scansionare l'elenco degli assiemi per qualsiasi Fabbrica di report e creare così l'elenco dei report.

Puoi applicare queste tecniche anche ai file. Il mio software esegue una macchina per il taglio dei metalli, quindi usiamo questa idea per le librerie di forma e adattamento che vendiamo insieme al nostro software.

Anche in questo caso le classi che implementano un'interfaccia principale dovrebbero risiedere in un assembly separato in modo da poterlo aggiornare separatamente dal resto del software.

Offro la mia esperienza che è contro altre risposte.

Tendo a mettere tutte le mie interfacce nel pacchetto a cui appartengono. Ciò garantisce che, se sposto un pacchetto in un altro progetto, ho tutto ciò che deve essere per eseguire il pacchetto senza modifiche.

Per me, tutte le funzioni di supporto e le funzioni di operatore che fanno parte della funzionalità di una classe dovrebbero andare nello stesso spazio dei nomi di quella classe, perché fanno parte dell'API pubblica di quello spazio dei nomi.

Se hai implementazioni comuni che condividono la stessa interfaccia in pacchetti diversi, probabilmente dovrai riformattare il tuo progetto.

A volte vedo che ci sono molte interfacce in un progetto che potrebbero essere convertite in un'implementazione astratta piuttosto che in un'interfaccia.

Quindi, chiediti se stai davvero modellando un tipo o una struttura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top