Compartilhar via


Diretrizes para escrever modelos de texto T4

Conheça as diretrizes gerais que podem ser úteis se você estiver gerando código do programa ou outros recursos de aplicativo no Visual Studio. Não são regras fixas.

Diretrizes para modelos T4 em tempo de design

Modelos T4 em tempo de design são modelos que geram código em seu projeto do Visual Studio em tempo de design. Para saber mais, confira Geração de código em tempo de design usando modelos de texto T4.

Gerar aspectos variáveis do aplicativo.

A geração de código é mais útil para os aspectos do aplicativo que podem ser alterados durante o projeto ou serão alterados entre diferentes versões do aplicativo. Separe esses aspectos variáveis dos aspectos mais invariáveis para que você possa determinar com mais facilidade o que precisa ser gerado. Por exemplo, se o seu aplicativo fornecer um site, separe as funções padrão de atendimento de página da lógica que define os caminhos de navegação de uma página para outra.

Codificar os aspectos variáveis em um ou mais modelos de origem.

Um modelo é um arquivo ou banco de dados que cada modelo lê para obter valores específicos de partes variáveis do código que deve ser gerado. Os modelos podem ser bancos de dados, arquivos XML de seu próprio design, diagramas ou linguagens específicas de domínio. Normalmente, um modelo é usado para gerar muitos arquivos em um projeto do Visual Studio. Cada arquivo é gerado a partir de um modelo separado.

Você pode usar mais de um modelo em um projeto. Por exemplo, você pode definir um modelo para navegação entre páginas da Web e um modelo separado para o layout das páginas.

Concentre o modelo nas necessidades e no vocabulário dos usuários, não na sua implementação.

Por exemplo, em um aplicativo de site, você esperaria que o modelo se referisse a páginas da Web e hiperlinks.

O ideal é escolher uma forma de apresentação que se adapte ao tipo de informação que o modelo representa. Por exemplo, um modelo de caminhos de navegação por meio de um site pode ser um diagrama de caixas e setas.

Teste o código gerado.

Use testes manuais ou automatizados para verificar se o código resultante funciona conforme os usuários exigem. Evite gerar testes do mesmo modelo do qual o código é gerado.

Em alguns casos, é possível executar testes gerais diretamente no modelo. Por exemplo, você pode escrever um teste que garante que todas as páginas do site possam ser acessadas pela navegação de qualquer outra página.

Permitir código personalizado: gerar classes parciais.

Permita o código que você escreve manualmente, além do código gerado. É incomum que um esquema de geração de código possa levar em conta todas as possíveis variações que possam surgir. Portanto, há a possibilidade de adicionar ou substituir parte do código gerado. Quando o material gerado está em uma linguagem .NET, como C# ou Visual Basic, duas estratégias são especialmente úteis:

  • As classes geradas devem ser parciais. Isso permite que você adicione conteúdo ao código gerado.

  • As classes devem ser geradas em pares, uma herdando da outra. A classe base deve conter todos os métodos e propriedades gerados, e a classe derivada deve conter apenas os construtores. Isso permite que o código escrito à mão substitua qualquer um dos métodos gerados.

Em outras linguagens geradas, como XML, use a diretiva <#@include#> para criar combinações simples de conteúdo gerado e escrito à mão. Em casos mais complexos, talvez seja necessário escrever uma etapa pós-processamento que combine o arquivo gerado com arquivos escritos à mão.

Mova o material comum em arquivos de inclusão ou modelos de tempo de execução.

Para evitar a repetição de blocos semelhantes de texto e de código em vários modelos, use a diretiva <#@ include #>. Para saber mais, confira Diretiva de inclusão T4.

Você também pode compilar modelos de texto em tempo de execução em um projeto separado e chamá-los do modelo em tempo de design. Para fazer isso, use a diretiva <#@ assembly #> para acessar o projeto separado.

Considere mover grandes blocos de código para um assembly separado.

Se você tiver blocos de código grandes e blocos de recursos de classe, pode ser útil mover parte desse código para métodos compilados em um projeto separado. Você pode usar a diretiva <#@ assembly #> para acessar o código no modelo. Para saber mais, confira Diretiva de assembly T4.

Você pode colocar os métodos em uma classe abstrata que o modelo pode herdar. A classe abstrata deve herdar de Microsoft.VisualStudio.TextTemplating.TextTransformation. Para saber mais, confira Diretiva de modelo T4.

Gerar código, não arquivos de configuração.

Um método de escrita de um aplicativo variável é escrever um código de programa genérico que aceite um arquivo de configuração. Um aplicativo escrito dessa maneira é muito flexível e pode ser reconfigurado quando os requisitos de negócios mudarem, sem recompilar o aplicativo. No entanto, uma desvantagem dessa abordagem é que o aplicativo terá um desempenho menor do que um aplicativo mais específico. Além disso, seu código de programa será mais difícil de ler e manter, em parte porque ele sempre tem que lidar com os tipos mais genéricos.

Por outro lado, um aplicativo cujas partes variáveis são geradas antes da compilação pode ser fortemente tipado. Isso torna muito mais fácil e confiável escrever o código à mão e integrá-lo às partes geradas do software.

Para obter o benefício total da geração de código, tente gerar código do programa em vez de arquivos de configuração.

Use uma pasta Código Gerado.

Coloque os modelos e os arquivos gerados em uma pasta de projeto chamada Código Gerado, para deixar claro que eles não são arquivos que devem ser editados diretamente. Se você criar um código personalizado para substituir ou adicionar às classes geradas, coloque essas classes em uma pasta chamada Código Personalizado. A estrutura de um projeto típico tem esta aparência:

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

Diretrizes para modelos T4 de tempo de execução (pré-processados)

Mova o material comum para os modelos herdados.

Você pode usar a herança para compartilhar métodos e blocos de texto entre modelos de texto T4. Para saber mais, confira Diretiva de modelo T4.

Você também pode usar arquivos de inclusão que têm modelos em tempo de execução.

Mova corpos grandes de código em uma classe parcial.

Cada modelo de tempo de execução gera uma definição de classe parcial que tem o mesmo nome que o modelo. Você pode escrever um arquivo de código que contém outra definição parcial da mesma classe. Você pode adicionar métodos, campos e construtores à classe dessa maneira. Esses membros podem ser chamados dos blocos de código no modelo.

Uma vantagem de fazer isso é que o código é mais fácil de gravar, pois o IntelliSense está disponível. Além disso, você pode obter uma separação melhor entre a apresentação e a lógica subjacente.

Por exemplo, em MyReportText.tt:

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

Em MyReportText-Methods.cs:

private string ComputeTotal() { ... }

Permitir código personalizado: forneça pontos de extensão.

Considere a geração de métodos virtuais em <#+ blocos de recursos de classe #>. Isso permite que um único modelo seja usado em muitos contextos sem modificação. Em vez de modificar o modelo, você pode construir uma classe derivada que fornece a lógica adicional mínima. A classe derivada pode ser um código regular ou pode ser um modelo em tempo de execução.

Por exemplo, em MyStandardRunTimeTemplate.tt:

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

No código de um aplicativo:

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

Diretrizes para todos os modelos T4

Separar a coleta de dados da geração de texto.

Tente evitar misturar blocos de computação e de texto. Em cada modelo de texto, use o primeiro <#bloco de código #> para definir variáveis e executar cálculos complexos. Do primeiro bloco de texto até o final do modelo ou do primeiro <#+ bloco de recursos de classe #> evite expressões longas e evite loops e condicionais, a menos que contenham blocos de texto. Essa prática facilita a leitura e a manutenção do modelo.

Não use .tt para incluir arquivos.

Use uma extensão de nome de arquivo diferente, como .ttinclude para incluir arquivos. Use .tt apenas para arquivos que você deseja que sejam processados como modelos de texto em tempo de execução ou em tempo de design. Em alguns casos, o Visual Studio reconhece arquivos .tt e define automaticamente suas propriedades para processamento.

Inicie cada modelo como um protótipo fixo.

Escreva um exemplo do código ou texto que você deseja gerar e verifique se ele está correto. Em seguida, altere sua extensão para .tt e insira incrementalmente o código que modifica o conteúdo por meio da leitura do modelo.

Considere o uso de modelos tipados.

Embora você possa criar um esquema XML ou de banco de dados para seus modelos, pode ser útil criar uma linguagem específica de domínio (DSL). Uma DSL tem a vantagem de gerar uma classe para representar cada nó no esquema e propriedades para representar os atributos. Isso significa que você pode programar em termos do modelo de negócios. Por exemplo:

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

Considere o uso de diagramas para seus modelos.

Muitos modelos são apresentados com mais eficiência e gerenciados simplesmente como tabelas de texto, especialmente se forem muito grandes.

No entanto, para alguns tipos de requisitos de negócios, é importante esclarecer conjuntos complexos de relações e fluxos de trabalho, e os diagramas são o meio mais adequado. Uma vantagem de um diagrama é que é fácil discutir com usuários e outros stakeholders. Ao gerar código de um modelo no nível dos requisitos de negócios, você torna seu código mais flexível quando os requisitos são alterados.

Você também pode criar seu próprio tipo de diagrama como uma DSL (linguagem específica de domínio). O código pode ser gerado de UML e DSLs. Para saber mais, confira Analisando e modelando arquitetura.