Qt Group是一家全球软件公司,在70多个行业中拥有强大影响力,是支撑超过十亿设备和应用的领先独立技术公司。
Qt Group中国资深解决方案工程师张帆拥有多年软件质量保证和软件测试工作经验,专注于Qt Group QA产品线的一体化测试解决方案。2024年3月12日,在2024第五届软件定义汽车论坛暨AUTOSAR中国日上,他谈到,架构验证工作可以在软件开发初期便启动,确保随着项目的推进,代码实现始终与既定架构保持一致。这样的做法不仅有助于我们在决策过程中把握方向,还为新加入的开发人员提供了重要的学习依据,使得架构文档成为一项至关重要的资源。
张 帆 | Qt Group中国资深解决方案工程师
以下为演讲内容整理:
为什么架构和代码需要匹配?
在工作中为什么需要架构?它是哪些事情的基础?这是比较基础的问题。软件当中首先我们要做的设计和实现都是围绕架构的,我们都知道进行架构设计是开始软件项目的基础。在新的开发人员到来的时候,怎么样让新进入项目的人员快速上手,加入我们的项目。
此外,我们在日常开发中也会有软件方面的调整和计划全局的大调整,架构在这些规划上面都会给我们带来很大的帮助。对于这些事情,如果架构和代码匹配完全一致,就给我们一种可能性,那就是我们不需要通过阅读代码来完成上述的事情。通过看架构,可以让新开发人员快速上手,进行日常开发中的调整,或者计划大的软件事项开发。
再来看一个简单的例子,这也是我们的客户在实际开发过程中碰到的情况。这是非常简单的架构,有三个模块,C模块是软件里的硬件抽象层,会在硬件的生成上读取到当前的环境温度,并且把此温度传给B模块(后台数据处理的模块),B模块把这些数据进行处理之后会传给A模块(用户展示模块)。通过这样简单的架构,就完成了从生成读取数据到最终在用户界面向用户展示的过程。有了此架构之后,开发人员就可以进行编码。
图源:Qt Group
出于某些原因,A模块的开发者没有像架构设计者一样从B模块读取环境的数据,而是直接从C模块底层拿到数据,在某些情况下这种情况就会出现,比如B模块的开发并未完成,A模块的开发者为了尽快的让自己的模块写好,可能会绕过B模块获取数据。也有可能开发者觉得直接从底层获取数据更好,就会从C模块直接获取,它给软件会带来什么影响呢?目前其实是没有影响的,但实际上这是一种架构的违反,它会给软件质量在长期上造成影响,因此将软件架构和代码进行统一是非常有必要的。
软件架构验证的要素
如果要通过这样的架构验证需要哪些要素?总共需要三个要素,首先,需要架构的模型。其次,源代码这些实体之间的依赖关系是什么样的。最后,把源代码当中的依赖关系和架构模型进行映射,在映射之后进行比对,就会知道源代码实现是否符合架构设计。
首先,第一个要素是架构模型。这里指的架构实际上是静态软件架构,它包括一些组件,比如函数和全局变量等,并且在组件之间的依赖关系也是架构的重要部分。它是由三个模块组成的,分别是Environment、Controller和Plant,这也是非常简单的一个架构,他们之间的依赖关系就是Environment会调用Controller,Controller和Plant会互相调用。
在架构模型中,模型可以用不同的形式表示,很多公司都会用word文档来记载架构,也有一些公司会用Python脚本描述,或者我们可以用Case工具中的UML来进行架构描述,以及可以在一些应用里面描述,比如我们Qt的Axivion会提供Group工具,在这样的工具里进行架构的模型绘制。此架构模型的理念是解释原始架构模型,这样就可以把它转化成一个可验证的结构。
第二个要素是源代码中依赖关系的表示。我们Axivion的架构验证工具是有编辑器的技术背景,用编辑器的技术把源代码编译为中间的表示形式,编译成中间表示形式之后,把形式可视化就可以得到右边这张图。右边图上可以看到有非常多的元素,比如有城市的方块,它是表示一个功能,黄色的六边形表示全局变量,还有蓝色的三角形、正方形表现Class之类的实体。
图源:Qt Group
我们这里的理念是可以把源代码中的依赖关系抽象出来,这样的架构图是源代码表示的抽象。实际上刚才的图有过多的元素,阅读非常困难,如果是一个大型的项目,这个图抽象出来会是非常复杂的网状结构,我们去读就会非常困难,就可以使用一些分层视图的方式通过一些隐藏元素,把这些源代码的视图变得更加可读。
当有了源代码视图和架构视图之后,还要把源代码元素映射到架构元素上。这里有一个重要的原则是一个源代码元素应该只映射到一个架构元素上,这样就方便对源代码进行比对。这里我们就可以把Environment下的所有元素和架构视图上的Environment进行关联,同样Controller和Plant也可以进行对应的关联。
要进行架构验证大致可以按照两步进行,当我们有了上述三种元素,首先可以考虑把源代码模型中的依赖关系和架构模型上的依赖关系进行比对,这样比对下来结果会有代码实现符合架构设计和代码实现不符合架构实现这两种结果。比较完之后,架构模型中还会有一些剩余的依赖关系,这些依赖关系只存在于架构模型,而不存在于源代码模型中。
这样我们也认为它是有问题的,架构模型中需要实现的依赖关系在源码里面有了缺失,就要把它归入Absence类型,所以我们一共是有三种预期结果。最理想的情况下,当代码实现和架构设计一致的话,那么所有的架构模型中的依赖关系都在源码中能够找到,并且没有额外的关系,所有的线条都会展示为绿色的结果。
但在实际的初始架构验证中,源代码模型没有跨包的依赖关系,没有将架构依赖关系标记为可选的,所有的依赖关系都导致确实。这里就给我们造成一个问题,问题的原因是依赖关系只存在于RTE代码之间的间接关系,而不是直接在SWC之间。
AUTOSAR项目都是有ARXML模型的,那么就可以从ARXML模型里把隐藏的依赖关系导入到架构验证的项目中,并且利用这种关系丰富原来的源代码视图,把这种隐藏的依赖关系也在模块之间体现。通过RTE进行的Sender/Receiver通信就可以在源代码通过定义进行查找,查找之后就可以定位到具体的地方。有了定位之后,源代码模型就可以自动扩展为RTE的源代码视图。
架构验证
在丰富源代码视图之后,进行架构验证。首先,把三个模块和架构视图里的三个模块进行关联,关联之后可以看到Plant和Controller之间的调用,从Plant里的RTEIringt Plant到Controller里的RTEIreder colour的调用,是符合我们在架构图中的调用。所以结果上面就会显示为绿色,同样在Controller到Plant的调用也是绿色,而最终在Environment到Plant的调用实际上它在架构视图中是没有这样的依赖关系的,所以它会标示为红色。
图源:Qt Group
最后在架构视图中还有Environment到Controller的调用,它在源码中是没有的,因此最后会标示为橙色的虚线的箭头。有了这样的一些架构违规的问题列表之后,后续就可以考虑如何处理。
要处理刚才出现的结果首先可以展开源代码的文件夹,包括Environment和Plant的文件夹,在展开之后就能看到具体的红色违规是在哪两个实体之间出现,找到实体之后一共有三种处理办法。首先,很容易想到的是直接修改源码,让源码符合架构设计,把调用关系改成Environment到Controller的调用,或者是经过Review发现调用实际上是一个正确的调用,那就需要修改架构来让它匹配代码实现。
此外,还有第三种解决方式是经过Review觉得这是个问题,但是出于一些原因没有办法马上修复它,我们就可以临时接受调用,作为一个临时的解决方案,在将来时机成熟的时候再进行修复,包括修改架构图或者修改源码。最后通过Axivion也可以把架构验证整合到日常工作中,具体的架构违规列表包括了Absence和Divergence这两种类型的架构违规,违规的具体位置我们也会在源码当中进行展示。同样在具体的问题展示页面,在页边会有模块之间调用的提示。
架构验证是可以在开发早期进行,这样随着软件项目的进行代码实现就一直是和架构统一的,因此在做很多事情的决定或者是有新的开发人员进来学习的时候,就可以用架构做一个非常重要的文档。架构验证不仅支持直接的C和C++的依赖关系,也可以支持中间键通信。
Qt的Axivion—架构验证和静态代码分析成立于2006年,有超过15年的历史,最早它是源于德国斯图加特大学的一个研究项目,因此它现在的开发团队在德国,但是我们在很多国家都有本地的团队提供技术支持与服务。
我们的客户在全球范围内超过200个,有1万个用户,这些客户也来自于各行各业,包括汽车、医疗、工业自动化、航空航天等行业,我们也支持帮助客户完成质量体系认证,包括汽车行业的26262,还有医疗、航空航天等行业的标准,目前Axivion是Qt Group的一部分。
在整个开发过程中,QA的工具流的使用有很多,在架构设计和编码阶段,我们可以用Axivion进行架构验证和代码扫描,从长期上保证软件质量的控制。在构建和测试阶段,可以用Coco来进行代码覆盖率分析以及用Squish进行UI的界面自动化测试,最后结果可以在Axivion提供的Dashboard和Report中进行展示,或者通过Test Center进行展示。
(以上内容来自Qt Group中国资深解决方案工程师张帆于2024年3月12-14日在2024第五届软件定义汽车论坛暨AUTOSAR中国日发表的《经典AUTOSAR项目中的软件架构验证》主题演讲。)
领取专属 10元无门槛券
私享最新 技术干货