通过Python脚本支持OC代码重构实践(二):数据项提供模块接入数据通路的代码生成
作者 | 刘俊启
导读
在软件开发中,经常会遇到一些代码问题,例如逻辑结构复杂、依赖关系混乱、代码冗余、不易读懂的命名等。这些问题可能导致代码的可维护性下降,增加维护成本,同时也会影响到开发效率。这时通常通过重构的方式对已有代码结构进行改进和优化。在重构的工作中,大部分的工作是人工的方式完成,是一个耗时且容易出错的过程。对于研发人员来讲,在不改变软件的功能和行为的前提下,保证质量和效率完成对已有功能的重构,是一个极大的挑战。本系列以Python实现自动化的工具,支持代码重构过程的实践。
全文5529字,预计阅读时间14分钟。
在上一篇《通过Python脚本支持OC代码重构实践(一):模块调用关系分析》的内容中,重点介绍了使用Python实现模块调用关系的分析,并以.csv格式文件输出,导入到excel中评估重构影响面及每个数据项重构方式,在重构编码工作启动前明确了具体的工作及重构之后的收益,这对于立项的人力投入的决策会起到很关键的作用,特别是当团队资源稀缺时,把要做的事情讲清楚是一件很重要的事情。
同时也在上篇内容中提到,技术层面先实现一个模块间数据项通讯的机制(本系列文章中以数据通路代指),支持数据项不需要公开,也可以被其它的组件中的模块读写。基于数据通路的实现,将XXXSetting模块接入数据通路,就可以解决因为XXXSetting模块中的数据项变更而带来的接口不兼容变更的问题,也会降低上层的依赖方组件二次的发布次数,间接的提升XXXSetting模块数据项相关研发需求的研发效率。
在XXXSetting模块数据项接入到数据通路过程,以百为量级的数据项需要逐项的按照数据通路的标准进行重构,手工的重构方式成本高,出错概率高,测试时需要逐项验证成本高,我们使用的Python脚本实现接入数据通路的这部分代码的生成,可精准的生成每一个数据项接入数据通路的代码段,实现了本次重构工作在测试及上线阶段零Bug。
本篇的内容先简单介绍数据通路的基础功能,随后再阐述如何利用Python编写的自动化工具,XXXSetting模块作为数据项提供方集成到数据通路中,代码自动的生成的实现思路。
01 数据通路技术实现与接入
基于本次配置数据项重构工作的目标和数据通路的复用,数据通路的实现目标为可支持不同模块接入,如图-1所示,与数据通路相关的模块共为两类。
△图-1
1.1 数据项交互模块定义及简介
数据项按照供需关系,主要分为两类,数据项提供模块和数据项使用模块。
1、数据项提供模块:数据的提供方(如本文中提到的XXXSetting),遵循系统中约定的数据读写协议,为系统提供互通的数据项支持。数据项与数据项提供模块是n:1的关系。数据通路支持多个数据项提供模块的接入,是 1:n 的关系。
2、数据项使用模块:数据的使用方(如上篇文章中的XXXLib中的模块),基于数据通路提供的能力,进行数据的读写调用,获取及更新所依赖的数据项的值。数据通路与数据项使用模块是 1:n 的关系。
1.2 数据通路实现及模块简介
数据通路的主体实现思路为,提供统一的接口,支持不同的数据项提供模块接入,在数据通路中管理接入数据项提供模块,当数据项使用模块需要读写数据时,根据数据通路提供的接口,进行数据项的数据同步。主要分为数据项提供模块接口层、数据项提供模块管理和数据项读写服务模块。
1、数据项提供模块接口层:约定数据项提供方要实现的数据读写能力,只有按照该标准实现的模块,才可作为数据的提供模块接入。
2、数据项提供模块管理:管理系统中所有数据项提供模块,提供注册的接口,数据项提供模块可调用注册接入需要在数据通路中管理的数据项。同时在收到数据项读写请求时,对模块中所关联的数据项的读写进行分发。
3、数据项读写服务模块:提供稳定的数据读写的能力,全局可访问,根据key查找数据项提供模块,并调用数据项提供模块的接口实现数据项的读写。
02 数据提供方接入数据通路的实现
2.1 数据项接入数据通路的主要工作
1、数据提供模块接入数据通路:按照数据项提供模块接口层约定,实现数据项的读写,主要分两步:
-
向数据通路注册可读写的数据项的信息,是一个数组,数组中存放的是每个数据项的Key,Key的命名规则为数据项提供模块类名_数据项名,这部分代码使用Python脚本自动生成。
-
数据项的读写,由数据项提供模块实现读写数的接口,根据key匹配数据项,之后再对该数据项进行读写 ,这部分代码也使用Python脚本自动生成。
2、数据项使用模块接入数据通路:由原直接调用方式,改为通过数据通路间接调用的方式,详细实现在下一篇内容介绍,敬请关注。
2.2 需要重构的数据项整理
在上一篇《通过Python脚本支持OC代码重构实践(一):模块调用关系分析》的内容中,3.1.2 提取的是变量类型和变量的名称小节中,经过预处理后,可提取所有数据项的类型及数据项名称。
同时结合上篇3.3.2 数据项的预分析统计输出小节中,取数据项被多个组件使用的数据项,确定为本次需要重构的数据项。
将这两部分数据进行交集的计算,得出来需要重构的数据项类型及数据项名称全集,为数据项读写代码生成时使用。下面为数据集的示例。
// 数据项类型 数据项名称; NSString value1; NSString value2; BOOL value3; ...
2.3 数据项提供模块的数据项列表生成
数据通路本身不产生数据,只作数据读写的桥接。数据项提供模块接入到数据通路时,需要知知数据通路支持那些数据项的读写。
具体的实现为,通过数据项提供模块接口层的约定告知数据通路,由数据通路调用,返回数据项提供模块支持的数据项列表,数据项列表的数据结构为数组,数组中为每个数据项的key,key的生成格式为数据项提供模块类名_数据项名。Python实现的转换代码如下:
# 原代码行示例 NSString value1; 参考2.2小节中的代码 matchObj = re.match(r"(.*)\s+(.*);", line, re.M|re.I) if matchObj: # value = matchObj.group(2) -- value1 key = ' @\"' + className + '_' + matchObj.group(2) + '\",\n' # key = ' @"className_value1",\n' # key 按OC的写法,每一行一个key,按NSArray的方式初始化多个key
2.4 数据项读取代码生成
注册了可通过数据通路读写的数据项,当数据通路需要读写该数据项时,数据项提供方按照标准实现数据项的读写。
2.4.1 数据项读取代码示例
数据通路支持基本的数据类型的读取,每一种数据类型对应的不同的读取接口,数据提供方根据数据项的类型,实现不同类型数据读取,同一种数据类型中,数据提供方根据key返回的对应的数据项值,目标生成的OC代码如下:
// 数据项是 NSString类型 - (NSString *)stringForKey:(NSString *)key { if ([key isEqual:@"className_value1"]) { return self.value1; } // 如有多个数据项,自动也合到同一个函数 if ([key isEqual:@"className_value2"]) { return self.value2; } return nil; } // 数据项是 BOOL类型 - (BOOL)boolForKey:(NSString *)key { if ([key isEqual:@"className_value3"]) { return self.value3; } return NO; } // 其它...
2.4.2 数据项读取实现生成
因数据项的类型不同,需要使用不同的接口读取,故在代码转换时,会根据数据项的类型,将转换后的代码行,分别的存储在不同的数据变量中,每个数据变量会在初始化时,增加函数头,在转换结束后增加函数尾。
- 函数头示例,以数据项为NSString类型为例
# NSString 类型的数据读接口,函数头字串由变量保存 funName = '- (NSString *)stringForKey:(NSString *)key {'
- 函数体示例,每个数据项均生成对应的代码,依次的存储每个数据项的读取
# 原代码行示例 NSString value1; 参考2.2小节中的代码 matchObj = re.match(r"(.*)\s+(.*);", line, re.M|re.I) if matchObj: funbody = ' if ([key isEqual:@\"' funbody += 'className_' + matchObj.group(2) + '\"]) {\n' funbody += ' return self.' + matchObj.group(2) + ';\n' funbody += ' }\n\n' # funbody 为转换之后的读取某个数据项的部分代码,匹配key,之后再返回对应的值,增加一些空格及换行,代码按规范对齐 # if ([key isEqual:@"className_value1"]) { # return self.value1; # }
- 函数尾示例,以NSString类型为例,所有数据项转换完成之后,再增加
funEnd = ' return nil;\n' funEnd += '}\n\n'
不同的数据类型依次转换,所有数据项转换完成之后,依次的组合成为一个文件,文件的内容可以直接copy到项目工程中,可直接的使用。
2.5 数据项更新
2.5.1 数据项更新代码示例
数据通路支持基本的数据类型的更新,每一种数据类型对应的不同的更新接口,数据提供方使用根据数据项的类型,实现不同类型数据更新,同一种数据类型中,数据提供方根据key更新的对应的数据项值,目标生成的OC代码如下:
// 数据项是 NSString类型 - (void)updateString:(NSString *)value forKey:(NSString *)key { if ([key isEqual:@"className_value1"]) { self.value1 = value; return; } // 如有多个数据项,自动也合到同一个函数 if ([key isEqual:@"className_value2"]) { self.value2 = value; return; } } // 数据项是 BOOL类型 - (void)updateBool:(BOOL)value forKey:(NSString *)key { if ([key isEqual:@"className_value3"]) { self.value3 = value; return; } } // 其它...
2.5.2 数据项更新实现生成
因数据项的类型不同,需要使用不同的接口更新数据项,故在代码转换时,会根据数据项的类型,将转换后的代码行,分别的存储在不同的数据变量中,每个数据变量会在初始化时,增加函数头,在转换结束后增加函数尾。
- 函数头示例
# NSString 类型的数据读接口,函数头字串由变量保存 funName = '- (void)updateString:(NSString *)value forKey:(NSString *)key {'
- 函数体示例,每个数据项均生成对应的代码,依次的存储每个数据项的读取
# 原代码行示例 NSString value1; 参考2.2小节中的代码 matchObj = re.match(r"(.*)\s+(.*);", line, re.M|re.I) if matchObj: funbody = ' if ([key isEqual:@\"' funbody += 'className_' + matchObj.group(2) + '\"]) {\n' funbody += ' self.' + matchObj.group(2) + ' = value;\n' funbody += ' return;\n' funbody += ' }\n\n' # funbody 为转换之后的更新某个数据项的部分代码,匹配key,之后再返回对应的值,增加一些空格及换行,代码按规范对齐 # if ([key isEqual:@"className_value1"]) { # self.value1 = value; # return; # }
- 函数尾示例,所有数据项转换完成之后,再增加
funEnd += '}\n\n'
03 小结
本篇的内容,基于上一篇内容的分析结论,将被多个组件使用的数据项接入到数据通路的代码,使用Python脚本自动生成的实践。
因涉及到的数据项较多,需要在所有的数据项中选出需要重构的数据项,生成数据项key列表,并跟据数据项的类型,接入到不同类型的读写接口中。使用人工书写代码的方式很难保证数据项接入到数据通路过程的质量,同时也很难验证数据项迁移的完整性。
而使用Python脚本实现工具支持数据项接入数据通路的代码生成,可以自动的、精准的生成每一个数据项接入数据通路的代码,可减少研发及测试人力的投入,间接的提升了研发效率。
下一篇我们将介绍如何通过Python脚本支持数据项使用模块接入数据通路时的适配,感兴趣的同学,可以持续关注。
欢迎加入百度搜索大前端团队,持续招聘iOS/Android/Web前端研发工程师
——END——
推荐阅读

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
SaaS 出海,如何搭建国际化服务体系?(三)
防噎指南:这可能是你看到的干货含量最高的 SaaS 出海经验分享,请准备好水杯,放肆食用(XD。 当越来越多中国 SaaS 企业选择开启「国际化」副本,出海便俨然成为国内 SaaS 的新·角斗场。 LigaAI 观察到,出海浪潮助生了许多「Day One 就做国际化」的产品和团队,而出海大军中也不乏在国内已经完成 PMF 的熟悉面孔。一个主要由中国人构成的团队在推进海外产品落地的过程中,可能会遇到哪些困难?是否能以行之有效的「避雷方案」,加快行军速度,一路披荆斩棘? 为解答心中的疑惑, #Liga妙谈# 第九期特别邀请 Aftership 全球客户成功副总裁刘徽(Sean)一起探讨中国 SaaS 企业出海的「路与行」,并为大家献上可复制、可实践、可落地的出海实操技巧。 全系列内容共分为三篇,本篇为第三篇:关于跨时区的异步团队协作模式的探讨。 中国 SaaS 企业出海会遇到哪些常见难题? 哪些 SaaS 产品或团队更适合发展出海业务? 大/中/小型企业如何落地国际化服务体系? 异步团队如何开展更高效的跨时区协作? 04 高效的跨时区管理与协作 LigaAI:SaaS 企业出海会遇到哪些跨...
- 下一篇
企业级开源分布式中间件 | DBLE 3.23.08.0 版本发布!
以下对 DBLE 3.23.08.0版本的 Release Notes 进行详细解读。 文章主要分为以下四部分内容: 一、DBLE 项目介绍 二、新版本主要更新解读 三、完整Release Notes 四、LTS 版本更新 一、DBLE 项目介绍 DBLE 是企业级开源分布式中间件,江湖人送外号“MyCat Plus”;以其简单稳定,持续维护,良好的社区环境和广大的群众基础得到了社区的大力支持; 破壳日:2017.10.24 爱好:开源 技能:数据水平拆分、读写分离、分布式事务支持、多分片算法、全局 ID、IP/SQL 黑白名单 特长:MySQL 语法兼容、复杂查询优化、低改造成本、成熟稳定、成熟技术栈 DBLE 官方项目: https://github.com/actiontech/dble DBLE 官方文档(已更新): https://actiontech.github.io/dble-docs-cn 新版本 DBLE 下载地址及 Release Notes: https://github.com/actiontech/dble/releases 官方课程: 点击学习《DBLE ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Red5直播服务器,属于Java语言的直播服务器
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7