Поделиться через


Практическое руководство. Создание файлов из модели UML

В модели UML можно создавать программный код, схемы, документы, ресурсы и другие артефакты.Удобно создавать текстовые файлы из модели UML с использованием шаблонов текста.В этом случае можно вставлять программный код в текст, который необходимо создать.

Существует три возможных сценария.

  • Создание файлов из команды меню или жеста.Для этого нужно определить команду Visual Studio, доступную в моделях UML.

  • Создание файлов из приложения.Нужно создать приложение, читающее модели UML и создающее файлы.

  • Создание файлов во время разработки.Модель используется для определения некоторых функциональных возможностей приложения, создания кода. ресурсов и т. д. в решении Visual Studio.

В конце этого раздела рассказывается, как использовать метод создания текста.Дополнительные сведения см. в разделе Создание кода и текстовые шаблоны T4.

Создание файлов из команды меню

В команде меню UML можно использовать предварительно обработанные шаблоны текста.В коде шаблона текста или в отдельном разделяемом классе можно прочитать модель, отображаемую на схеме.

Дополнительные сведения об использовании этих возможностей см. в следующих разделах.

Подход, продемонстрированный в следующем примере, подходит для создания текста из одной модели, когда операция инициируется из одной из схем модели.Чтобы обработать модель в отдельном контексте, рекомендуется использовать Visual Studio Modelbus для получения доступа к модели и ее элементам.

Ee329480.collapse_all(ru-ru,VS.110).gifПример

Для выполнения этого примера создайте проект с расширением Visual Studio (VSIX).В этом примере используется проект с именем VdmGenerator.В файле source.extension.vsixmanifest щелкните Добавить содержимое и задайте в поле типа значение Компонент MEF, исходный путь должен ссылаться на текущий проект.Дополнительные сведения о настройке этого типа проекта см. в разделе Практическое руководство. Определение команды меню на схеме моделирования.

Добавьте в проект файл C#, содержащий следующий код.Этот класс определяет команду меню, которая отобразится на UML-схеме классов.

using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;

namespace VdmGenerator
{
  [Export(typeof(ICommandExtension))]
  [ClassDesignerExtension]
  public class GenerateVdmFromClasses : ICommandExtension
  {
    [Import] public IDiagramContext DiagramContext { get; set; }
    public void Execute(IMenuCommand command)
    {
      // Initialize the template with the Model Store.
      VdmGen generator = new VdmGen(
             DiagramContext.CurrentDiagram.ModelStore);
      // Generate the text and write it.
      System.IO.File.WriteAllText
        (System.IO.Path.Combine(
            Environment.GetFolderPath(
                Environment.SpecialFolder.Desktop),
            "Generated.txt") 
         , generator.TransformText());
    }
    public void QueryStatus(IMenuCommand command)
    {
      command.Enabled = command.Visible = true;
    }
    public string Text
    { get { return "Generate VDM"; } }
  }
}

Следующий файл представляет собой текстовый шаблон.Он создает строку текста для каждого UML-класса в модели, а также для каждого атрибута этих классов.Код для чтения модели вставлен в текст и разделен <# ... #>.

Для создания этого файла щелкните проект в обозревателе решений правой кнопкой мыши и последовательно выберите Добавить и Новый элемент.Выберите Предварительно обработанный текстовый шаблон.В данном примере нужно использовать файл с именем VdmGen.tt.Свойство Пользовательский инструмент файла должно иметь значение TextTemplatingFilePreprocessor.Дополнительные сведения о предварительно обработанных текстовых шаблонах см. в разделе Создание текста во время выполнения с помощью текстовых шаблонов T4.

<#@ import namespace="Microsoft.VisualStudio.Uml.Classes" #>
<# 
   foreach (IClass classElement in store.AllInstances<IClass>())
   {
#>
Type <#= classElement.Name #> ::
<#
     foreach (IProperty attribute in classElement.OwnedAttributes)
     {
#>
       <#= attribute.Name #> : <#= 
           attribute.Type == null ? ""
                                  : attribute.Type.Name #> 
<#
     }
   }
#>

Текстовый шаблон создает разделяемый класс C#, который становится частью проекта Visual Studio.В отдельном файле нужно добавить другое частичное объявление того же класса.Этот код предоставляет шаблон с возможностью доступа в хранилище моделей UML.

using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
namespace VdmGenerator
{
    public partial class VdmGen
    {
        private IModelStore store;
        public VdmGen(IModelStore s)
        { store = s; }
    }
}

Чтобы протестировать проект, нажмите клавишу F5.Будет запущен новый экземпляр Visual Studio.В этой экземпляре откройте или создайте модель UML, содержащую схему классов.Добавьте на схему несколько классов, а в каждый класс — несколько атрибутов.Щелкните правой кнопкой мыши схему и выберите в качестве примера команду Создать VDM.Эта команда создает файл C:\Generated.txt.Проверьте этот файл.Его содержимое должно напоминать следующий текст, но с перечислением пользовательских классов и атрибутов.

Type Class1 ::
          Attribute1 : int 
          Attribute2 : string 
Type Class2 :: 
          Attribute3 : string 

Создание файлов из приложения

Можно создать фалы из приложения для чтения модели UML.Самый гибкий и надежный метод доступа к модели и ее элементам в этих целях — это Visual Studio Modelbus.

Кроме того, для загрузки модели и передачи модели текстовым шаблонам с помощью технологий, описанных в предыдущем подразделе, можно использовать базовый API-интерфейс.Дополнительные сведения о загрузке модели см. в разделе Практическое руководство. Чтение модели UML в программном коде.

Создание файлов во время разработки

Если стандартным методом интерпретации UML в проекте является код, можно создать текстовые шаблоны, позволяющие создавать код из модели UML внутри проекта.Как правило, имеется решение, которое содержит проект модели UML и один или несколько проектов для кода приложения.Каждый проект кода может содержать несколько шаблонов, создающих код программы, ресурсы и файлы конфигурации на основе содержимого модели.Разработчик может запустить все шаблоны, щелкнув Преобразовать все шаблоны на панели инструментов обозревателя решений.Программный код, как правило, создается в форме разделяемых классов, так как это облегчает интеграцию созданных вручную частей.

Проект Visual Studio такого вида можно распространять в форме шаблона, чтобы каждый участник команды мог создавать проекты, генерирующие код из модели аналогичным образом.Как правило, шаблон — это часть пакета расширения, включающая ограничения проверки модели, чтобы гарантировать соблюдение предусловий кода создания.

Ee329480.collapse_all(ru-ru,VS.110).gifОбщая процедура создания файлов

  • Чтобы добавить шаблон в проект, выберите Текстовый шаблон в диалоговом окне "Добавить новый файл".Шаблон можно добавить в проект практически любого типа, за исключением проектов моделирования.

  • Свойство "Пользовательские инструменты" файла шаблона должно иметь значение TextTemplatingFileGenerator, расширение имени файла должно быть .tt.

  • Шаблон должен иметь, по меньшей мере, директиву output.

    <#@ output extension=".cs" #>

    Задайте в поле расширения значение, соответствующее языку проекта.

  • Чтобы разрешить коду создания в шаблоне доступ к модели, создайте для всех сборок, необходимых для прочтения модели UML, директивы <#@ assembly #>.Для открытия модели используйте ModelingProject.LoadReadOnly().Дополнительные сведения см. в разделе Практическое руководство. Чтение модели UML в программном коде.

  • Шаблон выполняется при сохранении и выборе команды Преобразовать все шаблоны на панели инструментов обозревателя решений.

  • Дополнительные сведения об этом типе шаблона см. в разделе Создание кода во время разработки с помощью текстовых шаблонов T4.

  • В стандартном проекте имеется несколько шаблонов, позволяющих создавать из одной модели разные файлы.Первая часть всех шаблонов одинаковая.Во избежание дублирования переместите совпадающие части в отдельных текстовый файл и вызывайте его по мере надобности в каждом шаблоне с использованием директивы <#@include file="common.txt"#>.

  • Кроме того, можно определить специализированный процессор директив, позволяющий предоставлять параметры в процессе создания текста.Дополнительные сведения см. в разделе Настройка преобразования текста T4.

Ee329480.collapse_all(ru-ru,VS.110).gifПример

В этом примере показано создание класса C# для каждого класса UML в исходной модели.

Настройка решения Visual Studio для этого примера

  1. Создайте UML-схему классов в проекте моделирования нового решения.

    1. В меню Архитектура выберите пункт Новая схема.

    2. Выберите UML-схема классов.

    3. Следуйте подсказкам, чтобы создать новое решение и проект моделирования.

    4. Добавьте на схему несколько классов, перетащив средство создания классов UML с панели элементов.

    5. Сохраните файл.

  2. Создайте проект C# или Visual Basic в том же решении.

    • В обозревателе решений щелкните решение правой кнопкой мыши, последовательно выберите Добавить и Новый проект.В области Установленные шаблоны щелкните Visual Basic или Visual C# и выберите тип проекта, например Консольное приложение.
  3. Добавьте в проект C# или Visual Basic обычный текстовый файл.Этот файл содержит код, который можно использовать для создания нескольких текстовых шаблонов.

    • В обозревателе решений щелкните правой кнопкой мыши проект, выберите команду Добавить и щелкните Новый элемент.Выберите Текстовый файл.

    Вставьте текст, показанный в следующем подразделе.

  4. Добавьте в проект C# или Visual Basic файл текстового шаблона.

    • В обозревателе решений щелкните правой кнопкой мыши проект, выберите команду Добавить и щелкните Новый элемент.Выберите Текстовый шаблон.

    Вставьте следующий код в файл текстового шаблона.

  5. Сохраните файл текстового шаблона.

  6. Проверьте код в дочернем файле.Он должен содержать класс для каждого UML-класса в модели.

    1. В проекте Visual Basic щелкните Показать все файлы на панели инструментов обозревателя решений.

    2. Разверните узел файла шаблона в обозревателе решений.

Ee329480.collapse_all(ru-ru,VS.110).gifСодержимое общего текстового файла

В этом примере этот файл называется SharedTemplateCode.txt и находится в той же папке, что и текстовые шаблоны.

<# /* Common material for inclusion in my model templates */ #>
<# /* hostspecific allows access to the Visual Studio API */ #>
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="Microsoft.VisualStudio.Uml.Interfaces.dll"#>
<#@ assembly name="Microsoft.VisualStudio.ArchitectureTools.Extensibility.dll"#>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.Uml.Classes" #>
<#@ import namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility" #>
<#@ import namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml" #>
<#+  // Note this is a Class Feature Block
///<summary>
/// Text templates are run in a common AppDomain, so 
/// we can cache the model store that we find.
///</summary>
private IModelStore StoreCache
{
  get { return AppDomain.CurrentDomain.GetData("ModelStore") as IModelStore; }
  set { AppDomain.CurrentDomain.SetData("ModelStore", value); } 
}
private bool CacheIsOld()
{
    DateTime? dt = AppDomain.CurrentDomain
           .GetData("latestAccessTime") as DateTime?;
    DateTime t = dt.HasValue ? dt.Value : new DateTime(); 
    DateTime now = DateTime.Now;
    AppDomain.CurrentDomain.SetData("latestAccessTime", now);
    return now.Subtract(t).Seconds > 3;
}

///<summary>
/// Find the UML modeling project in this solution,
/// and load the model.
///</summary>
private IModelStore ModelStore
{
  get 
  {
    // Avoid loading the model for every template:
    if (StoreCache == null || CacheIsOld())
    {
      // Use Visual Studio API to find modeling project:
      EnvDTE.DTE dte = (EnvDTE.DTE) ((IServiceProvider) this.Host)
                       .GetService(typeof(EnvDTE.DTE));
      EnvDTE.Project project = null;
      foreach (EnvDTE.Project p in dte.Solution.Projects)
      {
        if (p.FullName.EndsWith(".modelproj"))
        {
          project = p;
          break;
        }            
      }
      if (project == null) return null;

      // Load UML model into this AppDomain
      // and access model store:
      IModelingProjectReader reader = 
           ModelingProject.LoadReadOnly(project.FullName);
      StoreCache = reader.Store;
    }
    return StoreCache;
  }
}
#>

Ee329480.collapse_all(ru-ru,VS.110).gifСодержимое файла текстового шаблона

Следующий текст помещен в файл .tt.В этом примере в файле C# классы создаются из UML-классов модели.Можно, однако, создавать файлы любого типа.Язык созданного файла не связан с языком, на котором написан код текстового шаблона.

<#@include file="SharedTemplateCode.txt"#>
<#@ output extension=".cs" #>
namespace Test
{
<#
      foreach (IClass c in ModelStore.AllInstances<IClass>())
      {
#>
   public partial class <#=c.Name#>
   {   }
<#
      }
#>
}

Использование методов создания текста

Преимущества моделирования раскрываются полнее всего, если модели используются для конструирования на уровне требований или архитектуры.Текстовые шаблоны можно использовать для выполнения некоторых задач по преобразованию высокоуровневых идей в код.Очень часто это не порождает однозначное соответствие между элементами в моделях UML и классах или других частях программного кода.

Более того, ход преобразования определяется проблемной областью; универсальное сопоставление между моделями и кодом невозможно.

Ниже приведено несколько примеров создания кода из моделей.

  • Продуктовые линейки.Fabrikam, Inc.занимается производством и установкой систем обработки багажа в аэропортах.Большая часть программного обеспечения совпадает в разных проектах, различается только конфигурация ПО, которая определяется типом установленного оборудования для обработки багажа и конвейерных ремней, соединяющих разные части этого оборудования.В самом начале выполнения контракта аналитики Fabrikam обсудили требования к системам с руководством аэропорта и с помощью UML-схемы активности составили план оборудования.На основе этой модели команда разработчиков создала файлы конфигурации, программный код, планы и документацию для пользователей.Наконец, в код было внесено вручную несколько добавлений и изменений.Приобретая все больший опыт в таких проектах, команда разработчиков создает все более полные и разнообразные материалы.

  • Шаблоны.Разработчики из компании Contoso, Ltd часто используют в создании веб-сайтов и разработке схем навигации UML-схемы классов.Каждая веб-страница представлена классом, а ссылки навигации — ассоциациями.Большую часть кода для веб-сайта разработчики берут из этой модели.Каждая веб-страница соответствует нескольким классам и записям в файле ресурсов.Преимущество этого метода в том, что все страницы создаются на основе одного шаблона, что обеспечивает большую надежность и гибкость, чем созданный вручную код.Шаблоны создания фиксируют общие аспекты, модель — меняющиеся от проекта к проекту.

  • Схемы.Компания Humongous Insurance работает с тысячами информационных систем по всему миру.В этих системах используются разные базы данных, языки и интерфейсы.Централизованная команда системных архитекторов публикует модели бизнес-концепций и бизнес-процессов для внутреннего пользования.На основе этих моделей локальные команды создают компоненты схем баз данных и схем обмена, объявления в программном коде и т. д.Графическое представление моделей помогает командам обсуждать предложения.Команды создают несколько схем, на которых показаны подмножества модели, применимые к разным бизнес-областям.Изменяемые зоны выделяются цветом.

Полезные техники создания артефактов

В предыдущих примерах модели использовались для решения разных связанных с бизнесом задач, а реализация элементов моделей (классов и действий) различалась от приложения к приложению.При создании артефактов из моделей оказываются полезными следующие техники.

  • Профили.Даже в пределах одной бизнес-области интерпретация типа элемента может варьироваться.Например, на схеме веб-сайта некоторые классы могут представлять веб-страницы, а другие — блоки содержимого.Чтобы облегчить фиксирование этих различий пользователями определяются стереотипы.Кроме того, стереотипы позволяют прикреплять дополнительные свойства, применимые к элементам соответствующего вида.Стереотипы упакованы в профили.Дополнительные сведения см. в разделе Практическое руководство. Определение профиля для расширения UML.

    В коде шаблона легко осуществить доступ к определенным для объекта стереотипам.Примеры.

    public bool HasStereotype(IClass c, string profile, string stereo)
    { return c.AppliedStereotypes.Any
       (s => s.Profile == profile && s.Name == stereo ); }
    
  • Ограниченные модели.Не все создаваемые модели можно использовать для любых целей.Например, в моделях систем обработки багажа Fabrikam отсутствие исходящего конвейера на стойке регистрации будет ошибкой.Можно определить функции проверки, с помощью которых пользователи будут следить за соблюдением подобных ограничений.Дополнительные сведения см. в разделе Практическое руководство. Определение ограничений проверки для моделей UML.

  • Сохранение внесенных вручную изменений.Лишь некоторые файлы решения можно создать из модели.В большинстве случаев в созданное содержимое приходится вносить добавления и изменения вручную.При этом очень важно, чтобы эти изменения сохранялись при повторном запуске процесса преобразования шаблона.

    Если с помощью шаблонов создается код на языках .NET, должна предоставляться возможность создания разделяемых классов, чтобы разработчики могли добавлять методы и код.Полезно создавать каждый класс в виде пары: абстрактный базовый класс с методами и наследующий класс, который содержит только конструктор.Это позволяет разработчикам переопределять методы.Чтобы разрешить переопределение инициализации, это делается не в конструкторах, а в отдельном методе.

    Если с помощью шаблона создается XML-код и другие выходные данные, отделить внесенные вручную изменения от автоматически созданного содержимого может оказаться нелегко.Для этого можно создать задачу в процессе построения, которая объединяет два файла.Кроме того, разработчики могут скорректировать локальную копию шаблона создания.

  • Перемещение кода в отдельные сборки.Не рекомендуется создавать в шаблонах большие объемы кода.Предпочтительнее отделить созданное содержимое от вычислений; кроме того, стоит отметить, что текстовые шаблоны предоставляют ограниченные возможности редактирования кода.

    Приходится выполнять объемные вычисления для создания текста, выполнять построение функций в отдельной сборке и вызывать соответствующие методы из шаблона.