UML Modeling and Code Generation in Visual Studio 2010


This article provides an overview of UML modeling in Visual Studio 2010. Assuming that reader is already familiar with UML, it focuses on custom UML profiles - an extensibility mechanism that can be used to tailor UML models to a particular problem domain. Readers will see an example of such a profile, which extends UML Class Diagrams for database modeling. Finally, the article shows how code can be generated from UML models using T4 text templates.

This article is based on Beta 2 of Visual Studio 2010 Ultimate Edition. To follow the code example you may also want to install T4 Editor which provides color syntax highlighting and IntelliSense for text templates in Visual Studio.

UML Modeling in Visual Studio

Visual Studio 2010 Ultimate Edition includes a fully-featured UML (Unified Modeling Language) support, integrated into the IDE. You can create Use Case diagrams to summarize who uses your application or system, and what they can do with it, Class diagrams to describe logical aspects of data types and their relationships, Sequence diagrams to display interaction between classes, components and actors, Activity diagrams to document flow of an algorithm or a business process and Component diagrams to show structure of a system, and how it can be deployed to a logical environment.

In order to start using UML diagrams in Visual Studio 2010, you first need to create a Modeling Project.

Once you have the project created, you can add new diagrams to it.

Here is an example of class diagram you can create.

Model elements can be added to the diagram from Toolbox and configured using Properties window.

  

You may have noticed that these diagrams are very similar to the sample diagrams that were included with the DSL (Domain-Specific Language) Toolkit in Visual Studio 2008. While little has changed on the surface, DSL diagrams had a major limitation before Visual Studio 2010. Model information was stored with each diagram, limiting you to a single diagram per model. Needless to say, this limitation made it impossible to use DSL diagrams for all but simplest models.

In Visual Studio 2010, definitions of model elements are stored in a centralized repository as part of your Modeling Project; they can be displayed on multiple diagrams. You can browse contents of the repository using UML Model Explorer and add existing elements to new diagrams by dragging them from this window onto the design surface.

 

UML Profiles

While UML works well for conceptual analysis, the standard models are often too abstract to be useful for logical and physical design. UML Profiles can be used to extend the standard models and adapt them for a particular purpose.

In Visual Studio 2010, a UML Profile is a collection of stereotypes that can be applied to individual model elements. Each stereotype defines a set of attributes that extend definition of the model element it is applied to. For example, Visual Studio includes C# Profile that can be used to extend UML classes with attributes specific to C#.

In order to use stereotypes from a particular profile, first you need to select a package in the UML Model Explorer and apply the profile in the Properties window.

 

Once a profile has been specified for the package, you can apply the stereotypes defined by the profile to the elements within the package. Example below shows the C# Class stereotype applied to a UML class, extending it with C#-specific attributes, such as Is Partial and Is Static.

Custom UML Profiles

You may want to consider creating a custom UML profile if you rely heavily on modeling in your software development project. Database modeling in particular has been widely adopted by the IT industry, with most of the new projects using database models in some shape or fashion. Unfortunately, no standard UML profile is available for database modeling at the time of this writing. However, the process of creating such a profile in Visual Studio 2010 is relatively straightforward.

Visual Studio 2010 UML profiles are defined in XML files with .profile extension.

The profile definition consists of three sections: metaclasses, propertyTypes and stereotypes.

The metaclasses section lists all UML meta-classes that are extended by stereotypes in the profile. In practical terms, meta-class is a type of model element, such as Package, Class or Association. Meta-classes are identified using fully-qualified type names of the interfaces used in Visual Studio implementation. For example, IAssociation interface represents UML meta-class Association.

The propertyTypes section lists all types used by properties in stereotypes defined by the profile. Standard types, such as System.String can be specified using externalType element. You can also use enumerationType elements to define enumerated types, such as ForeignKeyRule.

<enumerationType name=ForeignKeyRule>
  <enumerationLiterals>
    <enumerationLiteral name=NoActiondisplayName=No Action/>
    <enumerationLiteral name=CascadedisplayName=Cascade/>
    <enumerationLiteral name=SetNulldisplayName=Set Null/>
    <enumerationLiteral name=SetDefaultdisplayName=Set Default/>
  </enumerationLiterals>
</enumerationType>

Finally, the stereotypes section contains the actual stereotype definitions. Each stereotype contains a metaclasses element, which specifies the UML meta-class this stereotype extends, and a properties element, which lists the properties that will be added to the target model element when the stereotype is applied to it. 

<stereotype name=ForeignKeydisplayName=Foreign Key>
  <metaclasses>
    <metaclassMoniker name=/Sql2008DatabaseProfile/Microsoft.VisualStudio.Uml.Classes.IAssociation/>
  </metaclasses>
  <properties>
    <property name=DeleteRuledisplayName=Delete RuledefaultValue=NoAction>
      <propertyType>
        <enumerationTypeMoniker name=/Sql2008DatabaseProfile/ForeignKeyRule/>
      </propertyType>
    </property>
    <property name=UpdateRuledisplayName=Update RuledefaultValue=NoAction>
      <propertyType>
        <enumerationTypeMoniker name=/Sql2008DatabaseProfile/ForeignKeyRule/>
      </propertyType>
    </property>
  </properties>
</stereotype>

As you can see, the ForeignKey stereotype shown above can be applied to Associations in a UML model. This stereotype defines two properties – DeleteRule and UpdateRule, both of which use the ForeignKeyRule enumerated type defined in the propertyTypes section of our profile.

Notice that various elements in the profile definition have attributes called name and displayName. As you might expect, name specifies internal identifier you can use to access values programmatically, and displayName specifies human-readable text displayed by Visual Studio to the developer.

Sample Database Profile

A sample UML profile for database modeling is available for download at the end of this article. It allows you to extend UML class diagrams with stereotypes for modeling database schemas, tables, columns, primary and foreign keys in SQL Server 2008. Here is what a database diagram developed with this profile might look like.

The sample database profile contains the following stereotypes.

Stereotype
Schema
Table
Column
Foreign Key
Applies To
Package Class Property Association
Properties
Schema Name   Allow Nulls

Data TypeDefault Value

Is Identity

Update Rule

Delete Rule

Profile Installation

The intended way to install custom UML Profiles is with the help of Visual Studio Extensions, new to Visual Studio 2010. The process is well documented on MSDN, simple and easy to follow. Unfortunately, as of Visual Studio 2010 Beta 2, VSIX deployment of custom profiles appears to be broken. In order to install the sample database profile, I had to resort to manually copying the .profile file to the following directory on a 64-bit Windows 7 installation:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Team Architecture\UmlProfiles

and modifying extension.vsixmanifest file located in this directory to look like this.

<?xml version=1.0encoding=utf-8?>
<Vsix Version=1.0.0xmlns=http://schemas.microsoft.com/developer/vsx-schema/2010>
  <Identifier Id=Microsoft.VisualStudio.TeamArchitect.ProfileExtension>
    <Name>Team Architecture Profile Extension</Name>
    <Author>Microsoft</Author>
    <Version>10.0</Version>
    <Description>Microsoft Visual Studio Team Architecture Profile Extension</Description>
    <Locale>1033</Locale>
    <SupportedProducts>
      <VisualStudio Version=10.0>
        <Edition>VSTS</Edition>
      </VisualStudio>
    </SupportedProducts>
    <SupportedFrameworkRuntimeEdition MinVersion=4.0MaxVersion=4.0/>
    <SystemComponent>true</SystemComponent>
  </Identifier>
  <References />
  <Content>
    <CustomExtension Type=Microsoft.VisualStudio.UmlProfile>CSharp.Profile</CustomExtension>
    <CustomExtension Type=Microsoft.VisualStudio.UmlProfile>StandardProfileL2.Profile</CustomExtension>
    <CustomExtension Type=Microsoft.VisualStudio.UmlProfile>StandardProfileL3.Profile</CustomExtension>
    <CustomExtension Type=Microsoft.VisualStudio.UmlProfile>Sql2008Database.profile</CustomExtension>
  </Content>
</Vsix>

Notice the CustomExtension added in the end of the file, specifying Sql2008Database.profile as an extension of Microsoft.VisualStudio.UmlProfile type.

Code Generation

The simplest way to generate code from a UML model is with the help of T4 text templates. Text template is a simple code generator that can be added to any C# and Visual Basic project.

Here is the code you need to have in your template to load metadata from a UML model.

<#@ template debug=true hostspecific=true language=C# #>
<#@ output extension=.sql #>
<#@ assembly name=Microsoft.VisualStudio.Uml.Interfaces.dll #>
<#@ assembly name=Microsoft.VisualStudio.Uml.Extensions.dll #>
<#@ import namespace=Microsoft.VisualStudio.Uml.Classes #>
<#@ import namespace=Microsoft.VisualStudio.Uml.Extensions #>
<#
    string projectPath = Host.ResolvePath(@”..\ModelingProject\ModelingProject.modelproj”);
    IModelingProject project = ModelingProject.Load(projectPath);
#>

Notice the use of assembly and import directives to reference the Visual Studio assemblies and namespaces that provide API for accessing information in UML models. ResolvePath method of the Host object is used to determine absolute path to the modeling project and Load method of the ModelingProject class is used to open the UML repository.

Here is a complete template that generates SQL scripts for creating tables based on the UML class model extended by our database profile.

<#@ template debug=true hostspecific=true language=C# #>
<#@ output extension=.sql #>
<#@ assembly name=System.Core #>
<#@ assembly name=Microsoft.VisualStudio.Uml.Interfaces.dll #>
<#@ assembly name=Microsoft.VisualStudio.Uml.Extensions.dll #>
<#@ import namespace=System.Linq #>
<#@ import namespace=Microsoft.VisualStudio.Uml.Classes #>
<#@ import namespace=Microsoft.VisualStudio.Uml.Extensions #>
<#
    string projectPath = this.Host.ResolvePath(@”..\ModelingProject\ModelingProject.modelproj”);
    IModelingProject project = ModelingProject.Load(projectPath);
    foreach (IType t in project.Store.Root.OwnedTypes)
    {
        IClass c = t as IClass;
        if (c == null) continue;
#>
create table <#= GetSchema(project.Store.Root) #>.<#= c.Name #>
(
<#
        this.PushIndent(“\t”);
        foreach (IProperty p in c.OwnedAttributes)
        {
            IStereotypeInstance column = p.AppliedStereotypes.Where(s => s.Name == “Column”).First();
            this.WriteLine(p.Name + ” “ + GetDataType(column) + GetNull(column) + GetIdentity(column) + “,”);
        }
        this.PopIndent();
#>
);
<#
    }
#>
<#+
    private string GetSchema(IPackage package)
    {
        IStereotypeInstance schema = package.AppliedStereotypes.Where(s => s.Name == “Schema”).First();
        IStereotypePropertyInstance schemaName = schema.PropertyInstances.Where(p => p.Name == “Name”).First();
        return schemaName.Value;
    } 

    private string GetDataType(IStereotypeInstance column)
    {
        IStereotypePropertyInstance dataType = column.PropertyInstances.Where(p => p.Name == “DataType”).First();
        return dataType.Value;
    } 

    private string GetNull(IStereotypeInstance column)
    {
        IStereotypePropertyInstance allowNulls = column.PropertyInstances.Where(p => p.Name == “AllowNulls”).First();
        return bool.Parse(allowNulls.Value) == true ? string.Empty : ” not null”;
    } 

    private string GetIdentity(IStereotypeInstance column)
    {
        IStereotypePropertyInstance isIdentity = column.PropertyInstances.Where(p => p.Name == “IsIdentity”).First();
        return bool.Parse(isIdentity.Value) == true ? ” identity” : string.Empty;
    }
#>

This code uses a foreach loop to iterate through the list of types owned by the Root model in our project and generates a create table script for each class. Notice the helper methods, such as GetSchema and GetDataType. They use AppliedStereotypes property of the model element to find the stereotype defined in our database profile, such as Schema or Column. Having found the stereotype instance, its properties properties are accessed through the PropertyInstances collection.

Here is the code generated by this text template from our UML model.

create table dbo.Customer
(
    FirstName nvarchar,
    LastName nvarchar,
    StreetAddress nvarchar,
    City nvarchar,
    State nvarchar,
    PostalCode nvarchar,
    Id int not null identity,
);
create table dbo.Product
(
    Name nvarchar,
    Price nvarchar,
    Id int not null identity,
);
create table dbo.Order
(
    Date nvarchar,
    TotalAmount nvarchar,
    Id int not null identity,
    CustomerId int,
);
create table dbo.OrderItem
(
    Id int not null identity,
    OrderId int,
    ProductId int,
);

UML vs. DSL

UML models are high-level abstractions, typically representing systems at conceptual or logical levels. This is an intentional, desired aspect, as it allows you to model a wide variety of of systems without tying the design to any particular platform or implementation. While high-level models serve as an excellent communication tool during envisioning and design phases, during implementation high-level models quickly become outdated, causing confusion. While automated code generation and reverse engineering of models is possible, the process is complex, fragile and requires additional effort.

Comprehensive support for UML is a significant change in direction of Microsoft’s approach to modeling. You may remember that when Domain-Specific Language tools were announced a few years ago, the emphasis was on practical application of modeling throughout the software development lifecycle. It was suggested that models should be considered equal to other source code artifacts, such as .cs/.vb files and .aspx pages. Typical DSL models are lower-level abstractions, representing a system at logical or physical levels. They are predominantly used for code generation and rely on partial classes and inheritance to avoid reverse engineering model information from code back to the model. Examples of DSL models in Visual Studio include LINQ to SQL and Entity Framework designers.

While these approaches to modeling appear to be different, in reality they complement each other, providing us with a full range of modeling capabilities from conceptual and logical, down to physical level. UML models are useful during early stages of a software development project and DSL models work best during implementation and maintenance of the system. It is interesting to note that UML models are actually implemented using DSL tools, so from Visual Studio prospective, UML is simply a DSL for the “unified modeling” domain.

Conclusion

As you can see, Visual Studio 2010 Ultimate Edition provides powerful UML modeling tools that can be used for conceptual and logical analysis during software development. UML Profiles can be used to extend standard models and allow modeling information systems at physical level. A limited number of UML profiles is expected to ship with Visual Studio 2010. Custom profiles can be developed to tailor UML models to the needs of individual projects. Combined with T4 Text Templates, this gives developers a powerful tools for model-driven development of information systems, where large portions of the system can be modeled in UML and generated with T4. 

References

Download

Source code


Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

[…] UML Modeling and Code Generation in Visual Studio 2010 (Oleg Sych) […]

I’m intrigued at your comments in the UML vs DSL section of this article.

I’ve been using the EF modeling tool as a basis for a code gen solution. I’m not really making use of the EF itself but rather just using its modeling tool and EDMX file.

Two facts have come to mind during this process that I think relate to your article. The first is simply that at times I feel like while the EF modeler gets the job done, I would really like to be a bit more detailed/specific about the entities. Such as defining a base class vs a base interface. I have thought about moving away from the EF’s modeler to something else to get this, UML certainly comes to mind.

The second is that when doing significant code generation there comes a need to provide additional “hints” in the model to provide aids to the generation process. For example you can tell the EM modeler that a property is a string but you have no ability to constrain the length of that string. I would very much like a modeler that allows ad-hoc additional attributes to be placed on entities/properties. Your article here is clearly showing that the new ULM tools provide this which excites me.

So to the point.

As I read your article I get very excited as it seems to be showing that the new UML tools are going to hit both of my concerns. Thus I start to think about moving to UML as my modeler of choice. But I am trying to use a model more like you describe it on the DSL section as “equal with source code”.

Considering all this, do you really feel that the new UML tools are suited for the high-level modeling only? Yes I know this is the UML historical use, but the new features you describe in this article seem to me to suggest UML is moving toward being useful in a “model is source” environment.

Sorry for the long winded comment:)

Excellent article that gives me just the information I was looking for!

What’s your view on how MS will be enhance the UML features going forward? Do you foresee it evolving more into a physical model-driven approach?

Sorry though that MS does not include the read-only view of the models in VS 2010 Prof Edition as well.

Thx again

[…] UML Modeling and Code Generation in Visual Studio 2010 - Oleg Sych gives a tour round the UML Modelling functionality of Visual Studio 2010, showing how you can customise the UML profiles, and looking at generating code from the model […]

One of the challenges with doing UML in a team environment is how to merge changes made by different team members.

Any tool that stores it’s repository in a binary blob will have a really really tough time with this. And tools that use a relational database for storage often don’t understand branching and merging. Yet other tools use XML as their storage, which presents it’s own challenges.

How does VS.NET Ultimate Edition handle this problem?

Great article Oleg.

@ChipH - The UML tools within VS store the model as a set of XML documents, one per UML package, and the diagrams in a separate set of files. These files of course can be checked in/out of source control. As you mention each approach to model storage has trade-offs.

Thanks- Mark

Hi Oleg,

that is a really awesome summary. Again you are faster than the product group to actually assemble a full end to end story that is kind of real world on how to use UML inclusing Profiles and T4 in .NET Projects together.

Thank you very much for this post!

Tim

[…] You can find Oleg’s blog post about using T4 and the UML modeling tools to generate code on his blog at http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/. […]

[…] Oleg Sych – » UML Modeling and Code Generation in Visual Studio 2010 – I really need to play with Visual Studio 2010 Beta… Share and Enjoy: […]

Jeff,

Regarding whether UML can be used for modeling at physical level, It certainly can be. However, usability of a UML model extended by a custom profile is still worse than usability of a DSL model built specifically for that purpose. Take the database profile in this article as an example. Yes, you could model a database with it, but more than a half of the built-in attributes in UML Class diagrams are not applicable to database models, which will cause confusion and make it more difficult to use.

Hopefully at some point, UML Profiles will allow us not only to extend the models, but also restrict them by removing properties that are not applicable.

Oleg

@ChipH,

Mark is correct, Visual Studio stores model information in XML files, one per package. Personally, I feel having a single file per class would work better from the source control and team logistics prospectives, however, its too early to tell now. We’ll see how package-level files will work.

Oleg

do you know if vs2010ultimate allow ’sync’ changes between model and the code?

if i change something in the model, will this change affect the code and vice-versa?

best wishes,

[…] And Oleg’s slides from the Architecture session are at: http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/  […]

[…] And Oleg’s slides from the Architecture session are at: http://www.olegsych.com/2010/01/uml-modeling-and-code-generation-in-visual-studio-2010/  […]

Is there a way to get a IStereotype reference from a t4 template?
I tried something like this, but the ApplicableStereotypes enumereation is empty.
void WriteClassAttributes( IClass classItem )
{
foreach( IStereotypeInstance stereoInst in classItem.AppliedStereotypes )
{
this.WriteLine( string.Format( “{0} = {1}”, stereoInst.Profile, stereoInst.Name ) );
}
foreach( IStereotype stereo in classItem.ApplicableStereotypes )
{
this.WriteLine( string.Format( “{0} = {1}”, stereo.Profile.Name, stereo.Name ) );
}
}

I tried to get IStereotype from ModelStore. But ProfileManager property is always null.

string GetDefaultValue( IStereotypePropertyInstance stereoProp )
{
IModelStore modelStore = stereoProp.GetModelStore();
Microsoft.VisualStudio.Uml.Profiles.IProfile profile =
modelStore.ProfileManager.GetProfileByName( profileName );

foreach( Microsoft.VisualStudio.Uml.Profiles.IStereotype stereo in profile.Stereotypes )
{
if( stereo.Name == stereoProp.StereotypeInstance.Name )
{
return stereo.DefaultValue;
}
}
}

I’m stucked. Please help!

[…] T4, как всегда. Если интересно, можете почитать тут. В принципе, все не так сложно, но было бы круто если бы […]

[…] a good explanation on UML profiles, and code generation, you can check out this post. Now let’s go to the code. First, you will need to import the following […]

Excellent post, you have inspired me to write my own template. I have pulled togheter a very simple t4 template for generating classes, interfaces and enums based on a modeling project in case anyone needs it: http://thegsharp.wordpress.com/2010/05/24/vs2010-modeling-project-%E2%80%93-generating-classes-from-uml-%E2%80%93-t4-template

Cheers!

[…] обратите внимание на пост гуру T4 - Олега Сыча: UML Modeling and Code Generation in Visual Studio 2010 и блог Тима Фишера (Tim […]

Hi Oleg,

I am using a class diagram that is reversed engineered for code generation. I created a custom attribute where I want to set various properties that I will use during code gen.

I can manually add attributes to my class diagram, but when I reverse engineer the class diagram, the attribute decorations in my class are not being added to the diagram. Do you know how to make that happen?

Roy,

I suspect that reverse-engineering functionality simply does not support custom attributes at this time and to make it happen someone would need to submit a change request on Microsoft Connect portal.

Oleg

[…] a good article to help you. (Oleg Sych: UML Modeling and Code Generation in Visual Studio 2010) Tags: UML Category: .NET  |  Comment (RSS) […]

Great Article Oleg. For those looking for POCO generation, I have modified the .tt file to use with VS2k10 RTM Release.

<#
string projectPath = Host.ResolvePath(@"..\CommerceModeling\CommerceModeling.modelproj");
using (IModelingProjectReader projectReader =
ModelingProject.LoadReadOnly(projectPath))
{
IModelStore store = projectReader.Store;
foreach (IClass classElement in store.AllInstances())
{

if (classElement != null) {
#>

class {

string {get;set;}

}

Great Article Oleg. For those looking for POCO generation, I have modified the .tt file to use with VS2k10 RTM Release.

<#
string projectPath = Host.ResolvePath(@”..\CommerceModeling\CommerceModeling.modelproj”);
using (IModelingProjectReader projectReader =
ModelingProject.LoadReadOnly(projectPath))
{
IModelStore store = projectReader.Store;
foreach (IClass classElement in store.AllInstances())
{

if (classElement != null) {
#>

class {

string {get;set;}

}

Hope this comment translates better…

Holy $#!t, I feel like I just stumbled onto the website of a genius…defining custom VS 2010 UML stereotypes, T4 templating code generation…*exactly* what I was searching for, down to a T.

Been reading about your blog and learning about your seminars. Oleg, I am very impressed.

- Harvo

I tried this profile but, couldn’t get it to work.

I changed the assembly to “Microsoft.VisualStudio.ArchitectureTools.Extensibility.dll”, as the UML.Extensions didn’t survive the beta.

I stll can’t get it to work. I get the following error message:

Error 3 Compiling transformation: Cannot implicitly convert type ‘Microsoft.VisualStudio.ArchitectureTools.Extensibility.IModelingProjectReader’ to ‘Microsoft.VisualStudio.ArchitectureTools.Extensibility.IModelingProject’. An explicit conversion exists (are you missing a cast?)

I would appreciate any advice to resolve this.

i have only the class diagram in visual studio 2008 from this how do i create source code