用 C++ 编码架构图的最佳用例

news2024/11/13 13:40:05

在这里插入图片描述
统一建模语言(UML),作为一种实际应用的语言标准,借助一系列架构图呈现建模软件系统。UML 的出现鼓励了自动化软件工具的开发,有助于自动代码生成。UML 图面向对象系统和软件工具,将静态结构和动态行为以可视化的模型展现,而后继续根据既定的图表自动生成代码。

模型驱动工程(MDE)是一种软件开发方法,以模型代替源代码,作为架构图软件开发生命周期(SDLC)的主要构件。

模型驱动工程公认的发展源头是模型驱动架构(MDA)。这是对象管理组织(OMG)在 2001 年提出的一种新的软件开发范型(summerville, 2009)。模型驱动架构使用 UML 图的子集,如类图、序列图和状态图。其设计初衷是减少开发工作量,在软件开发过程的每个阶段创建、使用分析和设计模型,并自动从模型生成代码。

然而,自动代码生成在软件工程中得到了广泛的关注,因为它具有可重复使用、出错率低(对比人工代码编写)、易于维护和准确度高等优点。此外,如果可以从模型自动生成代码,以便精确理解模型和代码之间的对应关系,则高级建模和分析的优势将显著增强。

动机

鉴于抽象水平的差异,架构图通常存在模型 – 系统缺口。随着可视化建模的日益普及,使用高级模型进行程序代码自动生成也成为一个重要的问题。如果可以从模型中自动生成代码,从而更 地理解模型和代码之间的对应关系,则高级建模和分析的优势将更为显著。面向对象的方法可以帮助开发人员利用架构图分析、理解系统,但其分析和设计方法的致命弱点是向需要向代码过渡。

大多数可用的面向对象的方法在分析和设计阶段都需要遵循冗杂的步骤,而且很难描述如何将系统的分析和设计模型转换为代码。使用面向对象开发系统的一个难题是,即使创建了良好的模型,大部分软件开发人员也很难将设计模型转换为可执行的代码。所以,如果能有支持开发人员,并且能够自动生成或帮助模型生成可执行代码的工具就完美了。

此外,在 UML 模型的架构图中检查代码便于用户识别包含代码的关键模块,为后续深入了解预存的系统业务和系统需求做好准备,进而帮助开发人员全面理解源代码。

目标

开发架构图的终极目标是从 UML 类图自动生成代码,不过,一般的目标是:

  1. 从面向对象的编程语言(如 C++)中找到一种从 UML 类图生成实现代码的方法。 2、执行以上方法,并开发一个从 UML 类图生成
  2. C++ 代码的自动生成系统。我们的代码生成方法和工具将有助于弥合设计和开发阶段之间的差距,在软件开发过程中为开发人员提供支持。

实施方法

从 UML 生成 C++(双向工程)

架构图中的双向工程是指从源代码生成模型并从模型生成源代码,且两个过程可以同步进行。我们可以利用这种双向功能来保持模型和源代码的更新,生成模型的最新文件。

以类图为例。大多数的类图概念与编程语言概念都有一对一的映射。类图可以用类和对象、组合和继承等表示支持性概念的编程语言直接实现。

UML 与 C++ 的类图转换

在这里插入图片描述
有许多工具可以在线执行此过程,具体可以查看相关文档,了解如何使用这些工具。下表中提供了一些工具的名称和相应的网站:

UML 源代码生成器工具及网站:

在这里插入图片描述
上述一些工具可以免费试用,试用时间可长达一个月或以上。另外还需要注意的是,版权所属是进行双向处理时需要考虑的一个重要问题。在某些情况下,软件工具中的一些限制可能会阻止这个过程的运行。同样不可忽视的是,用户需要在启动这个过程前解决版权问题。下面列举了一些导致双向处理的情况,代码或 UML 图:

  1. 已经进行了开发
  2. 获得使用许可的只是第三方库的一部分
  3. 企业使用的只是框架的一部分
  4. 开发人员每天都在开发。

在开发架构图时,我们使用了一个名为 Visual Paradigm 的软件工具,该工具目前支持以下编程语言的双向工程:

  • Java
  • C++
  • C#
  • NET
  • PHP
  • ODL
  • ActionScript
  • Perl
  • Python
  • Objective C
  • Ruby
  • IDL
  • XML Schema

Visual Paradigm 架构图从 UML 图中用 ANSI 生成代码,并用上述的编程语言从 ANSI 代码中逆向生成 UML 类图。详情请访问 Visual Paradigm 网站,了解如何使用工具以及上表中列举的其他工具。

从 UML 图生成 C++ 代码

架构图系统由多个状态图组成,每个状态图都显示系统类图中包含的特定对象类的行为。我们用 UML 类图演示代码生成方法。

我们将使用类图 Animal 来展示 C++ 中生成的代码。
在这里插入图片描述

许多用于双向工程的面向对象工具大都会从类图中生成头文件。仅从类图生成代码将生成有限的骨架代码,由类属性和方法标记组成,为系统的对象结构提供框架代码。由于面向对象模型系统的动态行为可以使用状态图实现,生成的架构图代码不完整,所以无法执行。基于对象动态的部分模型,开发者可以用目标语言(例如 C++、Java 等)显式地编写对象行为和通信,使其成为可执行的。

上面 Animal 类的源代码如下所示
在这里插入图片描述
这是 Animal 类的头文件

在这里插入图片描述
生成的源代码包括 UML Animal 类图中每个属性和方法的类定义、变量和函数存根。

逆向工程

架构图的逆向工程是将现有的源代码导入到模型元素中,将源代码结构投映到UML视图中。方便用户检查遗留代码和代码库的功能,并重新利用,同时有利于保持UML模型与代码最新版本。逆向工程使用的语言,在此建议与 Visual Paradigm代码生成的语言保持一致。

现有的源代码结构映射到UML,例如C++类映射到UML类元素,变量定义为属性,方法建模为操作。借助适当的连接器,C++类之间的交互在UML模型中呈现为类图。

借助逆向工程,用户可以直观地检查遗留代码和代码库,取其精华并予以重新利用,同时随时检查 UML模型与代码的版本,保持更新状态。

在UML模型中检查代码,用户可以识别包含代码的关键模块,便于之后深入理解现有系统的业务和系统需求,使开发人员也得以更全面得了解源代码,为开发和部署软件新版本提供一致性空间。这个内联函数有助于编写下述特点的文件:

  • 友好,清晰
  • 最新的
  • 易于查找和使用
  • 全面、详细说明项目的各个方面。

下面将使用 Visual Paradigm 演示架构图的逆向工程;上文中从 Animal 类图生成的源代码将通过以下步骤进行逆向转换:

  1. 编辑 C++ 源代码头文件,包括附加方法 / 操作 sleep 和 sit,然后保存文件。
  2. 将保存的文件源代码导入到 Visual Paradigm 中,逆向转换为 UML 类图。

在这里插入图片描述
这是在源代码文件头中添加了 sleep 和 eat 方法

在这里插入图片描述

上图显示了使用Visual Paradigm生成的逆向UML Animal类图,源代码经过编辑,在现有方法中添加了sleep和eat两种方法。查看Visual Paradigm网站了解详情。

注意:带有关系的源代码类图也可以使用上述过程,通过Visual Paradigm生成。

有关UML类图之间关系的资源可以在线获取,了解如何在不同类图之间生成关系。

类图和状态图的结合

架构图的类图和状态图必须结合起来,才能完整地生成整个应用程序模型的代码。类图和状态图的结合,囊括了软件的静态和动态行为信息,拓宽了应用领域并覆盖了更广的使用范围。此外,两者的合作有助于处理包含多个状态图和复杂状态图的情况。

一个系统由多个状态图组成,每个状态图都显示系统类图中包含的特定对象类的行为。UML类图和状态图展示了代码生成的方法。

洗碗机系统

下面是一个洗碗机系统的架构图示例,可以展示我们的代码生成方法。下图首先是洗碗机系统的静态结构。洗碗机系统由Dishwasher(洗碗结构)、Jet (喷射结构)、Tank (水箱)和 Heater(加热器)四类组成。Dishwasher 类与 Jet、Tank 和 Heater 类有单向聚合关系。聚合表示整体/部分关系。Dishwasher 代表“整体”,Jet、Tank 和 Heater代表“部分”。Dishwasher 类有四个属性,即 cycle(周期)、rinseTime(漂洗时间)、washTime(洗涤时间)和dryTime(烘干时间),这些都是 int 类型属性。

在这里插入图片描述
下面的状态图展示了 Dishwasher 类的动态行为。它有两个顶层状态 PowerOff(关机)和PowerOn(开机)。在powerBut(电源触动)的事件发生后,这些状态相应被激活。实心圆转换到默认状态。一开始,Dishwasher 处于默认状态 PowerOff,在此状态下它接受powerBut 事件。洗碗结构对powerBut做出响应,从 PowerOff 状态切换到 PowerOn 状态。

PowerOn 状态是 Active(活跃)和 Mode(模式)两个并发区域的复合状态。一旦 PowerOn状态被激活,这些区域就会同时激活。每一个并发区域都有许多连续的子状态。在给定的时间内,只有一个连续的子状态可以转变为活跃状态。每当 PowerOn 状态变为活跃状态时,活跃区域中的 DoorClosed(门已关闭)和模式区域中的 Normal(正常)状态同时变为活跃状态,因为这是 PowerOn 复合状态中每个并发区域的默认状态。

在我们的方法中,应用程序类在单独的文件中生成。类图中所有类的实例都在应用程序类中被定义。对象实例只在应用程序类的构造方法中创建一次。其中还包含 main() 方法,这是应用程序的入口点。初始化代码也在 main() 方法中生成。包含了类图中各个类实现代码的独立文件,也在此生成。

如果没有附加到类的状态图,则生成的代码只包含类属性、与其他类关联的属性和方法标记。所附的状态图应说明类的行为信息。如果一个类有关联的状态图,那么生成的代码除了包含类属性、关联属性和方法标记之外,还应包含上下文类的行为实现。在同一个文件中,状态图的状态类代码也会相应生成。生成的代码是可执行的,并且包含应用程序模型中给定的所有信息。

在这里插入图片描述
当处于 PowerOn 状态时,在关闭或打开事件时,Dishwasher 将切换到活跃区域中的下一个连续状态。DoorClosed 的子状态是一个包含 Stop(停止), Filling(填充), Rinsing(漂洗), Washing(清洗), Draining(排水) 和 Drying(干燥)顺序的复合分层状态。当 DoorClosed 状态激活时,它的一个连续子状态也同时处于活跃状态。在 open(打开)事件中,洗碗机在活动区域切换到 DoorOpen(开门)状态。在 close(关闭)事件中,它切换到 DoorClosed 的历史状态,并调用 DoorClosed 的最后一个活跃子状态。架构图的状态图描述了对象的动态信息,现在的行为依赖于过去。实际上,状态图规定了对象在其生命周期中所经历状态的合理顺序。在历史记录状态的授权下,包含顺序子状态的复合状态可以记住转换之前处于活跃状态的最后一个子状态信息。

Tank类的动态行为在状态图表中也有详细说明,如下图所示。图中显示四个顶级状态 Empty(空置)、Fill(填充)、 Full(填满)和 Drain(排水)。每当发生 tankFill(水箱填充)、tankFull(填满)、tankDrain(排水)或 tankEmpty(空置)事件时,这些状态相应激活。最初,Tank 处于 Empty 默认状态,在此状态下它接受 tankFill 事件。Tank 相应地从 Empty 状态切换到 Fill 状态。

在这里插入图片描述
在架构图设计期间,Jet类图的动态行为在状态图中展示,如下图所示。Idle(闲置)和 Running(运行)是两个顶级状态。一开始,Jet 处于默认 Idle 状态,此时它可以接受 jetOn(启动喷射结构)事件。Jet 相应地从 Idle 状态切换到 Running 状态。Running 状态是一个包含 Spraying(洒水)和 Pulsing(冲水)两个连续的子状态的复合层级状态。在给定时间,只有一个连续的子状态变为活跃状态。每当运行状态变为活跃状态时,Spraying 状态同时变为活跃状态,正如它是复合运行状态的默认状态。在运行状态下,jetPulse 事件发生,Tank切换到下一个连续的 Pulsing 子状态。在 jetOff 事件中,Jet 会切换回 Idle 状态。

在这里插入图片描述
在这里插入图片描述
在架构图设计期间,Heater类图的动态行为在状态图中展示,如上所示。它有两个顶级状态,Off(关)和 On(开)。最初,加热器处于默认关闭状态,在此状态下它接受 HeaterOn 事件,加热器相应地从 Off 状态切换到 On。在HeaterOff 事件中,切换回 Off 状态。

代码生成工具概述

以下将通过上述洗碗机系统图来演示 C++ 的架构图 UML 代码生成方法。Visual Paradigm 工具系统分为三个主要模块,即类图模块、状态图模块和代码生成模块。以下是每个模块的简要说明。

类图模块

下面显示的dishwasher类头文件的源代码是 Visual Paradigm 生成的。如上面的dishwasher状态图所示,它包括与dishwasher类有关系的所有其他类的声明。其他类也有各自的头文件,同样由 Visual Paradigm 生成。

在这里插入图片描述
类图模块读取类图的规范,标识类图的各种组件,并将此存储在类表中。DSL(领域专用语言)中的节点表示类。所有关于类的信息,包括类的名称、属性和方法头都被存储。DSL 中的弧线表示类之间的关系。与关系相关的所有信息也存储在表中,然后类图模块处理类表并提取状态图 DSL 文件名,将此信息传递给状态图模块以处理关联的状态图。更多内容,请参考 DSL 维基百科。

状态图模块

架构图的状态图模块从类图模块接收状态图 DSL 文件名,读取对应输入的状态图 DSL 文件,将状态图信息记录到状态表中,从而将 DSL 格式的信息转换为表格形式。

状态图模块继而处理状态表,并从状态表中删除伪状态(初始、历史、分叉和联接等)的信息,并更新表格。

状态图模块将转换后的状态表返回给类图模块。状态表与相应类的其他信息一起存储在表中。

代码生成模块

在架构图的代码生成模块中,工具从类和状态表中获取信息,运用建议的代码生成方法,生成整个应用模型的 C++ 代码。

在我们的方法中,使用 main() 方法生成一个应用程序类,该方法充当整个系统的入口点。对于洗碗机系统,如图 3.1 所示,将生成主要应用类洗碗机。类的名称根据输入类图 DSL 文件中指定的项目名称派生。该类图中所有类的实例已进行初始化,应用程序对象是在 main() 方法中创建和初始化的。

在这里插入图片描述

类图中的类

架构图类图中的所有类都被转换成 C++ 代码。类图中的每个类,都将生成扩展名为(.cpp)的单独文件和扩展名为(.h)的头文件。生成的代码包含名称、属性和方法的所有类定义。类之间的关系被识别并转换成代码。为了实现类之间的关联,在相应的类中生成公共可用的引用属性。如果关联是双向的,则在两个类中生成引用属性;如果关联是单向的,则引用属性仅在源类中生成。

结论

为了实现我们开发架构图的目的,我们提出了一种面向对象的方法来将 UML 类图转换为实现代码。这种方法帮助整个应用程序模型生成简洁高效的可执行代码。生成的代码包含应用程序模型中所有类的静态结构代码和动态行为代码。

该方法已经在我们的示例中实现,使用 Visual Paradigm,自动将 UML 类图说明转换为 C++ 源代码。

我们的方法是面向对象的,在本次研究中,我们使用了 C++ 作为架构图的目标语言。不过,我们的方法也是通用的,因此可以应用于其他面向对象语言,生成相应的低级代码。代码生成机制必须根据目标语言进行定制,因为某些功能在不同的编程语言(面向对象)中的实现方式不同。

点击了解 Incredibuild 加速 C++ 的 CI 构建编译的解决方案,并获取试用 License!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1546374.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何统计代码量

工具: cloc 下载地址: Releases AlDanial/cloc GitHub 使用方法:

2024.3.26

实现闹钟 weiget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTimer> #include<QTime> #include<QTimerEvent> #include<QString> #include<QtTextToSpeech> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } Q…

力扣● 503.下一个更大元素II ● 42. 接雨水

503.下一个更大元素II 与496.下一个更大元素 I的不同是要循环地搜索元素的下一个更大的数。那么主要是对于遍历结束后&#xff0c;单调栈里面剩下的那些元素。 如果直接把两个数组拼接在一起&#xff0c;然后使用单调栈求下一个最大值就可以。 代码实现的话&#xff0c;不用直…

ubuntu22.04配置Azure Kinect DK深度相机

一.安装SDK 今天我来配置一下微软公司的Azure Kinect DK深度相机,以前在ubuntu18.04上配置过,因为官方说唯一支持linux版本是18.04,所以在18.04中配置还算顺利 but这不代表不可以在更高版本的ubuntu中使用,只不过需要自己去多配置一些东西 apt 源安装 更新源: c…

上海企业必应bing国内广告推广如何开户?

随着数字化营销时代的深入发展&#xff0c;搜索引擎广告已成为众多企业提升品牌知名度和促进产品销售的重要手段之一。在国内市场&#xff0c;微软必应&#xff08;Bing&#xff09;搜索广告以其精准定位与高价值用户群赢得了众多企业的青睐。对于位于上海地区的企业来说&#…

蓝桥杯:Python基础学习一

目录 一、遍历列表 1.使用for 循环和 enumerate()函数实现 2.案例代码 二、对列表进行统计和计算 1.统计数值列表的元素和 2.案例代码 三、对列表进行排序 1.使用列表对象的sort()方法 2.使用内置的 sorted()函数实现 四、列表推导式 1.从列表中选择符合条件的元素组…

flask_restful结合蓝图使用

在蓝图中&#xff0c;如果使用 Flask_RESTful &#xff0c; 创建 Api 对象的时候&#xff0c;传入蓝图对象即可&#xff0c;不再是传入 app 对象 /user/__init__.py from flask.blueprints import Blueprintuser_bp Blueprint(user,__name__)from user import views /user…

泛型编程的启蒙之旅

个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C/C小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 讲模板之前呢&#xff0c;我们先来谈谈泛型编程&#xff1a; 泛型编程&#xff1a;编写与类…

Linux——命名管道

Linux——命名管道 命名管道命名管道和匿名管道的区别 创建命名管道利用命名管道实现简单通信 我们之前学习了匿名管道&#xff0c;这种管道有一个缺点就是只有两个有血缘关系的进程才能够使用匿名管道&#xff0c;这个非常不方便。所以我们又在匿名管道的基础之上引入了命名管…

Linux实现m4a格式转换为wav格式

需要在linux上安装ffmpeg 参考博客 Linux上安装ffmpeg修改环境变量【这一点很重要&#xff0c;自己因为没有添加环境变量&#xff0c;捣鼓了很长时间】 将ffmpeg的绝对路径添加到 PATH 环境变量中&#xff0c;以让系统能找到ffmpeg的安装路径。 # /home//project/ffmpeg-6.1-a…

QT作业day3

1、使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是…

vue3+threejs新手从零开发卡牌游戏(八):关联卡组和手牌区、添加初始化卡组和初始化手牌逻辑

首先我们优化下之前的代码&#xff0c;先加载游戏资源&#xff0c;然后再初始化场景&#xff0c;由于目前只有一个font字体需要加载&#xff0c;所以我们将之前game/deck/p1.vue中的font相关代码迁移到game/index.vue下&#xff0c;同时使用async和await处理异步加载&#xff0…

干货分享之反射笔记

入门级笔记-反射 一、利用反射破泛型集合二、Student类三、获取构造器的演示和使用1.getConstructors只能获取当前运行时类的被public修饰的构造器2.getDeclaredConstructors:获取运行时类的全部修饰符的构造器3.获取指定的构造器3.1得到空构造器3.2得到两个参数的有参构造器&a…

基于java+springboot+vue实现的超市管理系统(文末源码+Lw+ppt)23-354

摘 要 系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对超市管理的现状进行系统调查。采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”…

启扬RK3568核心板助力智慧步道轻装健身,打造全民健康生活新方式

随着物联网、AI智能等新技术的快速发展&#xff0c;智慧步道成为全国各地公园建设和全民健身公共服务设施改造的新主题。智慧步道基于物联网、人脸识别、大数据分析等技术&#xff0c;对人们的运动进行监测和数据采集&#xff0c;显示运动数据&#xff0c;包括里程统计、热量消…

【王道训练营】第6题 输入一个整型数,判断是否是对称数,如果是,输出yes,否则输出no

文章目录 我的代码改正代码其他代码 我的代码 没有完成 #include<stdio.h> int main(){int a;int b;int c0;//位数int d0;//比较几次scanf("%d",&a);while(b!0){bb/10;c;}dc/2;//比较几次int ffor(int i0 ;i<d;i){int ec;//位数fa - a / (((e-i-1)*10…

2024年软件测试,“我“从初级到高级进阶,不再走弯路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 现在2024年&#…

Python算法100例-4.2 列出真分数序列

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.拓展训练 1&#xff0e;问题描述 按递增顺序依次列出所有分母为40、分子小于40的最简分数。 2&#xff0e;问题分析 分子和分母只有公因数1的分数&…

Maven发布开源框架到远程仓库

1.背景 当你写了一个自我感觉良好的开源工具希望给他人分享&#xff0c;如果只是在github等网站进行公布之外&#xff0c;用户使用起来还不是很方便&#xff0c;特别是当你提供是特定领域的基础工具。你还可以把它部署到中央仓库&#xff0c;这样别人使用就会方便很多。接下来…

android_uiautomator元素定位

通过UIAUTOMATOR的text属性定位到元素&#xff0c;并打印文本from appium import webdriver from appium.webdriver.common.appiumby import AppiumBy import time # For W3C actions from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriv…