开源项目的研发流程怎样提升产品稳定性
1.稳定性背景介绍
稳定性层级模型(by Google SRE):
本次分享关注点:
- 产品设计(Product):金字塔顶端,稳定性问题的源头。
- 软件研发(Development):编码实施工作量大头,稳定性问题的大头。
- 测试和发布流程(Testing&Release procedures):兜底阶段,稳定性问题的最后把关。
2.稳定性与流程规范
稳定性问题来源:
本次分享关注设计、编码、测试发布这3个阶段涉及到的流程规范,作为基础软件,在这3个方面投入时间也是非常具有性价比的。设计是引入稳定性问题的源头,编码和发布是引入稳定性问题的过程。我们需要从源头和过程两方面入手,来尽可能避免引入稳定性问题。
开源项目流程与稳定性:
据研究开源项目的缺陷密度普遍低于闭源项目,这与开源项目的规范流程息息相关,规范流程能提升产品的稳定性。开源项目的研发流程其实并不等价于规范的研发流程,只是说大多数开源项目的研发流程是比较规范的(主要原因是流行的开源项目涉及的开发者多、出问题影响面也比较广,为了保证高质量代码且高效协作,往往会制定规范的流程)。
当然,规范的研发流程不仅仅能提升产品质量及稳定性,还可以附带提升如下方面:
- 可读性、可维护性、可扩展性、健壮性、兼容性、易用性:受益于良好的设计;
- 研发过程的可控性:受益于明确的阶段;
- 协作衔接效率:受益于明确的接口规范;
- 新人融入效率:受益于清晰透明的步骤;
- 团队成员技术能力:受益于采用业界优秀的研发实践经验。
开源项目与高质量的思考:
- 开源项目若被广泛使用,需要高质量代码才能确保软件在各类场景正常工作,有需求则有市场;
- 开源项目参与人员多,而衔接处容易引入问题,需要有好的设计来保证协作的高效与代码的可控;
- 开源社区往往有技术大佬设立较高标准,会要求或指导新人,形成良性循环;
- 开源项目代码公开、项目持久、具备影响力,参与者有使命感、荣誉感、成就感,自发希望写出好代码;
- 开源社区之间相互学习交流,参与者相互贡献,好的实践方法容易在社区之间传递;
- 开源贡献者对技术的热爱与追求,也会促进了项目质量越变越好。
流程规范实践:
关于研发流程意义,可以理解为把业界好的实践方法归纳起来,沉淀为共同的经验然后大家一起去遵守。需要注意的是流程规范可能会降低个体成员的效率,而关于研发流程规范的作用,还可以类比有无红绿灯效果对比、正规军与游击队战斗力对比。
关于研发流程实践,可分为2个维度来看:一方面是协作成员遵守流程规范进行研发,另一方面是流程本身的自动化程度。具体涉及:
- 遵守流程规范:确保成员充分理解流程的目的与重要性,参与成员达成共识,制定流程规范,并确保流程本身闭环/合理/简单/柔和,最终保障成员遵守流程规范。
- 尽可能自动化流程:自动化流程的核心是尽可能降低对人的依赖程度,而是依赖流程来保障规范得以执行。自动化可以降低流程执行成本,同时避免过程中的人为操作引入问题。理论上,除了设计与编码需要人工Review,其它都可以交给自动化流程。
3.流程规范
3.1设计规范
好设计如何提升稳定性:
- 设计合理:需求明确、结构完整、条理清晰、推理严谨、逻辑自洽,符合逻辑的设计本身意味着正确可靠;
- 设计简洁:架构设计简洁,模块设计链路清晰,简洁清晰有助于减少问题,复杂问题可分治简化,避免复杂性导致潜在问题;
- 设计易理解:软件必然会面临增加需求或改进迭代,合理且易理解的设计在后续变更时有助于减少引入问题;
- 代码失序问题:代码一旦复杂而失去秩序,破窗效应让开发成员失去信心,项目往往会越变越乱而导致问题不断;
- 代码腐化问题:代码自然而然地向着腐化的方向演进,如果发现代码修改变得不容易时(难以理解、脆弱/一触即崩、小改动需要各处修改),需考虑重新设计与重构。
设计原则:
我们可以依靠设计评审流程,来保障方案遵循设计规范。
好设计的原则参考:
- 模块化设计原则
- 横向解耦:模块独立、输入输出明确、资源拥有者明确;
- 纵向解耦:依赖分层、逻辑层次分明、数据流转层次清晰;
- 服务隔离:进程隔离、故障隔离、服务版本化;
- 限制上下文依赖:减少上下文依赖数量,除了输入参数尽可能不依赖其它外部状态,上下文依赖越多越容易导致非预期行为;
- 平衡性能优化与设计:将性能优化带来的糅合体关进笼子里,严格控制所谓性能优化带来的一团乱麻代码的蔓延范围;
- 面向对象设计原则
- 聚焦自身:封装、高内聚、低耦合,关注点聚焦可以降低复杂性,而且当扩展功能需要添加代码时,可以避免大范围修改;
- 关注接口:暴露接口、隐藏实现细节,降低模块使用者与维护者的心智负担;
- 分离实现:将实现与策略/接口分离,避免当各种实现的频繁修改时导致主流程引入大问题;
- 保持健壮:关注异常情况,实现层次对各类异常进行处理,抽象层次对实现层次的异常进行隔离;
- 保持一致:同一层次的结构/流程/单位/参数等保持统一,不同层次之间的交互规则保持统一,同构性利于正确性且易于理解;
- 避免重复:适当抽象与组合,减少重复代码/无主代码,导致代码逻辑版本不一无人维护;
- 控制变更:收窄操作接口途径,明确变量状态的拥有者,仅允许通过本模块授权方法操作变量;
- 高可用设计原则
- 本次分享暂略过,关键点可参考上图“高可用架构设计”。
3.2编程规范
我们可以依靠代码评审流程(必须有2人+2才允许合入),来保障代码遵循编程规范、代码按设计方案实现。
代码评审的必要性:
编程是对需求及设计的实现,假如设计没问题的情况下,编码过程依然可能引入问题:一方面设计无法百分百定义所有细节(事实上编码与设计之间的Gap往往不小,编码阶段本身也包含了设计方案之外的细节设计),另一方面编码难以完全遵循设计,此外新模块衔接到各模块的过程也容易引入问题。
本质上,编码过程会引入大部分问题(包含设计问题),因此我们需要重点关注代码Review流程。此外,设计没问题的假设现实往往难以成立,Review代码的同时也是再次Review设计合理性的时机。
编码规范自动化检查:
- 业界或公司的编程规范检查;
- 静态代码检查;
- 编码风格检查;
人工代码评审检查点:
- 代码逻辑严谨:if-else、switch-case逻辑要完整及对等;
- 错误处理完善:错误处理覆盖完整,负反馈完整,函数在错误处理时,禁止吞异常/错误;
- 处理结果一致:在同一个模块/函数内部,多分支时对用户请求的处理逻辑对等一致,返回错误方式须一致;
- 错误信息清晰,给用户返回的错误提示信息要完整、清晰,不假设用户知道背景,尽可能多的把错误信息返回给用户(不吞错误信息);
- 确保资源释放:异步编程时,确保回调链路在各种异常下预期衔接,确保内存及锁等资源在各种异常下能释放;
- 参数传递一致:传参时内存拷贝/移动风格一致、采用引用/裸指针/sharedptr/uniqueptr风格一致、输入输出参数风格区分明确;
- 代码简洁清晰:尽可能使用局部变量/最小化成员变量范围/避免使用全局变量/避免跨模块共享数据、代码逻辑尽量复用、深层嵌套/大块代码/大文件代码进行抽象剥离、函数参数尽量不作为输出参数/或明确输出参数约定、命名直观且慎用缩写/变量命名可体现作用域/函数命名可体现读写幂等属性、按层次与类别划分代码目录名/文件命/类名;
- 代码风格一致:代码风格符合要求或与现有系统保持一致,包括换行、对齐、空格、变量与函数命名等;
- 具备关键注释:易误解点标记NOTE,待改进点标记好TODO,以定期重构腐化代码;
- 测试用例完善:确保新增代码添加了完整的测试用例;
- 设计合理清晰:设计是否符合规范、是否可以更加合理、更加清晰、更加优雅;
- 提交信息清晰:commit message包含issue/feature背景、设计目标why、如何实现how等要素;
3.3测试发布规范
测试发布规范:
- 自动化测试:具备自动化测试脚本,尽可能将99%测试用例自动化,因为自动化可确保研发流程简单、步骤无误,还避免手工介入引入风险;
- 测试用例丰富:具备完整的测试用例,包括单元测试、模块集成测试、功能场景测试、接口测试、系统集成测试、性能测试、混沌测试;
- 测试流程完整:研发自测、回归测试、压力测试、模拟环境测试
- 由RD进行研发自测,包括单元测试、模块集成测试、功能场景测试、接口测试,并且确保全部测试用例自动化;
- 由QA进行回归测试,包括系统集成测试、性能测试、混沌测试,并且确保测试90%以上自动化;
- 由QA进行模拟测试:包括负载测试(large users)、容量测试(large data)、压力测试(stable when breaking)、模拟环境测试,测试数据集可来源于业务场景或者模拟业务场景,并且尽可能自动化测试流程;
- 风险点可评估,确保在发版前获得完整测试报告,明确风险点;
- 自动化集成,将所有的可自动化测试用例集成到CI流程中,日常提交代码即可自动触发执行。
- 异常测试丰富:反向测试用例覆盖完善,将各种场景沉淀到测试脚本中;
- 测试可量化:CI流程中的自动化测试结果、测试覆盖率可即时反馈;
- 自动化发布:具备自动化打包、分发、安装部署脚本,具备配置文件版本控制机制,做到发布流程全程可控。
参考链接:
- https://www.infoq.cn/article/z4ssmnks3w4ebbustyo1
- https://www.51cto.com/article/720958.html
- https://www.on0926.com/%E7%B3%BB%E7%BB%9F%E7%A8%B3%E5%AE%9A%E6%80%A7%E6%B2%BB%E7%90%86%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%EF%BC%88%E4%B8%87%E5%AD%97%E9%95%BF%E6%96%87%EF%BC%89/
- https://blog.csdn.net/xc917563264/article/details/119827263
- https://blog.csdn.net/daocaokafei/article/details/116518022
- https://blog.csdn.net/zhoujinwang/article/details/127682273