I problemi con Evitare le classi di denominazione dei puffi con spazi dei nomi


39

Ho tirato denominazione il termine puffo da qui (numero 21). Per salvare chiunque non abbia familiarità con il problema, la denominazione di Puffo è l'atto di prefissare un gruppo di classi, variabili, ecc. Correlate con un prefisso comune in modo da finire con "a SmurfAccountViewpassa a SmurfAccountDTOa SmurfAccountController", ecc.

La soluzione che ho sentito in generale è creare uno spazio dei nomi puffo e rilasciare i prefissi puffi. Questo mi ha generalmente servito bene, ma sto incontrando due problemi.

  1. Sto lavorando con una biblioteca con una Configurationclasse. Potrebbe essere stato chiamato WartmongerConfigurationma è nello spazio dei nomi Wartmonger, quindi è appena chiamato Configuration. Allo stesso modo ho una Configurationclasse che potrebbe essere chiamata SmurfConfiguration, ma è nello spazio dei nomi Puffo, quindi sarebbe ridondante. Ci sono punti nel mio codice in cui Smurf.Configurationappare a fianco Wartmonger.Configuratione digitare nomi completi è goffo e rende il codice meno leggibile. Sarebbe più bello avere a che fare con un SmurfConfiguratione (se fosse il mio codice e non una libreria) WartmongerConfiguration.

  2. Ho una classe chiamata Servicenel mio spazio dei nomi Puffo che avrebbe potuto essere chiamata SmurfService. Serviceè una facciata sulla cima di una complessa libreria di Puffi che esegue lavori di Puffo. SmurfServicesembra un nome migliore perché Servicesenza il prefisso Puffo è così incredibilmente generico. Posso ammettere che SmurfServiceera già un nome generico, inutile e togliere puffo lo rendeva semplicemente più evidente. Ma avrebbe potuto essere chiamato Runner, Launcherecc. E mi starebbe ancora "meglio" SmurfLauncherperché non so cosa Launcherfa, ma so cosa SmurfLauncherfa. Si potrebbe sostenere che ciò che Smurf.Launcherfa dovrebbe essere altrettanto evidente di aSmurf.SmurfLauncher, ma ho potuto vedere `Puffo.Launcher essendo una sorta di classe relativa alla configurazione piuttosto che una classe che lancia puffi.

Se c'è un modo aperto e chiuso per affrontare uno di questi sarebbe fantastico. In caso contrario, quali sono alcune pratiche comuni per mitigare il loro fastidio?


3
Fa Smurf.Launcherpuffi di lancio, o lo fa lanciare SmurfJobs? Forse potrebbe essere chiamato Smurf.JobLauncher?
Blorgbeard,

2
È un odore di codice nominare una classe XService, XManager, ecc. Questi non significano nulla. È come un utensile. Se stai scremando i nomi dei file, qualcosa potrebbe essere lì dentro o mancare da lì. Non c'è modo di sapere se non guardi dentro. Lo rinominerei da SmurfService in qualcos'altro completamente.
Daniel Kaplan,

1
In realtà avvia SmurfJobs, o tecnicamente li esegue per essere coerenti con il linguaggio della documentazione di Puffo. Alla luce di questo e l'altro risponde, ho intenzione di rinominare SmurfServicea SmurfJobRunner. Sembra che il numero 1 non abbia una migliore risoluzione agnostica della lingua come mi aspettavo. Riesco a vedere casi in cui andare SmurfConfigurationsarebbe la chiamata giusta, ma nel mio caso penso che Configurationsia meglio anche con il fastidio di Wartmonger.Configuration.
Daniel Koverman,

6
Sto cercando di capire perché hai una sola classe che si preoccupa di configurare sia i Wartmongers che i Puffi.
Donal Fellows il

Perché fare Smurf.Configuratione SmurfConfigurationsentirsi diversi? Sicuramente non è il carattere extra, vero? (Accorciare Configse la lunghezza è il problema.) Ha Smurf.Configurationqualche problema che SmurfConfigurationnon lo fa?
Pablo H,

Risposte:


16

Sollevi alcuni punti positivi.

  1. Per quanto riguarda le classi duplicate, puoi alias le classi in C #. Utilizzare ad esempio using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;Vedere questo post su StackOverflow . Non hai indicato il tuo linguaggio di programmazione ma l'ho dedotto da ciò che hai scritto. Quindi, quando hai a che fare con due diversi progetti, puoi aliasarli SmurfConfiguratione WartmongerConfigurationciò libererebbe ambiguità quando consumano entrambe le classi.

  2. Poiché un servizio è esposto ad applicazioni esterne, non vedo alcun problema nel marchiare il servizio con il nome dell'applicazione, quindi in questo caso SmurfServicesarebbe valido in quanto disambiguerebbe effettivamente gruppi di servizi nell'applicazione che consuma.

Sento che gli spazi dei nomi dovrebbero essere usati per evitare questo stile di denominazione. Rende più difficile eseguire il grok del codice e vedere al valore nominale cosa è una classe senza leggere MyCompanyMyProductMyAreaClassName. L'uso della tecnica di aliasing consente di ridurre l'ambiguità laddove necessario. L'unica volta in cui penso che dovresti introdurre complessità nella tua denominazione è, come ho sottolineato nel n. 2, quando le persone consumeranno un servizio. È qui che ha perfettamente senso avere questo stile di denominazione perché se il consumatore ha una varietà di servizi sta consumando l'ambiguità potrebbe essere fonte di confusione.


5
gli alias confondono le cose. Invece di Puffo.Servizio ora hai SmurfService = Puffo.Servizio. Quindi potresti anche aver avuto SmurfService come nome della cosa in primo luogo. Hanno un posto, ma non per questo particolare problema. Tuttavia, è probabilmente la migliore risposta a un problema che non ha risposta :)
gbjbaanb

Il C # in me è emerso nella mia domanda, ma attualmente sto trattando con Java e org.apache.smurfville.wartmonger.configuration. Questo purtroppo esclude gli alias. 2 è un punto solido, quindi ho intenzione di mantenere il marchio Puffo per il Servizio.
Daniel Koverman,

25

Il punto degli spazi dei nomi è che puoi avere classi con lo stesso nome da diverse librerie senza che si scontrino. Quando è necessario utilizzare la stessa classe denominata da entrambi, è necessario rimuovere l'ambiguità anteponendo una o entrambe con l'ambito dello spazio dei nomi.

Detto questo, non è poi così male avere un sacco di lezioni di Puffo se Puffo ti dice qualcosa di specifico sulla classe. I nomi delle classi dovrebbero essere abbastanza descrittivi da darti alcune informazioni su ciò che fa la classe.

      Session
       ^   ^
      /     \
DBSession   HttpSession

Allo stesso modo un DBSessionpotrebbe prendere un DBRequestoggetto che restituisce un DBResponseoggetto. L' HttpSessionpotrebbero operare anche su HttpRequeste HttpResponseoggetti.

Queste sono classi di Puffo con uno scopo.

Potrebbero vivere nel MyCompanynamespace, ma MyCompanyHttpSessione MyCompanyDBSessionnon ti dà più informazioni di quanto si aveva prima. In questo caso rilasciare Puffo e renderlo uno spazio dei nomi.

MyCompany.HttpSession

3

Mi sono imbattuto in questo stesso punto di confusione prima e di solito è davvero una questione di includere il tipo di cosa che fa parte del suo nome.

Lei cita SmurfConfiguratione WartmongerConfigurationcome potenziali tipi di configurazioni. Indichi di aver rimosso l'aggettivo (il suo tipo) nel suo spazio dei nomi in modo che ciò che ti rimane sia solo la vaniglia Configuration. Eviterei di farlo.

È come decidere che il gelato alla fragola è solo un gelato nello spazio dei nomi delle fragole e allo stesso modo con il cioccolato, ma quello che è successo è che hai divorziato dall'aggettivo che gli conferisce la sua identità dalla cosa stessa. Non è un gelato nella categoria delle fragole. È un gelato alla fragola, una specie di gelato.

Immaginiamo che nella tua app, importi la Strawberry.IceCreamclasse e quindi inizi a creare un'istanza direttamente da IceCream.

var ic = new IceCream(); //actually I'm strawberry ice cream

Questo può sembrare buono e buono, fino al momento in cui finisci per importare un'altra IceCreamclasse. Ora sei tornato al problema originale di dover in qualche modo distinguerli, il che è problematico. Quello che volevi da sempre era:

var sic = new StrawberryIceCream();
var cic = new ChocolateIceCream();

Gli spazi dei nomi sono meglio lasciati per evitare potenziali conflitti tra terze parti che potrebbero incidentalmente rappresentare gli stessi concetti nelle loro librerie. Quando uno sviluppatore crea una libreria o un progetto, tuttavia, dovrebbe nominare ciascun concetto in modo univoco e utilizzare gli spazi dei nomi come cartelle solo per l'organizzazione. Spesso il nome della cartella si trova nel nome dei concetti che organizza e va bene.


2

È sicuramente una buona regola empirica che se hai un prefisso comune su un gruppo di classi, probabilmente meritano di andare nel loro spazio dei nomi. Per affrontare il problema, quindi, quando è necessario utilizzare classi con nomi simili da due spazi dei nomi:

1) Alias ​​gli spazi dei nomi, anche se lo renderei breve e al punto, qualsiasi abbreviazione naturale, forse anche solo 1 lettera:

using Sm = Smurf;
using W = Wartmonger;

Quindi aggiungi sempre il prefisso ovunque usato e assegna un nome alle istanze in modo appropriato:

Sm::Configuration smConf; 
W::Configuration wConf;

2) Alias ​​la classe, come suggerito in altre risposte.

using SmConf = Smurf.Configuration;

3) Qualsiasi libreria su cui hai il controllo, considera di non usare il termine "Configurazione". Usa il thesaurus: ad es. "Impostazioni", "Modello", "Parametri". Potrebbe comunque essere più significativo per il contesto: ad esempio se Puffo fosse una sorta di modulo di analisi numerica che avresti scritto, forse "Parametri" sarebbe meglio per la sua configurazione. Usa il particolare vocabolario associato al contesto di un modulo a tuo vantaggio per trovare nomi univoci che mantengano l'unicità anche se miscelati in altri spazi dei nomi. Penso che questa potrebbe essere una specie di risposta alla domanda 2 dell'OP.

4) Codice refactor in modo da non dover mescolare l'uso della configurazione da due luoghi diversi. I dettagli dipendono da te.

5) Combina le due configurazioni in una prima di passarle nella tua classe. Utilizzare una classe conf combinata per rappresentare:

struct Conf {
    SmurfConfiguration smurf;
    WartmongerConfiguation wart;
}

I nomi delle variabili dei membri brevi ora ottengono la stessa cosa dell'alias dello spazio dei nomi / classe.


0

Sembra strano che l'aggiunta di un punto al nome ti dia fastidio.

Wartmonger.Configuration configuration = Wartmonger.Configuration .new();

// vs

WartmongerConfiguration configuration = WartmongerConfiguration.new();

Se entrambi Smurfe le Wartmongerconfigurazioni vengono utilizzate insieme in un unico posto, ma separatamente vengono utilizzate in più punti, lo spazio dei nomi è sicuramente un buon approccio.

Avendo namespace darà possibilità di utilizzare i nomi "puliti" in codice interno, dove con prefissi si finisce per utilizzare SmurfConfigurationall'interno di SmurfService's codice interno, che può diventare fastidioso ogni volta che si aprirà quel codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.