通过Python脚本支持OC代码重构实践(二):数据项提供模块接入数据通路的代码生成

news2024/11/26 4:21:13

作者 | 刘俊启

导读

在软件开发中,经常会遇到一些代码问题,例如逻辑结构复杂、依赖关系混乱、代码冗余、不易读懂的命名等。这些问题可能导致代码的可维护性下降,增加维护成本,同时也会影响到开发效率。这时通常通过重构的方式对已有代码结构进行改进和优化。在重构的工作中,大部分的工作是人工的方式完成,是一个耗时且容易出错的过程。对于研发人员来讲,在不改变软件的功能和行为的前提下,保证质量和效率完成对已有功能的重构,是一个极大的挑战。本系列以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前端研发工程师

简历欢迎投递至joinefe@baidu.com

——END——

推荐阅读

对话InfoQ,聊聊百度开源高性能检索引擎 Puck

浅谈搜索展现层场景化技术-tanGo实践

初识搜索:百度搜索产品经理的第一课

智能问答技术在百度搜索中的应用

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1162568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32智能小车(循迹、跟随、避障、测速、蓝牙、wife、4g、语音识别)总结

目录 1.电机模块开发 1.1 让小车动起来 1.2 串口控制小车方向 1.3 如何进行小车PWM调速 1.4 PWM方式实现小车转向 2.循迹小车 2.1 循迹模块使用 2.2 循迹小车原理 2.3 循迹小车核心代码 2.4 循迹小车解决转弯平滑问题 3.跟随/避障小车 3.1 红外壁障模块分析​编辑 …

Redis 应用问题

1-缓存穿透 1.1-问题描述 Key 对应的数据在数据源并不存在,每次针对此 Key 的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。 比如:用一个不存在的用户ID 获取用户信息,不论缓存还是数据库都没有&…

有哪些适合做小说推文的配音软件?

其实现在市面上的短视频配音软件数不胜数,怎样才能挑选到简单又实用的呢?今天我就来给你盘一盘各大配音软件的优缺点,大家可以根据自己的需求来选择合适的配音软件! 一、悦音配音 推荐指数★★★★★ 推荐理由:无需自…

SpringBoot SerializationUtils克隆(反序列化) 类加载器不一致问题(ClassCastException)

问题分析 在SpringBoot中使用 org.apache.commons.lang.SerializationUtils.clone 方法时,发现克隆出来的类强转对应类时发生类型不一致的错误,经过检测发现两个看似相同的类的类加载器不一致 场景 报错信息 java.lang.ClassCastException: com.tianq…

伦敦金投资怎么玩收益高?

伦敦金,作为国际黄金市场的代表,一直备受投资者的关注。它有着高流动性和丰富的投资机会,但要真正玩得收益高,就需要掌握一些关键的方法和技巧。在本文中,万洲金业将为您提供专业建议,告诉您伦敦金投资怎么…

【广州华锐互动】VR虚拟现实技术在森林防火教学中的应用

在探索大自然的神秘面纱时,我们往往会遇到一些意想不到的风险,其中之一就是森林火灾。森林火灾是一种毁灭性的自然灾害,可以在短时间内摧毁大片森林,对人类和动物的生存环境造成严重影响。然而,通过3D仿真技术&#xf…

SteerMouse for mac Mac万能鼠标设置工具 功能介绍

鼠标可谓是用户们在使用电脑时候的必备外接设备呢!适合你自己的鼠标设置也绝对能够优化你的Mac使用体验!想要更好的Mac体验就试试用Steermouse Mac版吧。它通过软件来自由设置你的鼠标操作!在这款万能鼠标设置工具中,用户可以在偏…

uniapp在APP端使用swiper进行页面不卡顿滑动

uniapp在APP端使用swiper进行页面会卡顿&#xff0c;主要是渲染的数据有点多&#xff0c;这里只渲染三个数据就不好那么卡顿了&#xff0c;每次滑动后更新数据 <view><swiper change"changePoint" circular :disable-touch"disableTouch"><…

【Excel密码】四个方法,设置excel表格只读模式

Excel文件想要设置成只读模式&#xff0c;其实很简单&#xff0c;今天给大家分享四个excel设置只读模式的方法。 方法一&#xff1a;文件属性 右键点击文件&#xff0c;查看文件属性&#xff0c;在属性界面&#xff0c;勾选上只读属性就可以了。 方法二&#xff1a;始终以只读…

g.Grafana之Gauge的图形说明

直接上操作截图 1. 创建一个新的Dashboard 2.为Dashboard创建变量 【General】下的Name与Label的名称自定义 【Query options】 下的Group可以填写Zabbix内的所有组/.*/ , 然后通过Regex正则过滤需要的组名 3.设置Dashboard的图形 我使用文字来描述下这个图 1.我们在dash…

【分享】winterm ssh登录报错Unkown error

非软文哈&#xff0c;实测Winterm非常好用&#xff0c;唯一的障碍是 某些特定服务器ssh登录报错Unkown error 后经github issue得知&#xff0c;关闭会话设置-ssh选项卡中的 尝试键盘交互认证的勾即可。 https://github.com/kingToolbox/WindTerm/issues/1922

【C++】基础语法(上)

C基础语法 此语法笔记面向算法竞赛考研&#xff0c;可供参考&#xff0c;本人的一些笔记的记录~ 失踪人口回归&#xff0c;将近半个月没有更新&#xff0c;那么接下来也会逐步开始更新分享知识内容~ 本篇将分享cpp基础语法中的变量、输出输入语句、表达式、顺序语句、条件判断…

el-table添加class类名并添加样式

先上效果图&#xff1a;输入框内容被 内边距 padding: 0 12px; 但是只想在这列开始去除内边距 理想效果 解决方案 AddClass <!-- 给某个td里面添加类名:cell-class-name --> <el-table:data"data"size"mini"borderselection-change"sele…

大恒相机在halcon里面的可读可写参数和只读参数

查询图像采集设备具体参数的算子 get_framegrabber_param (AcqHandle, available_param_names, AvailableParamNames) U3相机 可读可写 只读参数 活动参数 网口相机 只读参数 活动参数

Kafka-入门及简单示例

启动与简单示例 # 命令行1 #开启Zookeeper E:\>cd E:\kafka_2.13-3.6.0E:\kafka_2.13-3.6.0>bin\windows\zookeeper-server-start.bat config\zookeeper.properties # 命令行2 #开启Kafka E:\>cd E:\kafka_2.13-3.6.0 E:\kafka_2.13-3.6.0>bin\windows\kafka-serv…

【Windows-软件-FFmpeg】(01)通过CMD运行FFmpeg进行操作,快速上手

前言 通过"cmd"运行"ffmpeg"进行操作&#xff0c;快速上手&#xff1b; 实操 【实操一】 说明 使用"FFmpeg"来合并音频文件和视频文件 &#xff1b; 环境 Windows 11 专业版&#xff08;22621.2428&#xff09;&#xff1b; 代码 &#xf…

【MATLAB源码-第65期】基于matlab的OFDM/OTFS通信系统性能对比,输处误码率曲线;对比是否采用LDPC编码。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OTFS&#xff08;Orthogonal Time Frequency Space&#xff09;是一种无线通信调制技术&#xff0c;它利用时间、频率和空间的正交性来传输数据&#xff0c;目的是提高无线通信系统的性能&#xff0c;尤其是在多径和高移动性环…

fastapi-参数

路径参数 你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量"&#xff1a; from fastapi import FastAPIapp FastAPI()app.get("/items/{item_id}") async def item_details(item_id: int):return {"item_id": i…

关于电容充放电

计算下电容放电时&#xff0c;其电压和时间的关系 百度&#xff1a;电容充放电电压公式 电容充放电时间 百度安全验证https://baijiahao.baidu.com/s?id1618374634281434486&wfrspider&forpc 电容充电放电时间计算公式&#xff1a; 设&#xff0c;V0 为电容上的初始…

双十一有哪些值得买的东西?2023年双十一运动好物强烈推荐

看着日历上的双十一正在一步一步的向我们挥手&#xff0c;同时也能感受到各大电商平台的预热活动&#xff0c;我们很清楚的知道双十一快要到来了&#xff0c;这也意味着一年一度疯狂扫货的日子也快到了&#xff0c;那么在今年双十一有哪些值得买的东西&#xff1f;作为一个玩转…