Instructions relatives à l'écriture de modèles de texte T4

Ces instructions générales peuvent être utiles si vous générez du code de programme ou d’autres ressources d’application dans Visual Studio. Il ne s’agit pas de règles fixes.

Instructions relatives aux modèles de texte T4 au moment de la conception

Les modèles T4 au moment de la conception sont des modèles qui génèrent du code dans le projet Visual Studio au moment de la conception. Pour plus d’informations, consultez Génération de code au moment de la conception à l’aide de modèles de texte T4.

Générez des aspects variables de l’application.

La génération de code est particulièrement utile pour les aspects de l’application susceptibles de changer pendant le projet ou entre différentes versions de l’application. Séparez ces aspects variables des moins changeants afin de pouvoir déterminer plus facilement ce qui doit être généré. Par exemple, si votre application fournit un site web, distinguez les fonctions standard de mise à disposition des pages de la logique qui définit les chemins de navigation d’une page à une autre.

Encodez les aspects variables dans un ou plusieurs modèles sources.

Un modèle est un fichier ou une base de données que chaque modèle de texte lit pour obtenir des valeurs propres aux parties variables du code à générer. Il peut s’agit d’une base de données, d’un fichier XML de votre conception, d’un diagramme ou d’un langage dédié. En règle générale, un modèle est utilisé pour générer de nombreux fichiers dans un projet Visual Studio. Chaque fichier est généré à partir d’un modèle distinct.

Vous pouvez utiliser plusieurs modèles dans un projet. Par exemple, vous pouvez en définir un pour la navigation entre les pages web et un autre pour la disposition des pages.

Concentrez le modèle sur les besoins et le vocabulaire des utilisateurs, et non sur votre implémentation.

Par exemple, dans une application de site web, le modèle doit faire référence à des pages web et à des liens hypertextes.

Dans l’idéal, choisissez une forme de présentation adaptée au type d’informations représenté par le modèle. Par exemple, un modèle de chemins de navigation à travers un site web peut revêtir l’aspect d’un diagramme de zones et de flèches.

Testez le code généré.

Utilisez des tests manuels ou automatisés pour vérifier que le code obtenu fonctionne comme l’exigent les utilisateurs. Évitez de générer les tests à partir du même modèle que le code.

Dans certains cas, des tests généraux peuvent être effectués directement sur le modèle. Par exemple, vous pouvez écrire un test qui garantit que chaque page du site web est atteignable par navigation à partir d’une autre page.

Autorisez le code personnalisé : générez des classes partielles.

Autorisez le code écrit manuellement en plus du code généré. Il est rare qu’un schéma de génération de code puisse prendre en compte toutes les variantes possibles susceptibles de survenir. Prévoyez par conséquent de devoir ajouter ou remplacer une partie du code généré. Lorsque le contenu généré est formulé dans un langage .NET comme C# ou Visual Basic, deux stratégies sont particulièrement utiles :

  • Les classes générées doivent être partielles. Cela vous permet d’ajouter du contenu au code généré.

  • Les classes doivent être générées par paires, l’une héritant de l’autre. La classe de base contient toutes les méthodes et propriétés générées, et la classe dérivée uniquement les constructeurs. Cela permet à votre code écrit à la main de remplacer les méthodes générées.

Dans d’autres langages générés (par exemple XML), utilisez la directive <#@include#> pour créer des combinaisons simples de contenu écrit à la main et de contenu généré. Il se peut, dans les cas plus complexes, que vous deviez ajouter une étape de post-traitement qui combine le fichier généré avec les fichiers écrits à la main.

Déplacez les documents communs dans des fichiers include ou des modèles au moment de l’exécution.

Pour éviter de répéter des blocs de texte et de code similaires dans plusieurs modèles, utilisez la directive <#@ include #>. Pour plus d’informations, consultez Directive d’inclusion T4.

Vous pouvez également générer des modèles de texte au moment de l’exécution dans un projet distinct, puis les appeler à partir du modèle au moment de la conception. Utilisez alors la directive <#@ assembly #> pour accéder au projet distinct.

Déplacez éventuellement les grands blocs de code dans un assembly distinct.

Si vous avez des blocs de code volumineux et des blocs de fonctionnalités de classe, il peut être utile de déplacer une partie de ce code dans des méthodes compilées au sein d’un projet distinct. Vous pouvez utiliser la directive <#@ assembly #> pour accéder au code dans le modèle. Pour plus d’informations, consultez Directive d’assembly T4.

Vous pouvez placer les méthodes dans une classe abstraite dont le modèle hérite. La classe abstraite doit hériter de Microsoft.VisualStudio.TextTemplating.TextTransformation. Pour plus d’informations, consultez Directives de modèle T4.

Générez du code, et non des fichiers de configuration.

Une méthode pour créer une application variable consiste à écrire du code de programme générique qui accepte un fichier de configuration. Une application conçue de cette manière se révèle très flexible et peut être reconfigurée sans être regénérée lorsque les besoins de l’entreprise changent. L’inconvénient de cette approche reste toutefois que l’application fonctionne moins bien qu’une application plus spécifique. En outre, son code de programme sera plus difficile à lire et à gérer, en partie parce qu’il doit toujours traiter les types les plus génériques.

À l’inverse, une application dont les parties variables sont générées avant la compilation peut être fortement typée. Il est ainsi beaucoup plus facile et plus fiable d’écrire du code à la main et de l’intégrer aux parties générées du logiciel.

Pour tirer pleinement parti de la génération de code, essayez de générer du code de programme au lieu de fichiers de configuration.

Utilisez un dossier Code généré.

Placez les modèles et les fichiers générés dans un dossier de projet nommé Code généré pour indiquer clairement qu’il ne s’agit pas de fichiers qui doivent être modifiés directement. Si vous créez du code personnalisé pour remplacer ou compléter les classes générées, placez ces classes dans un dossier nommé Code personnalisé. La structure d’un projet classique se présente ainsi :

MyProject
   Custom Code
      Class1.cs
      Class2.cs
   Generated Code
      Class1.tt
          Class1.cs
      Class2.tt
          Class2.cs
   AnotherClass.cs

Instructions relatives aux modèles T4 au moment de l’exécution (prétraités)

Déplacez le contenu commun dans des modèles hérités.

Vous pouvez utiliser l’héritage pour partager des méthodes et des blocs de texte entre des modèles de texte T4. Pour plus d’informations, consultez Directives de modèle T4.

Vous pouvez également utiliser des fichiers include comportant des modèles au moment de l’exécution.

Déplacez les corps de code volumineux dans une classe partielle.

Chaque modèle au moment de l’exécution génère une définition de classe partielle portant le même nom que le modèle. Vous pouvez écrire un fichier de code qui contient une autre définition partielle de la même classe. Ajoutez des méthodes, des champs et des constructeurs à la classe de cette manière. Ces membres peuvent être appelés à partir des blocs de code du modèle.

L’avantage de cette méthode est que le code se révèle plus facile à écrire, car IntelliSense est disponible. En outre, vous pouvez obtenir une meilleure séparation entre la présentation et la logique sous-jacente.

Par exemple, voici MyReportText.tt :

The total is: <#= ComputeTotal() #>

Voici maintenant MyReportText-Methods.cs :

private string ComputeTotal() { ... }

Autorisez le code personnalisé : fournissez des points d’extension.

Générez éventuellement des méthodes virtuelles dans les <#+ blocs de fonctionnalités de classe #>. Cela permet d’utiliser un même modèle dans de nombreux contextes sans modification. Au lieu de modifier le modèle, vous pouvez construire une classe dérivée qui fournit la logique supplémentaire minimale. La classe dérivée peut se présenter sous la forme de code standard ou d’un modèle au moment de l’exécution.

Par exemple, voici MyStandardRunTimeTemplate.tt :

This page is copyright <#= CompanyName() #>.
<#+ protected virtual string CompanyName() { return ""; } #>

Voici maintenant le code d’une application :

class FabrikamTemplate : MyStandardRunTimeTemplate
{
  protected override string CompanyName() { return "Fabrikam"; }
}
...
  string PageToDisplay = new FabrikamTemplate().TextTransform();

Instructions relatives à tous les modèles T4

Séparez la collecte de données de la génération de texte.

Dans la mesure du possible, ne mélangez pas les blocs de calcul et de texte. Dans chaque modèle de texte, utilisez le premier <# bloc de code #> pour définir des variables et effectuer des calculs complexes. Du premier bloc de texte à la fin du modèle ou du premier <#+ bloc de fonctionnalités de classe #>, évitez les expressions longues ainsi que les boucles et conditions, à moins qu’elles ne contiennent des blocs de texte. Cette pratique facilite la lecture et la maintenance du modèle.

N’utilisez pas .tt pour les fichiers include.

Utilisez une autre extension de nom de fichier (par exemple .ttinclude) pour les fichiers include. Réservez .tt aux fichiers que vous souhaitez traiter en tant que modèles de texte au moment de l’exécution ou de la conception. Dans certains cas, Visual Studio reconnaît les fichiers .tt et définit automatiquement leurs propriétés à traiter.

Lancez chaque modèle comme prototype fixe.

Écrivez un exemple de code ou de texte que vous souhaitez générer et assurez-vous qu’il est correct. Modifiez ensuite son extension en .tt et insérez de façon incrémentielle du code qui modifie le contenu en lisant le modèle.

Utilisez éventuellement des modèles typés.

Bien que vous ayez la possibilité de créer un schéma XML ou de base de données pour les modèles, il peut se révéler utile de produire un langage dédié. Un langage dédié présente l’avantage de générer une classe pour représenter chaque nœud du schéma, et des propriétés pour représenter les attributs. Vous pouvez ainsi programmer au niveau du modèle d’entreprise. Par exemple :

Team Members:
<# foreach (Person p in team.Members)
 { #>
    <#= p.Name #>
<# } #>

Utilisez éventuellement des diagrammes pour vos modèles.

De nombreux modèles sont mieux présentés et gérés sous forme de simples tables de texte, en particulier s’ils sont très volumineux.

Pour certains types d’exigences métier toutefois, il est important de clarifier les ensembles complexes de relations et de flux de travail. Les diagrammes constituent alors le support le mieux adapté. L’avantage d’un diagramme est qu’ils facilitent la discussion avec les utilisateurs et d’autres parties prenantes. En générant du code à partir d’un modèle au niveau des exigences métier, vous rendez votre code plus flexible en fonction de leurs évolutions.

Vous avez également la possibilité de concevoir votre propre type de diagramme comme langage dédié. Le code peut être généré à la fois dans le langage UML et dans des langages dédiés. Pour plus d’informations, consultez Analyse et modélisation de l’architecture.