IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Rational  >

使用 IBM Rational Systems Developer 和 Rational Software Architect 实现 UML 与 C++ 的转换

同步修改模型和代码,实现由 UML 模型向 C++ 代码转换的迭代开发。

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

样例代码


级别: 中级

Sandeep Kohli, 高级软件工程师, IBM
Sreerupa Sen, 高级软件工程师, IBM

2007 年 8 月 13 日

学习如何使用 IBM® Rational® Software Architect 和 Rational® Systems Developer 工具将 UML 建模适于开发 C++ 应用程序。本文描述了7.0版本支持 C++ 领域建模的特性。在此,假设您正在不断更新模型和代码,并且想要实现 UML 与 C++ 之间的对应修改。那么您只需要拥有 UML 的基本知识,了解本文中介绍到的 Rational 软件产品,掌握如何运行转换以及如何应用概要文件和构造类型,就可以达到您的目的。

通过本文的姊妹篇 “使用 Rational Systems Developer 和 Rational Software Architect 进行 C++ 转换的提示与技巧,第 1 部分:控制由 UML 模型生成的 C++ 代码” 了解从 UML 模型生成 C++ 代码的方法与技巧。

条件及过程概述

本文解释了作为一名 C++ 开发人员,如何在使用统一建模语言 UML 建模的时候,继续使用 C++ 数据结构进行设计。您只需掌握 UML、IBM® Rational® Software Architect 和 IBM® Rational® Systems Developer 的相关基本知识即可。

  1. 在 IBM Rational Systems Developer 创建一个简单的 UML 模型。
  2. 将一个 C++ 概要文件应用在模型上,这样,就可以在建模的过程中使用 C++ 的数据结构。
  3. 将 C++ 类型库导入模型,这样,就可以使用 C++ 基本类型。
  4. 生成代码。
  5. 在类中添加方法体。
  6. 另外提供一些小技巧,以便在重复进行转换时保存代码和模型的修改。

创建一个简单的 UML 模型

UML 概要文件是扩展 UML 的一个标准机制,所以对某些特定领域的建模可以在不增加 UML 负担的情况下进行。UML 的创始人不可能涉足到所有的应用领域,因而,他们明智地提供了扩展机制。

应用 C++ 概要文件

例如,要对某个 C++ 具体的元素建模,比如 structuniontypedef 等,您需要在 UML 模型上应用 C++ 概要文件。步骤如下:

  1. 确定您正处于 Modeling 透视图。
  2. 选中模型,然后单击 Properties 视图。
  3. Properties view 左侧,从列表中选择 Profiles
  4. 单击 Add Profile,在 Select Profile 对话框中 Deployed Profile 下方选择 C++ Transformation (如图1和2所示)。

图1. 应用 C++(CPP)概要文件
Figure 1. Steps in applying the C++ (CPP) profile


图2. 选择 C++ 概要文件
Figure 2. Selecting the C++ profile

导入 C++ 类型库

UML 提供了一组预定义的类型,有 Boolean、Integer、String UnlimitedNatural。而大多数的编程语言,包括 C++,提供了更为丰富的基本类型。在 C++ 中建模的时候,您可能经常需要使用 C++ 预定义的基本类型(比如,将一个类型赋给某个属性、参数、操作返回类型,等)。下面讲述如何导入 C++ 模型库:

  1. Project Explorer 中右键单击 UML 模型。
  2. 如图3所示,选择 Import Model Library

图3. 导入 C++ 类型库
Importing C++ Type Library

  1. 如图4所示,在 Import Model Library 的运行界面上,从下拉列表框中选择 C++ Types

图4. 选择要导入的 C++ 类型库
Selecting C++ Type Library

现在已经作好为 C++ 特定元素建模的准备了。请接着参看后面的示例。

创建一个简单的 UML 模型,car factory。

创建如图5所示的 UML 模型。创建的过程如下所示:

  • 这个示例模型中,BusCar 的基类是 Vehicle
  • BusCarVehicle 类被创建在一个名为 Vehicles 的 UML 包中。
  • 同样的,在名为 Parts 的包中,建立EngineWheels 类。
  • CarEngine 之间存在组合的关系。
  • 理论上, CarEngine 是不可分的,因为汽车需要引擎。
  • CarBusWheels 都有聚合的关系。
  • 本例中,轮胎可以没有汽车而存在,汽车可以没有轮胎而存在 -- 至少在组装的时候。

图5.一个简单的汽车工厂 UML 模型的示例
Figure 5. Simple UML model of a car factory used here as an example

在模型中创建 C++ 元素

  1. 接下来,创建一个名为 Strategy 的 UML 包。
  2. Strategy,定义公共汽车的路线和起点。
    1. 创建一个名为 Route 的类,用来表示路线;一个名为 Address 的类,用来表示地址,比如公共汽车路线的起点。
    2. Address 需要是 C++ struct 元素而不是普通的类。
  3. 为 UML 模型指定每个公共汽车的路线。如图6所示,您可以为 Vehicles 包中的 Bus 类和 Route 类之间设置聚合关系。
  4. 起始点是路线的一个属性。所以,为 Route 类增加一个类型为 Address,名称为 startingPoint 的属性。

图6. 名为 Strategy UML 包的内容
Figure 6. Contents of the new UML package called Strategy

在图6中,请注意 Address 是 <<cpp_struct>>类。创建的步骤如下:

  1. 创建一个 UML 类,命名为 Address
  2. cpp_struct 原型应用给新建立的类。
    1. 将一个原型应用给 UML 元素,转到 Properties 视图。
    2. 如图7所示,从左侧的列表中选择 Stereotypes,然后单击 Apply Stereotypes

图7. 应用一个原型
Figure 7. Applying          a stereotype

  1. 从该元素可用的原型列表中选择 cpp_struct。同时,也可以留意一下其它的选择,以备日后参考。

您很快就能发现,将这个模型转换成代码的时候,带有<<cpp_struct>>原型的 Address 类将会生成一个 struct 元素,而不是一个类。





回页首


配置转换并生成代码

在由模型生成 C++ 代码之前,需要通过创建转换配置来设置相应的参数。

创建转换配置

步骤如下:

  1. 单击 File > New > Others,然后选择 Transformations 文件夹中的 transformation configuration
  2. New Transform Configuration 向导中,指定配置文件名,此处命名为 tc1
  3. 选择 transformation typeproject
    1. 展开 IBM Rational Transformations 列表,然后选择转换类型 UML to C++
    2. 本练习中,使用已有 UML 模型项目来保存转换配置文件。
  4. 单击 Next,继续进行后面的步骤。
  5. Source and Target 选项卡中:
    1. Source:选择 UML 模型。
    2. Target:创建一个新的 C++ 项目。
  6. 请确定 sourcetarget 都是选中的,然后单击 Finish

注:
如果需要,您可以再对转换配置进行修改。

生成代码

之后的步骤就比较简单了。

  1. 进行到现在,您已经完成了大部分比较难的工作,接下来,只需右键单击 tc1.tc,然后从弹出式菜单中选择 Transform > UML to C++,就可以在选定的项目中生成代码。
  2. 看一下 Route 类生成的代码。如列表1所示,它包括 startingPointendingPoint 属性,以及 getFare() 方法。

列表1. Route 类生成的代码文件 Route.h
                

#ifndef ROUTE_H
#define ROUTE_H
//Begin section for file Route.h
//TODO: Add definitions that you want preserved
//End section for file Route.h

struct Address;

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class Route
{

    private:
  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_Hk7qMACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        float runningCost;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_hKd58ACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        float expectedProfit;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_ieiw8ACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        Address * startingPoint;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_jkEOkACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        Address * endingPoint;
    public:

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_kawmAACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"

        float getFare()const ;

};  //end Class Route

#endif    
      

如列表2所示, getFare 方法的默认内容已经生成。


列表2. Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp


float Route::getFare() const 
{
    //TODO Auto-generated method stub
    return 0;
}    
      





回页首


修改代码

请注意,默认生成的内容一般不能够直接使用,因为 fare 总是 0 (zero),而这并不是一个有利的业务!所以需要将 getFare 方法的内容用列表3来代替。


列表3. Route.cpp
                
float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}
      





回页首


开发模型并再次运行转换

现在,在UML模型中为 Route 类添加另一个名为 print_disclaimer() 的方法。

  1. 设置返回类型为 String
  2. 请注意,我们已为 getFare 方法添加内容,修改了Route.cpp文件。
  3. 使用相同的配置 (tc1.tc > Transformation > UML to C++)运行转换。
  4. 选择目标文件自动更新(默认选项)。

现在,一起来看看更新的代码(列表4)。


列表4. 更新的 Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp


float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer() 
{
    //TODO Auto-generated method stub
    return 0;
}
      

关于 @generated 标记

请注意方法注释中的 <<@generated>>。方法体可以被自动保存。但是,如果您从模型中删除了该方法,然后再次运行 C++ 转换,那么这个方法和代码中的方法体都将会被删除。这样,就能够确保代码与模型的一致。

如果想要当模型中删除方法之后,代码中仍保存方法体,那么,您可以从方法注释中删除 <<@generated>> 标记。

请注意,修改的 getFare() 方法体已被保存。同时,模型中新添加的 print_disclaimer 方法已在 Route.h 和 Route.cpp 文件中生成新的代码。这样,您可以继续在代码中执行方法,同样地,可以对模型作增量修改。这在模型驱动迭代开发中相当有用的。





回页首


将 include 声明添加到保存节中。

print_disclaimer 方法体的代码如图5所示。请注意,我们使用了 cout 操作符,但 C++ 不能够识别。然而,代码是否能够正确解析,这是相当重要的,所以当转换再次执行的时候,应当将代码结构和方法体保存下来。如果想使这段代码可编译,您需要在 cpp 文件中添加 #include <iostream>using namespace std;。当重复执行 UML 与 C++ 转换的时候,这些声明将会被保存下来。把这些声明插入到以下两条注释之间:

//Begin section for file Route.cpp
//End section for file Route.cpp

您添加到这个节中的内容将一字不漏地保存下来, 并且不需要 C++ 转换解析。


列表5. Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
#include <iostream>
using namespace std;
//End section for file Route.cpp


float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer() 
{
    const char *s = "No Refund once the ticket is purchased\n";
    cout << s;
    return s;
}
      

下载:

  • UML 模型和 C++ 项目示例:选择 File > Import,然后按照 Import Existing Projects into Workspace 向导的提示操作,就可以将项目导入到 Eclipse 工作空间。





回页首


小结

本文讲述了使用 Rational Systems Developer 创建 UML model,然后生成 C++ 代码的基本步骤,以及保持代码与模型同步的方法。想要了解更多的信息,请参阅相关的链接资源。






回页首


下载

描述名字大小下载方法
Sample UML Model project.MyAutomobileFleet.zip7KBHTTP
Final CPP ProjectAutomobileFleetCode.zip33KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论


作者简介

Sandeep Kohli

Sandeep Kohli 是位于 Bangalore 的 Rational Software Architect / Rational Systems Developer 项目组的开发工程师和构架师。他的工作涉及到多种 Rational 建模工具,比如 Rational Rose、Rational RoseRT 和 Rational Software Architect。此外,他还从事 C/C++/Fortran/Ada 编译器方面的工作。


Sreerupa Sen

Sreerupa Sen 是 IBM 的一位架构师,主要从事 Rational UML 建模工具方面的工作。在她的软件职业生涯中,她曾跨足不同的领域,包括银行应用系统、中间件、实用数据中心,以及建模工具。在 IBM 她主要致力于 IBM Rational Software Architect / Rational Systems Developer,特别擅长使用 C++。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款