一种基于软件依赖关系提取的多层架构识别方法

文档序号:26902120发布日期:2021-10-09 13:25阅读:76来源:国知局
一种基于软件依赖关系提取的多层架构识别方法

1.本发明属于软件维护中与框架反演和框架识别相关的技术领域,涉及一种基于软件依赖关系 提取的多层架构识别方法。


背景技术:

2.多层架构在企业级开发中应用广泛,其在结构上对程序中的实体进行了层次划分,不同的层 次具有不同的职责,协同完成系统某个功能的子操作,多层架构模式便于开发人员对软件系统 的理解,不仅方便开发还提高了系统的可维护性。
3.软件演化过程中,系统架构无法确保按照预定计划被构建,可能出现架构偏移或者违背系统 的约束和规则等情况,这种现象正是源于开发过程中对软件频繁的修改。开发人员不能及时对 这种偏差进行检测和干预,导致系统不断偏离设计目标、可维护性变差,甚至影响软件质量。 为了应对这种风险,通常需要对迭代频繁的系统进行架构恢复。
4.架构识别是软件架构恢复的关键步骤,可以通过分析目标系统的源代码,得到目标系统架构 层面的抽象表示,在多层架构中,通过层次划分中形成的描述实体分布和依赖轨迹的图像,开 发人员可以加深对当前系统的理解,找到演化过程中发生架构偏移和违反架构原则等问题的关 键结点。


技术实现要素:

5.本发明的目的是提供一种基于软件依赖关系提取的多层架构识别方法,目标是获取目标系统架 构级别的抽象表示,该视图包含各个层次及其内部的程序实体,不同层次内的实体之间的依赖 关系。本方法对于软件层次的划分具有较高的准确度,可用于提高框架反演中架构识别过程的 效率,并且辅助进行代码重构。该方案首先使用软件依赖关系提取程序对静态的软件源码进行 处理并获取用于层次划分的信息,例如获取源码中存在的所有的类的类名、类的路径和类之间 的依赖关系;根据第一步得出的信息统计出每个类的扇入值和扇出值等参考值;以上面获得的 数据为依据对软件的层次进行划分,具体是将源码中的实体初步划分到三个基本的层次中,包 括顶层、中间层和底层,随后利用分层架构的规则对初步划分结果进行调整。使用聚类算法对 中间层次中的类进一步划分,其中聚类算法的依据采用的是实体的结构相似度,具体考察类中 的注解、继承关系和接口实现关系,根据层次划分结果可以对软件中的依赖关系进行清晰的展 示,有助于代码审查和架构偏移关键点的定位。
6.为了实现上述目的,本发明的技术方案如下,一种基于软件依赖关系提取过程的多层架构 的识别方法,所述方法包括以下步骤:
7.步骤1:目标系统源码预处理,
8.步骤2:目标系统依赖信息提取,
9.步骤3:目标系统层次划分。
10.其中,所述步骤1:目标系统源码预处理,具体如下:
11.11)对非源码形式的目标系统的编译产物进行反编译,将输入形式统一为静态源码;
12.12)剔除系统中没有内容或被注释的类;
13.13)将系统中存在接口实现关系或继承关系的多个类进行绑定,参与层次划分时可将其作为 一个实体看待,缩小识别对象的规模。
14.其中,步骤2:目标系统依赖信息提取,具体如下:
15.21)提取预处理后每个类文件中的标识符信息,包括类名、属性名、方法名、方法形参名和 注解名,构成一个标识符信息表,每个类的标识符信息是其中的一条记录;
16.22)扫描标识符列表,提取出可用来初步划分层次的依赖信息,每条依赖信息包括:类名、 该类所在的路径(目录结构)、类所依赖的其他自定义类名,形成依赖信息表;
17.23)根据依赖信息表可以构建出若干条目标系统中的依赖路径,将源码中不在任何一条路径 上的类剔除,可认为其不是分层架构的组成部分。
18.其中,步骤3:目标系统层次划分,具体如下,
19.31)根据依赖信息表,计算出每个实体的扇入值fanin和扇出值fanout,其中fanin是系 统中依赖当前结点的结点个数,fanout是当前结点所依赖的系统中其他结点的个数;
20.32)以扇入扇出值为依据,按照规则进行目标系统的初步划分,三条规则如下所列:
21.满足fanin=0且fanout>0的结点划分到顶层;
22.满足fanin≠0且fanout≠0的结点划分到中间层;
23.满足fanin>0且fanout=0的结点划分到底层;
24.33)对初步划分结果中可能存在的“跨层依赖”现象,定义消除规则,然后根据规则对相关 结点进行调整,规则如下所示:
25.若某顶层结点跨层依赖底层结点的同时还保持对中间层某结点的依赖,并且该底层结点 没有被中间层依赖,就将底层结点上移到中间层;
26.若某顶层结点跨层依赖底层结点的同时不依赖中间层结点,并且该底层结点被中间层依 赖,就将顶层结点下移到中间层;
27.若某顶层结点跨层依赖底层结点的同时还依赖中间层结点,被该顶层结点依赖的底层结 点同时也被中间层结点依赖,就比较顶层结点到中间层的扇出值和底层结点到中间层结 点的扇入值,值小的一方移动到中间层;
28.若某顶层结点跨层依赖底层结点,同时顶层、底层结点同中间层都没有依赖关系,则顶 层结点或底层结点移动到中间层都可以;
29.34)对中间层的结点采用聚类算法进行进一步划分,聚类依据为实体结构相似度,其中使用 结构相似度的依据是同层次实体实现类似的功能并且对相邻的需要使用其功能的层次提供 统一的接口,这里主要考察其代码结构中的注解、继承的父类和实现的接口具有的相似性;
30.35)结合中间层聚类结果可得目标系统整体的分层状态,可以绘制分层架构图,图中展现了所划分 的层次及其包含的实体,各层实体之间的依赖路径信息
31.有益效果:本发明通过对目标系统的源码进行信息提取和分析,获得目标系统的真实架构, 本发明与现有技术相比,主要优点有:
32.(1)本发明提出的基于软件依赖关系提取的多层架构的识别方法,较以往的方法增加了预 处理的步骤,包括输入形式的统一和对源码中干扰项的过滤,提高了识别的效率。
33.(2)本发明基于多层架构的发展规律,提出初步划分和中间层进一步划分的流程,降低了 以往方法整体划分的复杂度,提高了可行性。
34.(3)设计了针对初步识别结果的优化过程,具体是引入分层架构的设计思想,消除可能出 现的跨层依赖,降低软件维护人员对识别结果的理解难度。
35.(4)本发明的识别方法在进一步划分层次时,考虑了不同层次实体之间多个相关结构的相 似度,并且最终生成的架构层次图可以用来加深对目标系统的理解,辅助对架构偏移点的定位。
附图说明
36.图1为本发明框架示意图;
37.图2为预处理过程示意图;
38.图3依赖信息提取过程示意图;
39.图4为最佳k值选取示意图;
40.图5为层次划分流程示意图;
41.图6为基础三层实例;
42.图7为层次聚类树;
43.图8表示k为2时子树的情况示意图;
44.图9表示k为3时子树的情况示意图。
具体实施方式
45.为了加深对本发明的认识和理解,下面结合附图和实施例进一步介绍该发明。
46.实施例:一种基于软件依赖关系提取过程的多层架构的识别方法,所述方法包括以下步骤:: 步骤1:目标系统源码预处理:
47.(1)预处理的目的是缩小识别对象的规模,降低信息提取过程中扫描源码的开销,具体包括:
48.a)对非源码形式的目标系统的编译产物进行反编译,将输入形式统一为静态源码;
49.b)剔除系统中没有内容或被注释的类;
50.c)将系统中存在接口实现关系或继承关系的多个类进行绑定,参与层次划分时可将其作为 一个实体看待,缩小识别对象的规模。
51.(2)具体步骤:
52.本方法所识别的对象是目标系统的静态工程源码,在实际生产过程中,可能存在通过系统编译 产物进行识别的需求,因此在预处理阶段增加反编译的支持。
53.检查目标系统源码,对于没有实际作用的实体可以进行删除,对于存在实现或继承关系的实体,记 录其相关性,并选取一个具有代表性的实体参与信息提取过程,源码预处理过程如图2所示。
54.步骤2:目标系统依赖信息提取:
55.(1)目的:依赖信息提取的目的是获取进行层次划分的“原材料”,首先扫描源码获取词汇文本信 息,然后从中提取出依赖关系信息,并根据依赖关系表计算出相关参考值。
56.(2)具体步骤(如图3所示):
57.d)实施过程中首先使用开源的java集成开发工具eclipse相关的jdt库中提供的一套关于解 析java代码,生成、分析和操作ast(abstract syntax tree)结构的api编写程序(即 形成依赖关系提取工具),获取一个java项目源代码中所有类的基本信息(包括类名、包 名、属性名、方法名等),将提取出的全部实体及其标识符信息构成标识符信息表,每个实 体的标识符信息作为其中的一条记录;
58.e)扫描标识符信息表,筛选出可用于层次初步划分的基本依赖信息,每条依赖信息具体包 括:当前类名、当前类所在路径(目录结构)、当前类所依赖的类名,存储这些数据并 构建成依赖信息表;
59.f)根据依赖信息表可以找出若干条目标系统中的依赖路径,记录每条路径及其上所包含的 实体,将不在任何一条路径上的实体剔除,可认为其不是分层架构的组成部分,例如在 使用springboot框架时经常使用的配置类,配置类被用来替代配置文件,而不处理具 体的业务逻辑,对于软件架构层次划分无益且会增加划分复杂度。将筛选好的结果保存 到数据库。
60.步骤3:目标系统层次划分:
61.(1)目的:层次划分的目的是充分使用上述工作的成果,结合分层架构的相关原则,划分出较 为准确的软件层次。
62.(2)多层架构背景
63.三层架构是多层架构中最典型的例子,从顶层到底层依次是表示层、应用层和数据层,表示 层是用户可以直接访问和交互的层次,应用层封装了业务逻辑,例如业务运算的规则和数据验 证,数据层用来存取应用程序数据的外部数据源。根据三层架构中相邻层次之间的耦合度和功 能特性,还可以在三层基础上划分出更多层次。
64.(3)具体步骤:
65.g)根据依赖信息表,计算出每个实体的扇入值fanin和扇出值fanout,其中fanin是系统 中依赖当前结点的结点个数,fanout是当前结点所依赖的系统中其他结点的个数;
66.h)以计算得到的扇入、扇出值为依据,按照预定的规则进行目标系统的初步划分。在实际 开发中需要注意的是,处于系统底层的实体可能还会依赖例如datasource等api,而这 些第三方实体不是属于当前系统内的,不能参与当前目标系统的分层架构组成,因此在 标识符信息表中需要区分自定义实体、jdk提供的实体和第三方实体,架构识别聚焦于 自定义实体(编码时手动创建的类)。预定的三条规则如下:
67.i.满足fanin=0且fanout>0的结点划分到顶层;
68.ii.满足fanin≠0且fanout≠0的结点划分到中间层;
69.iii.满足fanin>0且fanout=0的结点划分到底层;
70.i)在分层架构中,可能会存在“跨层依赖”现象,由于在分层架构的思想中每层应该只与 其相邻的两层有感知,其他不相邻的层次应该是透明的,因此对于结点间存在的跨层依 赖,在划分基础三层时定义了消除规则,这样做丰富了中间层结点且尽量降低初步划
分 的误差,然后根据规则对相关结点进行调整,规则如下所示:
71.i.若顶层结点除跨层依赖底层结点外还保持对中间层某结点的依赖,同时该底层结点 没有被中间层依赖,就将底层结点上移到中间层;
72.ii.若顶层结点除跨层次依赖底层结点外不依赖中间层结点,同时该底层结点被中间层 结点依赖,就将顶层结点下移到中间层;
73.iii.若顶层结点跨层依赖底层结点的同时还依赖中间层结点,被该顶层结点依赖的底层 结点同时也被中间层结点依赖,就比较顶层结点到中间层的扇出值和底层结点到中 间层结点的扇入值,值小的一方移动到中间层;
74.iv.若顶层结点跨层依赖底层结点,同时顶层、底层结点同中间层都没有依赖关系,则 移动顶层和底层结点中任一至中间层。
75.j)对中间层的结点采用聚类算法进行进一步划分。
76.i.聚类算法选取:
77.这里主要使用了k

means聚类算法,该算法需要事先指定划分个数,随机选取一个 对象作为一组的中心,根据其他对象到各组中心的距离将其分配到最近组,一直迭代使 得同组内的对象尽可能接近,不同组对象尽可能远离。
78.ii.k值选取:
79.由于在基于源码的架构恢复中无法直接指定划分个数,需要采用动态选取k值。虽 然无法直接得到具体k值大小,但可以得到k值存在的数值范围:对于k值上限k
max
,可 通过在架构信息提取过程中构建的多条依赖路径中找到最长的路径,去掉顶层和底层结 点后剩余结点数获得,k值下限k
min
为1(基于三层架构)。
80.iii.聚类依据选取与处理:
81.聚类过程的依据主要是实体之间结构的相似度,考察的结构包括实体的注解(包含 类级别的注解和方法级别的注解)、实体继承的父类和实体实现的接口。考虑结构元素 的依据是同层次实体实现类似的功能或作用,其代码结构中的注解类型、继承的父类和 实现的接口等具有相似性。
82.iv.聚类过程:
83.1.获取各实体的结构特征信息,包括注解、父类和接口;
84.2.将结构特征采用特定规则进行数值化,方便参与运算:
85.a)对每种结构构造其集合,并统计集合中每种元素的出现频次,例如注解集合 anno中包含实体中出现的所有不同注解,统计每种注解被多少个实体使用。
86.b)使用二进制数表示每个实体的某个结构的数值。例如对于a类的注解,使用 一个n位的二进制数(n为注解集合anno的大小),将anno中的注解按照 频次的大小降序排列,同频次的按照字母表升序排列,对应到二进制数从高 位到低位的每一位,该位表示的注解在类a中存在就为1,反之为0(对于 一个二进制数,其高位转为十进制时表示的数值更大,而高位用来表示出现 次数较多的注解,可以用来模拟出具有相同的注解越多,则两个不同实体在 注解方面越相似)。其他两种结构也进行同样的处理。
87.c)使用三维的点(注解值,继承值,接口值)来代表实体参与聚类过程。
88.3.进行层次聚类过程,每轮计算出距离最短的两个点,然后合并这两个点参与到 下一轮的计算,直到所有结点都合并完毕,由此得到层次聚类树状图。具体步 骤如下:
89.a)计算任意两个点之间的距离,取其中距离最短的两个点加入集合s
k
,k∈ (1,n),n为层次聚类过程的轮数,
90.b)计算集合s
k
的代表点(这里采用的是central法),即计算出a)中两个点的 中点,
91.c)用该中点替代s
k
中的点,
92.d)重复以上步骤
93.4.进行k

means聚类过程,该过程需要借助之前计算的k值的数值范围,以及层 次聚类树状图。一共要进行k
max

k
min
次k

means聚类过程,其中每次k

means 过程如下:
94.a)按照当前k值在层次聚类树状图中切出k个子树,计算出每个子树的中心点 (即每个类别的初始质心),然后计算每个点到各中心点的距离,将该点划 分到该中心点所在的一组点中;
95.b)划分完毕后,再次计算出每个组中的中心点,作为新的中心;
96.c)重复以上过程,直到新的中心与原中心重合。
97.5.所有的k

means聚类过程结束后,计算误差平方和sse(sum of the squared errors):
[0098][0099]
其中c
i
是第i个簇,p是c
i
中的样本点,m
i
是c
i
的质心(c
i
中所有样本的均值), sse是所有样本的聚类误差,代表聚类效果的好坏。随着划分个数k的增大,样 本划分更加精细,每个簇的聚合程度会逐渐提高,sse会逐渐变小。当k小于真 实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故sse的下降幅度 会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报变小,故sse的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,最终sse和k的 关系图呈现手肘的形状,而肘部对应的k值就是数据的真实聚类数,如图4。
[0100]
k)结合中间层聚类结果可得目标系统整体的分层状态,流程如图5所示,可以绘制分层架 构图,用来展现所划分的层次及其包含的实体,各层实体之间的依赖路径等信息。
[0101]
具体实施例:
[0102]
为了方便对本架构识别方法加深理解,我们假定有如下的简化实施案例:
[0103]
对目标系统已经完成了预处理过程,预处理后的目标系统统一为源码形式并且源码集合中已 经剔除了与层次划分不相关的类或实体,编写语法分析程序提取出了源码中的依赖关系,生成 的依赖信息如表1所示。
[0104]
表1依赖信息示例
[0105]
类名类的路径依赖的类controller1com.demo.controllerservice1、service3controller2com.demo.controllerservice2、dao3service1com.demo.serviceservice2、dao1service2com.demo.serviceservice3、dao1、dao2service3com.demo.servicedao2dao1com.demo.dao无
dao2com.demo.dao无dao3com.demo.dao无
[0106]
(1)得到依赖信息后,首先对每个类进行扇入、扇出值的统计:
[0107]
controller1:0,2
[0108]
controller2:0,2
[0109]
service1:1,2
[0110]
service2:2,3
[0111]
service3:1,1
[0112]
dao1:2,0
[0113]
dao2:2,0
[0114]
dao3:1,0
[0115]
(2)按照基础三层划分策略及跨层调整规则可得:
[0116]
顶层:controller1、controller2
[0117]
中间层:service1、service2、service3、dao3
[0118]
底层:dao1、dao2
[0119]
(3)中间层进一步划分准备工作:
[0120]
根据依赖关系画出依赖图可以获得多条依赖路径如图6,由图6统计可得聚类算法k值 的取值范围,即k∈{1,2,3}。
[0121]
获取中间层各实体结构信息如表2,可得各结构信息集合(其中集合元素已按规则排序):
[0122]
表2结构信息示例
[0123][0124]
注解集合anno={anno1,anno2,anno3},
[0125]
继承集合extends={extends1,extends2},
[0126]
接口集合interface={interface1,interface2,interface3}。
[0127]
根据以上信息将实体表示成三维点参与运算:
[0128]
service1(4,2,4),
[0129]
service2(4,2,6),
[0130]
service3(6,2,4),
[0131]
dao3(1,1,1)
[0132]
(4)计算各点间距离,这里采用欧氏距离,即点x=(x1,...,x
n
)和y=(y1,...,y
n
)之间的距离 为:
[0133][0134]
得到结果如表3所示。
[0135]
表3初始各点间距离(对称部分的数据省略)
[0136][0137][0138]
(5)层次聚类过程(为减少计算量,这里不用central法,而是选择single法,即用集合 s
k
中到目标点最近的点替代集合s
k
参与下一轮计算),生成的层次聚类树如图7所示。
[0139]
s1={service1,service2},
[0140]
s2={s1,service3},
[0141]
s3={s2,dao3}。
[0142]
(6)k

means聚类过程
[0143]
k取1时,经计算最终中心点o(15/4,7/4,15/4);
[0144]
k取2时,经计算最终中心点o1(14/3,2,14/3),o2(1,1,1),此时的子树情况 如图8,其中的点在距离计算和比较过程中没有移动到别的簇的情况;
[0145]
k取3时,经计算最终中心点o1(4,2,5),o2(6,2,4),o3(1,1,1),此时的子 树情况如图9,未发生点的移动。
[0146]
(7)分别计算不同k值的误差平方和,绘制折线图,找到最佳k值为2。以k为2为例, 此时存在两个簇及其中心点,计算每个簇中各点到中心点的距离,取所有距离的平方 和作为sse
(k=2)
的值,k为1和3时同理,最终绘制出关于k和sse的折线图,位于手 肘部位置的点即为最佳k值。
[0147]
(8)假设上一步得出k值为2,此时可将中间层分为两层,每层中包含相应的结点,最终 同顶层和底层构成目标系统的层次。
[0148]
以上仅是本发明的优选实施方式,应当指出:对于本技术领域的普通技术人员来说,在不脱离 本发明原理的前提下,还可以做出若干改进和等同替换,这些对本发明权利要求进行改进和等 同替换后的技术方案,均落入本发明的保护范围。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1