作者 | 刘俊启
导读
在软件开发中,经常会遇到一些代码问题,例如逻辑结构杂乱、依靠联系紊乱、代码冗余、不易读懂的命名等。这些问题可能导致代码的可保护性下降,添加保护本钱,一起也会影响到开发功率。这时通常经过重构的方法对已有代码结构进行改善和优化。在重构的作业中,大部分的作业是人工的方法完结,是一个耗时且简略出错的进程。对于研制人员来讲,在不改变软件的功能和行为的前提下,确保质量和功率完结对已有功能的重构,是一个极大的挑战。本系列以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 = ' }nn'
# funbody 为转化之后的读取某个数据项的部分代码,匹配key,之后再回来对应的值,添加一些空格及换行,代码按标准对齐
# if ([key isEqual:@"className_value1"]) {
# return self.value1;
# }
- 函数尾示例,以NSString类型为例,一切数据项转化完结之后,再添加
funEnd = ' return nil;n'
funEnd = '}nn'
不同的数据类型顺次转化,一切数据项转化完结之后,顺次的组合成为一个文件,文件的内容能够直接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 = ' }nn'
# funbody 为转化之后的更新某个数据项的部分代码,匹配key,之后再回来对应的值,添加一些空格及换行,代码按标准对齐
# if ([key isEqual:@"className_value1"]) {
# self.value1 = value;
# return;
# }
- 函数尾示例,一切数据项转化完结之后,再添加
funEnd = '}nn'
03 小结
本篇的内容,依据上一篇内容的剖析结论,将被多个组件运用的数据项接入到数据通路的代码,运用Python脚本主动生成的实践。
因涉及到的数据项较多,需求在一切的数据项中选出需求重构的数据项,生成数据项key列表,并跟据数据项的类型,接入到不同类型的读写接口中。运用人工书写代码的方法很难确保数据项接入到数据通路进程的质量,一起也很难验证数据项搬迁的完整性。
而运用Python脚本完结工具支撑数据项接入数据通路的代码生成,能够主动的、精准的生成每一个数据项接入数据通路的代码,可减少研制及测验人力的投入,直接的提高了研制功率。
下一篇我们将介绍怎么经过Python脚本支撑数据项运用模块接入数据通路时的适配,感兴趣的同学,能够继续重视。
欢迎加入百度搜索大前端团队,继续招聘iOS/Android/Web前端研制工程师
简历欢迎投递至joinefe@baidu.com
——END——
推荐阅览