Python脚本支持OC代码重构实践:模块调用关系分析( 三 )

到这了一步,公开可访问的数据项及类型的提取就已级完成,这时就可以转换代码 , 如果这时转换代码,会存在冗余,因为如果公开的变量在其它模块中没有使用,那实际上就不需要使用数据通路进行封装,下一步应该分析调用关系之后,再进行 。
 
 
3.2 数据项关联调用组件
确定了公开的数据项之后 , 需要在工程源码中查找每个数据项的调用点,之后再跟据调用点数据确定每个数据项在不同的组件中调用的情况 。
数据项调用代码常见于以下写法,OC中也有其它的写法,本文中以下写法作为示例介绍调用关系的生成 。
[XXXSetting share].value1 
3.2.1. 查找每个数据项在文件中的调用

  • 原始数据项调用字串使用数据通路的数据项绑定 。
  • 整体的思路为,依次的从每个文件中 , 全字匹配字符串 , 查找到一次,算作调用一次,保存到字典中,统一输出到表格中 。
# 定义个全局字典 , 存放每个数据项在不同的文件中调用的次数# {数据项:{文件名:该文件内数据项调用的次数}}valueCallInfoDic = {}# 使用上节中,提取出来的数据项名,拼装为实际调和时的写法realValueName = '[XXXSetting share].' + valueName# fileNameList 为所有源码文件(.m 和 .mm)for fileName in fileNameList:# 记录该文件调用数据项的次数callNum = 0# 记录文件每个文件调用该数据项的次数信息fileCallInfoDic = {}# 依次的读取源文件的每一行,匹配调用情况,记录调用次数,及文件名,line 为代码行for line in f:# 使用正则全字匹配,查找替换regAbKey = realValueName.replace('[', '[')regAbKey = regAbKey.replace(']', ']')regAbKey = regAbKey.replace('.', '.')# pattern = [XXXSetting share].value1b主要为了防止数据项名有子串的情况pattern = r'' + fromstr + r'b'matchObj = re.match(r'.*' + regAbKey +'', line, re.M|re.I)if matchObj:callNum = callNum + 1if callNum > 0fileCallInfoDic[fileName] = str(callNum)# 如果有调用关系,则存储if len(fileCallInfoDic)valueCallInfoDic[valueName] = fileCallInfoDic 
 
3.3 输出为Excel表格文件使用Python分析的数据还是以机器语言的形式表式,需要以人类语言描述 , 将数据输出为excel表格,这样就可以借助于表格工具进行数据的查看及分析 。
 
3.3.1 数据项的详细使用情况输出表格的输出Python没有使用有excel操作的相关库,使用 ,(逗号)作为分隔符 , 存储为.csv文件,在excel中导入csv文件使用 。
具体的实现为依次的将每个数据项的使用的组件,使用的文件及在这个文件文件中使用次数,输出到.csv文件中 。
# 表头分别为,数据项,使用的组件,使用的文件 , 文件中使用次数outfiledata = https://www.isolves.com/it/cxkf/yy/Python/2023-10-27/'value , uselib , usefile , usenumn'# 遍历全局字典valueCallInfoDic,获取每个数据项 及数据项的调用信息# {数据项:{文件名:该文件内数据项调用的次数}}for.valueName , valueInfo in valueCallInfoDic.items():# 从数据项的调用信息中获?。?文件名和该文件内数据项调用的次数# {文件名:该文件内数据项调用的次数}for.fileName , callNum in valueCallInfoDic.items():outfiledata += valueName + " , "# libByFile 函数,实现根据文件获取所在的组件名outfiledata += libByFile(fileName) + " , "outfiledata += fileName + " , "outfiledata += callNum + " n"表格数据示例基于输出的表格数据,可以比较容易的判断每个数据项的优化影响范围,下表为表格数据的示例 。
Python脚本支持OC代码重构实践:模块调用关系分析

文章插图
△注:表格数据非真实业务场景数据
3.3.2 数据项的预分析统计输出基于数据的调用关系数据,确定每个数据项被每个组件使用的情况,并确定重构的方式 。
同样,表格的输出Python没有使用有excel操作的相关库,使用 ,(逗号)作为分隔符 , 存储为.csv文件,在excel中导入csv文件使用 。
具体的实现为依次的读取数据项,计算每个数据项被组件的使用情况 , 并将结果输出到.csv文件中 。
# 表头分别为,数据项,使用的组件  , 组件中总使用次数 , 使用类型outfiledata = https://www.isolves.com/it/cxkf/yy/Python/2023-10-27/'value , uselib , usenum , usetype n'# 遍历全局字典,获取每个数据项 及数据项的调用信息# {数据项:{文件名:该文件内数据项调用的次数}}for.valueName , valueInfo in valueCallInfoDic.items():libCallInfo = {}# 从数据项的调用信息中获取,文件名和该文件内数据项调用的次数# {文件名:该文件内数据项调用的次数}for.fileName , callNum in valueCallInfoDic.items():# libByFile 函数,实现根据文件获取所在的组件名libName =libByFile(fileName)if libName in libCallInfo:libCallInfo[libName] = int(libCallInfo[libName]) + int(callNum)else:libCallInfo[libName] = callNum# 每个组件的使用XXXSetting 的数据项情况hasSelfCall = FalseuseType = ""for.libName in libCallInfo:if libName == "XXXSetting":hasSelfCall = Truebreakif len(libCallInfo) == 1:if hasSelfCall:# 配置数据项仅在XXXSetting模块内使用,这部分数据项不需要接入数据通路 。useType = "selfCall"else:# 配置数据项在XXXSetting模块内没有使用 , 只在一个模块中使用,这类数据项应该迁移到使用该数据项的模块中 。useType = "otherCall"else:if hasSelfCall:# 配置数据项在XXXSetting模块内使用,也在其它的模块中使用,这类数据项在XXXSetting模块中维护,数据项需要接入数据通路 。useType = "selfAndOtherCall"else:# 配置数据项在XXXSetting模块内没有使用 , 但在一个以上模块中使用,这类数据项可以在XXXSetting模块中维护,但数据项需要接入数据通路 。useType = "othersCall"for.libName , libCallNum in libCallInfo.items():outfiledata += valueName + " , "outfiledata += libName + " , "outfiledata += libCallNum + " n"


推荐阅读