Analogia Candy Cup
Versione 1: una tazza per ogni caramella
Diciamo che hai scritto un codice come questo:
Mod1.ts
export namespace A {
export class Twix { ... }
}
Mod2.ts
export namespace A {
export class PeanutButterCup { ... }
}
Mod3.ts
export namespace A {
export class KitKat { ... }
}
Hai creato questa configurazione:
A ciascun modulo (foglio di carta) viene assegnato un proprio nome A
. Questo è inutile: non stai organizzando le tue caramelle qui, stai solo aggiungendo un ulteriore passaggio (togliendolo dalla tazza) tra te e le prelibatezze.
Versione 2: una tazza nell'ambito globale
Se non stavi utilizzando i moduli, potresti scrivere codice in questo modo (nota la mancanza di export
dichiarazioni):
global1.ts
namespace A {
export class Twix { ... }
}
global2.ts
namespace A {
export class PeanutButterCup { ... }
}
global3.ts
namespace A {
export class KitKat { ... }
}
Questo codice crea uno spazio dei nomi unito A
nell'ambito globale:
Questa configurazione è utile, ma non si applica nel caso dei moduli (poiché i moduli non inquinano l'ambito globale).
Versione 3: andare senza coppa
Tornando all'esempio originale, le tazze A
, A
e A
non stanno facendo qualsiasi favori. Invece, potresti scrivere il codice come:
Mod1.ts
export class Twix { ... }
Mod2.ts
export class PeanutButterCup { ... }
Mod3.ts
export class KitKat { ... }
per creare un'immagine simile a questa:
Molto meglio!
Ora, se stai ancora pensando a quanto vuoi veramente usare lo spazio dei nomi con i tuoi moduli, continua a leggere ...
Questi non sono i concetti che stai cercando
Dobbiamo tornare alle origini del perché gli spazi dei nomi esistono in primo luogo ed esaminare se tali ragioni hanno senso per i moduli esterni.
Organizzazione : gli spazi dei nomi sono utili per raggruppare oggetti e tipi logicamente correlati. Ad esempio, in C #, troverai tutti i tipi di raccolta inSystem.Collections
. Organizzando i nostri tipi in spazi dei nomi gerarchici, forniamo una buona esperienza di "scoperta" per gli utenti di quei tipi.
Conflitti di nomi: gli spazi dei nomi sono importanti per evitare la collisione dei nomi. Ad esempio, potresti avere My.Application.Customer.AddForm
e My.Application.Order.AddForm
- due tipi con lo stesso nome, ma uno spazio dei nomi diverso. In una lingua in cui tutti gli identificatori esistono nello stesso ambito radice e tutti gli assembly caricano tutti i tipi, è fondamentale che tutto sia nello spazio dei nomi.
Queste ragioni hanno senso nei moduli esterni?
Organizzazione : i moduli esterni sono già presenti in un file system, necessariamente. Dobbiamo risolverli per percorso e nome file, quindi c'è uno schema logico di organizzazione che possiamo usare. Possiamo avere una /collections/generic/
cartella con alist
modulo al suo interno.
Conflitti di nomi : questo non si applica affatto ai moduli esterni. All'interno di un modulo, non esiste alcun motivo plausibile per avere due oggetti con lo stesso nome. Dal punto di vista del consumo, il consumatore di un determinato modulo può scegliere il nome che utilizzerà per fare riferimento al modulo, quindi i conflitti di denominazione accidentale sono impossibili.
Anche se non credete che tali ragioni siano adeguatamente affrontate dal modo in cui funzionano i moduli, la "soluzione" di provare a usare spazi dei nomi in moduli esterni non funziona nemmeno.
Scatole in scatole in scatole
Una storia:
Il tuo amico Bob ti chiama. "Ho un grande nuovo schema organizzativo nella mia casa", dice, "vieni a dare un'occhiata!". Bene, andiamo a vedere cosa ha inventato Bob.
Inizi in cucina e apri la dispensa. Ci sono 60 scatole diverse, ciascuna etichettata "Pantry". Scegli una scatola a caso e la apri. All'interno c'è una singola scatola con l'etichetta "Grani". Apri la casella "Grani" e trova una singola casella con l'etichetta "Pasta". Apri la casella "Pasta" e trova una casella singola denominata "Penne". Apri questa scatola e trova, come ti aspetti, un sacchetto di penne.
Leggermente confuso, raccogli una scatola adiacente, anche etichettata "Dispensa". All'interno c'è una singola scatola, di nuovo etichettata "Grani". Apri la casella "Grani" e, di nuovo, trovi una singola scatola con l'etichetta "Pasta". Apri la scatola "Pasta" e trovi una scatola singola, questa è etichettata "Rigatoni". Apri questa scatola e trova ... un sacchetto di rigatoni.
"È ottimo!" dice Bob. "Tutto è in uno spazio dei nomi!".
"Ma Bob ..." rispondi. "Il tuo schema organizzativo è inutile. Devi aprire un mucchio di scatole per arrivare a qualsiasi cosa, e in realtà non è più conveniente trovare qualcosa che se avessi semplicemente messo tutto in una scatola anziché tre . In effetti, dal momento che il tuo la dispensa è già ordinata scaffale per scaffale, non hai bisogno delle scatole. Perché non mettere la pasta sullo scaffale e raccoglierla quando ne hai bisogno? "
"Non capisci - Devo assicurarmi che nessun altro metta qualcosa che non appartiene allo spazio dei nomi" Pantry ". E ho organizzato in modo sicuro tutta la mia pasta nello Pantry.Grains.Pasta
spazio dei nomi in modo da poterlo facilmente trovare"
Bob è un uomo molto confuso.
I moduli sono la loro scatola
Probabilmente hai avuto qualcosa di simile accadere nella vita reale: ordini alcune cose su Amazon e ogni articolo viene mostrato nella sua scatola, con una scatola più piccola all'interno, con l'articolo avvolto nella sua confezione. Anche se le scatole interne sono simili, le spedizioni non vengono "combinate" utilmente.
Seguendo l'analogia della scatola, l'osservazione chiave è che i moduli esterni sono la loro scatola . Potrebbe essere un articolo molto complesso con molte funzionalità, ma ogni dato modulo esterno è la sua scatola.
Guida per moduli esterni
Ora che abbiamo capito che non abbiamo bisogno di usare "spazi dei nomi", come dovremmo organizzare i nostri moduli? Seguono alcuni principi guida ed esempi.
Esporta il più vicino possibile al livello più alto
- Se esporti solo una singola classe o funzione, usa
export default
:
MyClass.ts
export default class SomeType {
constructor() { ... }
}
MyFunc.ts
function getThing() { return 'thing'; }
export default getThing;
Consumo
import t from './MyClass';
import f from './MyFunc';
var x = new t();
console.log(f());
Questo è ottimale per i consumatori. Possono nominare il tuo tipo come preferiscono ( t
in questo caso) e non devono fare punti estranei per trovare i tuoi oggetti.
- Se esporti più oggetti, mettili tutti ai massimi livelli:
MyThings.ts
export class SomeType { ... }
export function someFunc() { ... }
Consumo
import * as m from './MyThings';
var x = new m.SomeType();
var y = m.someFunc();
- Se stai esportando un gran numero di cose, solo allora dovresti usare la parola chiave
module
/ namespace
:
MyLargeModule.ts
export namespace Animals {
export class Dog { ... }
export class Cat { ... }
}
export namespace Plants {
export class Tree { ... }
}
Consumo
import { Animals, Plants} from './MyLargeModule';
var x = new Animals.Dog();
Bandiere rosse
Tutte le seguenti sono bandiere rosse per la strutturazione del modulo. Controlla di nuovo che non stai provando a namespace dei tuoi moduli esterni se qualcuno di questi si applica ai tuoi file:
- Un file la cui unica dichiarazione di livello superiore è
export module Foo { ... }
(rimuovere Foo
e spostare tutto 'su' un livello)
- Un file che ha un singolo
export class
o export function
che non lo èexport default
- Più file che hanno lo stesso
export module Foo {
livello di primo livello (non pensare che questi si uniranno in uno Foo
!)