Le chapitre A36/F29 contient des directives pour la conception de packages. Notez que la notion de package n’existe pas en TypeScript (et en JavaScript), mais le principe de namespace (espace de nom) existe. La Section 18.1 explique quelques pratiques pour la gestion des namespaces en TypeScript.
Les points importants sont les suivants (les détails se trouvent dans le livre) :
- La notation UML des diagrammes de packages ;
- Organiser les packages par cohésion ;
- Organiser les packages en une famille d’interface (convention Java) ;
- Créer un package par tâche et par groupe de classes instables (Branches) ;
- Les packages les plus responsables sont les plus stables ;
- Factoriser (placer dans un package à part) les types indépendants ;
- Utiliser fabrique (factory) pour limiter la dépendance aux packages concrets ;
- Comment rompre les cycles dans les packages.
La figure 18.1 est un exemple d’un diagramme de packages.
18.1 Absence de packages dans TypeScript
En effet, TypeScript n’a pas la notion de package comme dans C# ou Java. Cependant, il y a des pratiques pour organiser logiquement le code et pour éviter les conflits (les collisions) de noms. Rappelons que la notion de package existe dans Java pour :
- Organiser logiquement le code : le type interface
java.util.List
est disponible dans la bibliothèquejava.util
) ; - Éviter les conflits de noms : les classes
java.util.List
etca.etsmtl.log121.fuhrman.projet2.List
ont le même nom de base, mais puisqu’elles sont dans deux packages différents, elles peuvent être utilisées dans le même programme (leur « fully qualified name » est différent).
En TypeScript, on peut atteindre les mêmes objectifs.
18.1.1 Organisation des éléments du code
L’organisation peut être réalisée grâce aux modules avec les mots-clés export
et import
. Par exemple :
// maClasse.ts
export class MaClasse {
// définition
}
// client.ts
import { MaClasse } from './maClasse'
On organise les fichiers, par exemple maClasse.ts
, dans les répertoires.
18.1.2 Noms sans conflit
Dans l’exemple précédent, il ne serait pas possible d’avoir deux fichiers nommés maClasse.ts
dans le même répertoire, alors il est impossible d’avoir une collision avec le nom du fichier. Donc, on pourrait importer la classe MaClasse
de maClasse.ts
et la classe MaClasse
de lib/projet2/maClasse.ts
dans le même programme. Cependant, pour éviter un conflit de noms, on emploie le mot-clé as
pour renommer la classe (MaClasseP2
) lorsqu’on l’importe :
// client.ts
import { MaClasse } from './maClasse'
import { MaClasse as MaClasseP2 } from './lib/projet2/maClasse'
18.1.3 Namespaces
TypeScript offre une autre manière pour organiser et éviter les conflits de noms avec les namespaces (anciennement les modules internes). L’exemple de Validators est intéressant puisqu’il s’agit d’un namespace commun réparti dans plusieurs fichiers. C’est à utiliser surtout lorsqu’on ne veut pas centraliser tout le code dans un seul (gros) fichier (avec export
). Mais, comme vous le voyez dans l’exemple, on doit utiliser les commentaires dans le code de certains fichiers, par exemple
/// <reference path="Validation.ts" />
, et c’est plus compliqué à maintenir.