Code is generated, and output to files, from the UML | Code | Generate menu:
This command opens the Generate dialog window, shown in the screenshot opposite:
In the Target language field the developer can choose the programming language, which becomes the output language for the code - if this disagrees with the choice of language made at any point in the diagramming phase, no error will be reported. We'll look more at this again in a moment. In the right-hand side of the dialog window you can select namespaces and classes you want to export from your model to the resulting code. After all the components are chosen - selecting the entire model selects each class in the model - and the programming language to be used is chosen, we can launch the generating process by clicking the OK button. If the directory into which you wish to generate the code does not exist, you will be asked if the directory should be created for you: Remember the Target Language field that we saw in each of the earlier Code Generation Options dialogs? Well, it turns out that any language choices you made there are irrelevant to the final code generation from the UML | Code | Generate menu.
Thus if you choose C# from the Generate dialog but have the target language for some of your methods set as Visual Basic (.NET), then they will still be generated as C#. The code will be generated and put into the file we specified from the Location field, ready to be added to our projects. Note that the code generating procedure allows us to add the generated code to Visual Studio .NET projects automatically by checking the Add Classes to Visual Studio Project checkbox. With this checkbox checked, the Template drop-down becomes active, and it contains a list of the Visual Studio .NET project types into which the generated code will be added. All possible types of Visual Studio .NET projects are listed. If you want to add your classes to a web project - Empty Web Application, ASP.NET Web Application, or ASP.NET Web Service, then you have to specify a valid URL for the project, rather than a filename, just as you would in Visual Studio .NET. Code will be generated for each selected class, and will go into a separate file with the name of the class followed by the extension for that language. There are three files created for our example, Employee.cs, Person.cs, and DateTime.cs. Employee.cs contains the code for the Employees class, the Person interface code is in Person.cs, and the System. DateTime code is in DateTime.cs - this file only contains the class definition, since we didn't do anything else to the class. Here's Employee.cs:
// Static Model using System; public class Employee : Person { Here we can see the using directive for the System namespace - this comes from the System package that contained the DateTime structure. We can also see that the Employee class is indeed implementing the Person interface.
private int id; private System.DateTime hireDate; private decimal salary; Here we have our private fields, and the public members are next - note the read-only properties ID and Salary:
public string FirstName { get { } set { } } public string LastName { get { } set { } } public DateTime BirthDate { get { } set { } } public int ID { get { } } public decimal Salary { get { } } public DateTime HireDate { get { } set { } } Next up is our pre-populated ChangeSalary() method, with the information that we specified in the Documentation box added as a comment:
// Changes the salary of the employee public void ChangeSalary(decimal amount) { salary += amount; } }// END CLASS DEFINITION Employee You may be wondering why the code has been organized so - we'll see why in a moment. Here is the code in Person.cs for the Person interface, with its properties:
// Static Model using System; public interface Person { string FirstName { get; set; } string LastName { get; set; } DateTime BirthDate { get; set; } }// END INTERFACE DEFINITION Person
Regenerating CodeGenerating code again will not overwrite an existing file - any existing files that would be overwritten are renamed to <classname>~1 followed by the language extension, and the new code is always of the form <classname> with the language extension. Thus generating the code again for our example would rename Employee.cs to Employee~1.cs and Person.cs to Person~1.cs, and the new code files would be Employee.cs and Person.cs. Subsequent generations would see Employee~1.cs and Person~1.cs renamed to Employee~2.cs and Person~2.cs, and so on, so that existing code is never overwritten.
Checking ErrorsWe can investigate any errors that would be produced in the code generation process by first selecting the UML | Check menu item. This command activates the Output window, which is shown below:
In the drop-down list situated in the top part of the Output window, you can choose the kind of errors to be shown. If the Errors element is chosen, then the error messages about the semantic errors in UML model will be shown. Semantic errors indicate invalid constructions in UML 1.2. For example, in UML you can't use interfaces as parameter types. The offending classes that contain these errors will be highlighted in red on the diagram. If the Code element is shown, then the error messages about possible errors in generated code will be shown. Code errors indicate invalid constructions in the target language. For example, in C# and in Visual Basic .NET you cannot have multiple inheritance:
Here we've modified the Employee class to inherit from more than one class - as you can see, the offending class is named in the Output window, and if you the click on the error line then the offending class is highlighted in the diagram.
Code Generation in Different LanguagesWe have seen how code generation works with C#, but let's take a moment to see compare the code generated for our Employee class in Visual Basic .NET with that in C#. We'll see that although Visio can generate code to other languages, the language-specific choices you make when creating the model have consequences. Here is the Visual Basic .NET code for the Employee class, as generated by Visio:
' Static Model Imports TopPackage.System Public Class Employee Implements Person Private id As Integer Private hireDate As System.DateTime Private salary As Decimal Public Function FirstName () As String Implements Person.FirstName End Function Public Function LastName () As String Implements Person.LastName End Function Public Function BirthDate () As DateTime Implements Person.BirthDate End Function Public Function ID () As Integer End Function Public Function Salary () As Decimal End Function Public Function HireDate () As DateTime End Function ' Changes the salary of the employee Public Sub ChangeSalary (ByVal amount As Decimal) salary += amount; End Sub End Class ' END CLASS DEFINITION Employee Take a look at this code. There are two problems here - the first is the Imports statement:
Imports TopPackage.System This is not the namespace we want imported - we want System imported. This is a peculiar behavior of Visio. When we generated code for the C# project, the Default Namespace property was set to TopPackage - this property does not affect existing code. It is only used during the creation of new files, when this property is applied to set up a namespace. In the Visual Basic .NET project the Root namespace property is set to TopPackage, but this property has a different meaning from the C# Default Namespace - in the Visual Basic .NET project any namespace is prefixed with TopPackage during compilation. Thus if you have the namespace System55 in your code, it compiles to TopPackage.System55. Therefore, Visio will generate System.DateTime to TopPackage.System.DateTime. This is a curiosity, and hopefully one that will be corrected in future releases. The other problem is the code in the ChangeSalary() method body - it's still C#.
Public Sub Changesalary (ByVal amount As Decimal) salary += amount; End Sub Any code that we explicitly add to method bodies will be inserted into generated code files without modification, regardless of the language used for generation. In this situation, our Visual Basic .NET code will not compile.
| |||||||||||||||||||||||||||||||||||