Candy Cup Analogy
Version 1: une tasse pour chaque bonbon
Disons que vous avez écrit du code comme celui-ci:
Mod1.ts
export namespace A {
export class Twix { ... }
}
Mod2.ts
export namespace A {
export class PeanutButterCup { ... }
}
Mod3.ts
export namespace A {
export class KitKat { ... }
}
Vous avez créé cette configuration:
Chaque module (feuille de papier) a son propre gobelet nommé A
. Cela ne sert à rien - vous n'organisez pas réellement vos bonbons ici, vous ajoutez simplement une étape supplémentaire (en le sortant de la tasse) entre vous et les friandises.
Version 2: une tasse à l'échelle mondiale
Si vous n'utilisiez pas de modules, vous pourriez écrire du code comme celui-ci (notez le manque de export
déclarations):
global1.ts
namespace A {
export class Twix { ... }
}
global2.ts
namespace A {
export class PeanutButterCup { ... }
}
global3.ts
namespace A {
export class KitKat { ... }
}
Ce code crée un espace A
de noms fusionné dans la portée globale:
Cette configuration est utile, mais ne s'applique pas dans le cas des modules (car les modules ne polluent pas la portée globale).
Version 3: aller sans coupe
Pour en revenir à l'exemple d' origine, les tasses A
, A
et A
ne sont pas vous faire des faveurs. Au lieu de cela, vous pouvez écrire le code comme suit:
Mod1.ts
export class Twix { ... }
Mod2.ts
export class PeanutButterCup { ... }
Mod3.ts
export class KitKat { ... }
pour créer une image qui ressemble à ceci:
Bien mieux!
Maintenant, si vous pensez toujours à combien vous voulez vraiment utiliser l'espace de noms avec vos modules, lisez la suite ...
Ce ne sont pas les concepts que vous recherchez
Nous devons revenir aux origines de la raison pour laquelle les espaces de noms existent en premier lieu et examiner si ces raisons ont un sens pour les modules externes.
Organisation : les espaces de noms sont pratiques pour regrouper des objets et des types liés de manière logique. Par exemple, en C #, vous allez trouver tous les types de collection dans System.Collections
. En organisant nos types en espaces de noms hiérarchiques, nous offrons une bonne expérience de «découverte» aux utilisateurs de ces types.
Conflits de noms: les espaces de noms sont importants pour éviter les collisions de noms. Par exemple, vous pouvez avoir My.Application.Customer.AddForm
et My.Application.Order.AddForm
- deux types avec le même nom, mais un espace de noms différent. Dans un langage où tous les identificateurs existent dans la même portée racine et tous les assemblys chargent tous les types, il est essentiel que tout soit dans un espace de noms.
Ces raisons ont-elles un sens dans les modules externes?
Organisation : les modules externes sont déjà présents dans un système de fichiers, nécessairement. Nous devons les résoudre par chemin et nom de fichier, il y a donc un schéma d'organisation logique à utiliser. Nous pouvons avoir un /collections/generic/
dossier contenant un list
module.
Conflits de noms : cela ne s'applique pas du tout dans les modules externes. Dans un module, il n'y a aucune raison plausible d'avoir deux objets avec le même nom. Du côté de la consommation, le consommateur d'un module donné peut choisir le nom qu'il utilisera pour se référer au module, de sorte que les conflits de nommage accidentels sont impossibles.
Même si vous ne pensez pas que ces raisons sont correctement traitées par le fonctionnement des modules, la «solution» consistant à essayer d'utiliser des espaces de noms dans des modules externes ne fonctionne même pas.
Boîtes en Boîtes en Boîtes
Une histoire:
Votre ami Bob vous appelle. "J'ai un nouveau plan d'organisation formidable dans ma maison", dit-il, "venez le vérifier!". Bien, allons voir ce que Bob a imaginé.
Vous commencez dans la cuisine et ouvrez le garde-manger. Il y a 60 boîtes différentes, chacune intitulée "Garde-manger". Vous choisissez une boîte au hasard et l'ouvrez. A l'intérieur se trouve une seule boîte intitulée "Grains". Vous ouvrez la boîte "Grains" et trouvez une seule boîte intitulée "Pâtes". Vous ouvrez la boîte "Pâtes" et trouvez une seule boîte intitulée "Penne". Vous ouvrez cette boîte et trouvez, comme vous vous en doutez, un sachet de pâtes penne.
Légèrement confus, vous prenez une boîte adjacente, également étiquetée "Garde-manger". A l'intérieur se trouve une seule boîte, à nouveau étiquetée "Grains". Vous ouvrez la boîte "Grains" et, encore une fois, vous trouvez une seule boîte intitulée "Pâtes". Vous ouvrez la boîte "Pasta" et trouvez une seule boîte, celle-ci est étiquetée "Rigatoni". Vous ouvrez cette boîte et trouvez ... un sac de pâtes rigatoni.
"C'est bien!" dit Bob. "Tout est dans un espace de noms!".
"Mais Bob ..." répondez-vous. "Votre schéma d'organisation est inutile. Vous devez ouvrir un tas de boîtes pour accéder à quoi que ce soit, et il n'est pas plus pratique de trouver quoi que ce soit que si vous veniez de tout mettre dans une seule boîte au lieu de trois . En fait, depuis votre le garde-manger est déjà trié étagère par étagère, vous n'avez pas du tout besoin des boîtes. Pourquoi ne pas simplement mettre les pâtes sur l'étagère et les ramasser quand vous en avez besoin? "
"Vous ne comprenez pas - je dois m'assurer que personne d'autre ne place quelque chose qui n'appartient pas à l'espace de noms" Pantry ". Et j'ai organisé toutes mes pâtes en toute sécurité dans l' Pantry.Grains.Pasta
espace de noms afin que je puisse facilement le trouver"
Bob est un homme très confus.
Les modules sont leur propre boîte
Vous avez probablement eu quelque chose de similaire dans la vie réelle: vous commandez quelques choses sur Amazon, et chaque article apparaît dans sa propre boîte, avec une petite boîte à l'intérieur, avec votre article emballé dans son propre emballage. Même si les boîtes intérieures sont similaires, les envois ne sont pas utilement «combinés».
Pour l'analogie avec la boîte, l'observation clé est que les modules externes sont leur propre boîte . Ce pourrait être un élément très complexe avec beaucoup de fonctionnalités, mais tout module externe donné est sa propre boîte.
Guide pour les modules externes
Maintenant que nous avons compris que nous n'avons pas besoin d'utiliser des «espaces de noms», comment devrions-nous organiser nos modules? Voici quelques principes directeurs et exemples.
Exportez le plus près possible du niveau supérieur
- Si vous n'exportez qu'une seule classe ou fonction, utilisez
export default
:
MyClass.ts
export default class SomeType {
constructor() { ... }
}
MyFunc.ts
function getThing() { return 'thing'; }
export default getThing;
Consommation
import t from './MyClass';
import f from './MyFunc';
var x = new t();
console.log(f());
Ceci est optimal pour les consommateurs. Ils peuvent nommer votre type comme ils le souhaitent ( t
dans ce cas) et n'ont pas à faire de pointage étranger pour trouver vos objets.
- Si vous exportez plusieurs objets, placez-les tous au niveau supérieur:
MyThings.ts
export class SomeType { ... }
export function someFunc() { ... }
Consommation
import * as m from './MyThings';
var x = new m.SomeType();
var y = m.someFunc();
- Si vous exportez un grand nombre de choses, alors seulement devez-vous utiliser le mot
module
- namespace
clé / :
MyLargeModule.ts
export namespace Animals {
export class Dog { ... }
export class Cat { ... }
}
export namespace Plants {
export class Tree { ... }
}
Consommation
import { Animals, Plants} from './MyLargeModule';
var x = new Animals.Dog();
Drapeaux rouges
Tous les éléments suivants sont des drapeaux rouges pour la structuration des modules. Vérifiez que vous n'essayez pas de nommer vos modules externes si l'un de ces éléments s'applique à vos fichiers:
- Un fichier dont la seule déclaration de niveau supérieur est
export module Foo { ... }
(supprimer Foo
et déplacer tout «vers le haut» d'un niveau)
- Un fichier qui a un seul
export class
ou export function
qui n'est pasexport default
- Plusieurs fichiers qui ont le même
export module Foo {
niveau supérieur (ne pensez pas qu'ils vont se combiner en un seul Foo
!)