从公众号转载,关注微信公众号掌握更多技术动态
---------------------------------------------------------------
一 、质量标准化
1.什么是质量标准化
通过标准化各条业务线的研发流程,以做的比较好的业务线作为标准样板间,规范出一套标准化的流程,并适用到其它业务线,从而使各条业务线都能进行高质量的交付。
(1)质量不只是测出来的
“质量既是设计出来的,也是测试出来的,还是被逼出来的”,但质量一定不只是测出来的,质量保障不只是测试一种角色的责任,是贯穿研发流程各个角色共同的责任。
(2)缺陷发现的时间越早,成本越低
毫无疑问,缺陷被越早的发现,修复的成本就越低。在需求评审阶段就发现需求上的不合理,在技术设计阶段就发现技术方案的问题所在,在测试验证阶段发现系统的bug和产品bug,修复这些环节发现的问题的成本逐渐升高,但如果问题对客后才被发现,修复的成本将是巨大的,可能会影响客户体验和满意度,或造成资损,甚至导致公司名誉受损。
(3)测试策略本质上是在质量成本和质量风险之间取得平衡的一种方法
我们知道,程序的执行场景和场景中涉及的数据输入都是无法穷举的,因此测试是不能被穷举的。所以我们需要进行测试方案的设计,通过运用黑盒测试用例设计的等价类、边界值法等,白盒测试用例设计的条件覆盖法、路径覆盖法等从无限的测试数据中选出有效的测试数据,在有限的测试时间内进行有效的测试。
(4)开发自测是基本要求和基本素养
我们一直在强调开发自测,无论需求是否有测试接手,开发都必须要自觉地完成自测。作为一名合格的开发,本身就要对自己交付的代码有充分的质量保证,这应该是自上而下地在团队里需要贯彻的思想和共识。
2.软件质量
(1)功能质量
基础要求:满足用户需求。
质量指标:bug数量、性能、UI/UX
(2)代码质量
-
可维护性:在不影响稳定性的前提下,是否能方便地添加或修改现有的代码。
-
可读性:代码是否容易理解,是否能快速上手。
-
执行效率
-
安全性:是否有安全漏洞。
-
可测试性:代码是否能使用单元测试、集成测试进行测试验证。
(3)过程质量
软件开发过程的质量决定了项目能否如期完成,开发成本是都在预算之内。
3.质量责任划分
根据项目中的角色的职责来分析:
-
软件测试:对功能质量负责。对产品进行测试验收,确保满足功能需求,通常不能对代码质量和过程质量负责
-
开发人员:对代码质量负责,也可以写测试代码。通常对过程质量影响有限。
-
项目负责人:对过程质量负责。一般不直接参与编码和测试,所以无法直接影响代码质量和功能质量。
总结:权责角度看,项目经理最应该对项目质量负责。从效果上看,开发人员对质量负责最有利。
4.系统研发流程
编码开发--->开发测试(单元测试、联调测试)--->发布QA(SIT_System Integration Test)--->QA测试(回归和功能)--->发布灰度--->灰度测试(引流)--->发布生产——>完成(只有此时才是真正完成)
(1)需求阶段
在需求阶段我们常遇到的问题是,在项目开发过程中,才发现存在未评估到的需求点,如果要实现这些未评估到的需求点,可能会导致项目延期,也无疑会加重项目组成员的压力。
-
项目开发过程中,发现存在未评估到的需求点,如果不影响到主流程,通过走变更的方式解决。
-
项目进入开发前,需要再评审一遍细的PRD,如果有UED 变更,需要先准备好设计稿再组织PRD评审;
(2)资源投入评估
需求评审结束后,开发和测试同学需要评估投入的开发资源和测试资源,需求PM会拉通各方定下排期,主要包括联调时间、提测时间和发布上线时间,各个节点的时间一旦确定,PM和 TPM将会严格按照这个时间点来推进,一般是不允许延期交付的,除非有特殊原因,比如其它紧急需求临时插入等。
在资源投入评估中,除了定下排期,测试还会评估该需求是开发自测还是测试介入,会有一套评估机制。
-
拉通各方资源,协调排期
-
确定联调时间、提测时间、发布上线时间,接下来PM和TPM 会严格按照这三个节点推进项目
-
由测试确认是否需要测试接手
(3)系分阶段
在进入开发前,必不可少的环节便是技术方案的设计和评审。技术方案评审我们要求团队 master 以及架构师必须参加,并且有一套技术方案设计模板。此环节做得好的话,可以让后面的环节走得事半功倍。总的来说,技术方案设计会要求开发考虑到以下方面:
-
目标和背景
-
功能点及开发人日
-
系统间和系统内的交互时序图
-
数据库设计
-
接口设计(包括提供给前端的接口和提供给业务上下游的接口)
-
定时任务设计
-
接口性能评估
-
兼容性评估(是否兼容旧功能)
-
灰度方案
-
系统监控
-
核对方案
-
资金安全checkList
如果技术方案里没有详细地描述清楚上述方面的设计,在技术评审时会被打回,改完后再次组织下次的技术方案评审,通过后,才会进入开发。这种方式可以卡住那些在技术方案设计上就有问题的实现,避免到提测后才发现系统设计问题的不可控局面。
(4)测分阶段
毫无疑问,详细的测试方案和测试用例评审一来可以让测试同学对本次需求的改动和风险了然于胸,二来可以帮助开发梳理功能点和影响范围,三来可以正式拉通三方(测试、开发、产品)对本次交付功能点的共识。为了达到这个三个目的,我们整理了测试方案设计的模板和规范,要求团队内的测试同学:
-
在接手超过2天的测试项目时必须要有测试方案和测试用例的评审环节
-
要在开发技术方案评审后的五天内完成测试方案的评审
总的来说,测试方案设计会要求测试考虑到以下方面:
-
需要提供给开发的冒烟用例
-
本次需求的功能点及对应的覆盖用例
-
本次需求改动点可能影响的旧功能及回归用例
-
上下游联测方案和时间点
-
可能导致的资损点分析及需要建核对的场景
-
接口性能分析
-
灰度发布方案分析
-
维护并且更新主干用例库
(5)开发&联调&自测阶段
-
进入项目联调环节后,需要发联调日报(PM汇总发出),并每日晨会同步联调进度。
-
2.原则:联调前需要先完成域内的自测;
-
遇到卡点问题,由接口依赖方主动去push被依赖方解决,如果被依赖方没有及时解决,并影响了进度,需要同步风险
-
联调阶段,上游Mock联调或者真实链路联调发送消息,跟对方开发确认消息是否正确,增加确认过程;真实链路联调和mock联调接口不允许有差异。
-
由测试同学提供冒烟用例给到开发自测,开发必须把冒烟用例的所有场景走完才可以提测
-
发布前单测增量覆盖率需达到60%,单测通过率 100%
-
提前两天后需完成组内CR
我们会要求开发必须把冒烟用例的所有场景走完才可以提测。目前冒烟用例是用语雀文档的形式提供给开发,这是一种线下的方式,不太利于回溯和标准化推广,因此ICBU质量团队在菲尔兹平台上结合 aone 的用例管理提供了线上化的冒烟流程,后续会基于菲尔兹平台提供线上化的冒烟用例及冒烟状态管理。
衡量这一环节做的好不好的指标是:
-
提测准点率
-
提测通过率
-
自测可发现 bug 率
(6)测试阶段
超过3天的测试时间的项目,测试同学会发每天发日报,通过日报来及时同步测试进展和风险,同时要求 bug 开发日结。日报模板:
①项目里程碑
-
11.9-12.28:设计&开发&联调,已完成
-
12.21:发票配置后台功能预演,已完成
-
12.30:开票流程优化功能预演,已完成(延期6.5个工作日)
-
12.22-1.6:线下测试,已完成
-
1.8-1.12:预发回归测试,进行中(延期2个工作日上预发,原计划1.5日)
-
1.13:发布(延期5个工作日,原因:开发人员被其他项目占用资源,进入此项目时间晚)
②进展和问题
-
线下测试进度:100%
-
预发测试进度:
-
发票配置后台测试进度:100%
-
开票流程优化测试进度:90%
③风险
-
项目延期:项目延期至2022.1.13发布,延期5个工作日。 原因:① 开发人员被其他项目占用资源,进入时间晚;② 开发同学前期对工作量评估略少于实际;③xxx项目紧急插入,前端同学需要投入一天。④ 缺陷修复完成时间未如预期,预发提测时间延期2天。
-
bug修复
④明日计划
-
回归验证 新开票功能遗留缺陷;
-
回归嵌入式开票流程;
-
回归原有开票流程。
通过日报触项目组的所有同学(包括开发、产品、业务、测试),可以让大家对目前的测试进度和问题有个清晰的认知,同时如果项目有风险需要延迟,也可以及时周知到产品和业务,方便拉齐大家的预期。目前大家对日报还是非常认同的,后续也会坚持这个规范。
(7)发布计划评审
在大项目发布前,需要进行发布计划评审,在发布前在项目组内同步一遍准备工作,之后再进行发布。
-
发布范围
-
应用范围
-
发布顺序
-
-
资源梳理
-
HSF接口
-
数据库资源
-
消息资源(metaq)
-
调度资源(dts)
-
配置资源(diamond、switch、antx)
-
-
灰度计划
-
发布过程
-
预发发布过程
-
线上发布过程
-
-
回滚计划
-
跟踪计划
-
核对
-
系统监控
-
服务监控
-
-
风险控制和注意事项
-
历史数据兼容
-
幂等逻辑确认
-
灰度方案
-
应急开关
-
二、系统测试
3.产品测试
(1)软件测试的主要工作
发现bug
测试人员设计的测试用例,要尽可能做到覆盖所有用户操作的可能,但理论上来说是不可能的,不过可以通过一些科学方法来通过有限的测试用例,保证尽可能多的测试覆盖。
-
等价类划分:分类是有限的。
-
边界值分析
-
探索性测试:根据前面的测试结果,通过有效的策略进行测试。
-
场景设计
-
因果图
-
错误推测法
报告bug
bug跟踪系统和任务跟踪系统是一样的,也是需要提交ticket,说明bug内容,重现步骤、提供截图和日志等辅助信息。
跟踪bug
在验证修复后需要对整体进行回归测试。
(2)测试工具
在bug跟踪工具中,一个bug的基本信息包括:
-
标题
-
描述:期望结果,实际结果和重新步骤等关键信息
-
优先级
-
指派人
-
状态
-
其他
一个bug的完整生命流程:
使用bug跟踪工具的注意事项:
-
所有bug都应该通过bug跟踪管理系统跟踪。
-
不能把多条bug合并成一条
-
描述清楚如何重新bug十分重要
-
不要把bug跟踪系统当成谈论板使用。
①bug跟踪工具:
-
BugZilla
-
MantisBT
-
Redmine
②自动化测试工具:
-
Selenium
-
Appium
-
Macaca
③压力测试工具:
-
Apache JMeter
-
LoadRunner
-
阿里云性能测试PTS
-
WebPageTest
④安全性能测试工具:
-
Sqlmap
-
APPScane
⑤浏览器兼容性测试工具
-
Browsera
-
Browslering
-
TestRail
-
飞蛾
2.QA测试
开发小组要把“QA应该找不到任何错误”作为努力的目标。对于QA找到的没一个问题,开发团队都应该高度重视、认真对待,反思为什么会出现这种错误。
QA也是团队的一部分,QA和开发人员应该紧密合作携手保障系统的质量,通常业务人员编写针对正常路径的测试,而QA编写针对极端情况、边界状态和异常路径的测试。
三、运行维护
1.版本发布
(1)软件版本的定义
软件版本包含两部分含义:
-
特定功能的集合
-
某一次特定代码的构建结果
为明确标识版本,通常采用以下方式进行版本命名:
主版本号.子版本号[.修正版本号[.构建版本号]] 如:1.2.1 build-123
主版本号和子版本号:用来标识功能变化。小的功能变化增加子版本号,大的功能变化增加主版本号。
修正版本号:功能不变的情况下修复bug。
构建版本号:表示一次新的构建,通常由编译程序自动生成。
(2)版本发布规划
要达到好的发布效果,就需要在版本发布前先做好版本发布的规划。版本的发布规划包含以下内容:
-
规划好要发布的功能:对用户需求进行细分。
-
定义好发布的质量标准:用户对不同功能的质量的容忍度。
-
设计好发布策略:beta版本测试、灰度测试等。
-
有一个综合性的版本发布计划:和所有项目成员及项目利益相关方共同参与制定项目的发布计划。
(3)规范发布流程
发布版本需要注意的几个问题:
-
必须保证要编译部署的是正确的版本。
-
要保证版本稳定可靠。
-
在发布失败后能回滚。
制定合理流程,来应用好的实践,保证发布质量。一个参考流程如下:
-
在发布之前做代码冻结:在源码管理工具中创建一个release分支,对于这个分支的代码,冻结功能修改,不接受新功能的增加,只修复重要的bug。
-
对代码冻结后发现的bug要分级:确认是在发布前还是发布后修改。
-
每次修复bug后,发布新的候选版本
-
每次部署新的候选发布版本后,要做回归测试:手动了解自动化构建的方案
-
申请上线发布
-
部署发布
-
上线后的测试
2.DevOps是什么
DevOps可以理解为一种开发和运维紧密协作的工作方式,从而可以更快更可靠的构建、测试和发布软件。
DevOps方式的好处:
-
整个软件的构建、测试和发布过程高度自动化
-
信息更加透明和易于测量:信息更加透明,通过日志和工具,数据也可以被更好测量。
-
培养跨职能协作的文化:在日常工作中包容错误,对事不对人,能对项目的开发流程持续改进,鼓励创新。
3.线上故障解决
(1)快速定位bug
高手快速定位bug,关键在于通过有效的手段,逐步缩小问题范围,直到找到bug。常见的手段:
-
重现bug:通过重现的bug将问题的范围缩小。
-
分析错误日志:平时要注意收集错误日志
(2)大厂处理线上故障的方法
具体的处理流程,大同小异,总结如下:
-
对故障进行评级:先评级,从而决定后续的处理方案
-
马上恢复生产:避免进一步损失。可以采用部署回滚、服务降级等方式。
-
分析故障原因,恢复故障。
-
记录故障:记录故障处理的全过程,分析故障原因,提出后续改进方案。
值得学习和借鉴的地方:
-
故障报警和轮值机制:要做到最快速度处理线上故障,关键就是要让正确的人第一时间就可以去响应。正确的人就是对故障服务最熟悉的人,通常就是服务的开发人员。
-
实战演习:在日常开发中就对应急方法进行实际测试。
-
日志记录和分析工具:平时开发中,就注意对关键日志信息的记录,同时搭建ELK这样的日志分析系统,方便查询日志。
4.日志管理
在日志数量不多的时候,凭借肉眼或借助文本编辑器,可以大概看出日志的内容,当日志的数量很多的时候,就需要借助日志管理系统对日志进行统一管理。搭建日志管理系统的好处:
-
方便地对所有日志进行统一的检索。
-
可以通过图表直观地看到应用运行情况。
-
可以根据日志的数值设置规则自动报警。
(1)日志管理系统的架构
有几个重要的模块:
-
日志采集和解析:Logstash可以帮助实现对日志的采集,将日志解析成结构化的数据才能方便地检索。
-
存储和搜索:ElasticSearch是专业的全文检索和数据存储系统。
-
数据可视化:Kibana就是专门针对ElasticSearch的图形化操作工具。通过可视化图表,可以直观地看到数据的走势,以及方便地和历史数据进行对比。
-
监控和报警:可以安装Elast Alert这样的自动报警插件,实现报警功能。
(2)工具推荐
-
Splunk:商业日志管理系统
-
Grafana:开源的数据监测和可视化工具,支持自动报警功能。
-
Wavefront:图形化监测和分析工具,支持自动报警
-
PagerDuty:报警服务,可以和手机、邮件、Slack方便集成,还可以和企业的轮值安排结合。、
5.Code Review
(1)优点
-
提升团队代码质量。合理的CR环节,可以有效地把控每次提交的代码质量,不至于让项目的可维护性随着版本迭代和时间推移变得太差,这也是CR的首要目的。「CR环节并不会降低开发效率」,就一次代码提交来说,也许部分人认为CR可能花费了时间,但是有效的CR给后人扩展和维护时所节省的时间是远超于此的。
-
团队技术交流。Reviewer和Reviewee,在参与CR的过程中,都是可以收获到许多知识,进行技术交流的。
-
有利于帮助新人快速成长。
-
通过CR环节,团队成员可以了解他人的业务,而不局限于自己的所负责的业务范围。
-
学习他人的优秀代码。
-
-
保证项目的统一规范。一方面,统一的项目规范才能保证项目的代码质量,提高项目的质量和可维护性;另一方面,在大家熟悉了统一的规范后,能够提升CR的效率,节省时间。
(2)什么时候发起 Review
在代码 Review 上,Author 需要意识到:Reviewer 的时间是昂贵的。因此在正式邀请 Reviewer 发起代码 Review 前,Author 有几项需要注意的点,这些都能提高代码 Review 的效率,节省 Reviewer 的时间。
①MR (Merge Request)
也称为 PR(Pull Request), MR 是我们进行代码 Review 的地方,它记录着代码的具体改动,参与者具体的讨论过程。好的 MR 应该做到以下几点:
-
单一:一个 MR 应该只解决一个单一的问题,无论是修复一个 bug,还是实现一个新 feature。Author 应该避免一个 MR 包含不同意图的代码改动。单一的 MR 能帮助 Reviewer 快速地了解代码改动的动机,能有针对性地进行 Review。
-
短小:MR 应该尽量地小,比如一个 feature 引入了较多的改动,需要考虑是否可以拆成独立的几块实现,分开提 MR,比如接口定义、接口实现、逻辑对接等拆分开。
-
详细: 这里说的详细是指 MR 应该尽可能地详细描述它的背景和动机,可以是在 MR 的描述中详细体现,也可以是连接到具体 issue 或 tapd 单中。需要达到的目的是,其他人翻开一个 MR 能知道当时做这个改动的背景以及动机。
②Commit Message
应该有良好的提交信息,让人知道这次提交包括什么内容
③CI 通过
CI(Continuous Integration),持续集成可以帮助我们自动发现很多代码中的基本问题,在合适的静态代码检查(lint)配置和良好的单元测试覆盖下,CI 可以有效地提高代码的质量。很多人都低估了静态代码检查的能力,实际上现在常见语言的静态代码检查已经能帮助发现不少的 bug 和隐患。对于 Go 语言,可以配置 golangci-lint 来做代码检查,单元测试根据实际情况可以制定相应的标准,比如覆盖率 60%,其中关键的代码逻辑尽量全面覆盖。提交代码 Review 前需要确保 CI 执行通过,这也是为了节省 Reviewer 的时间,能够通过自动化解决的事情,尽量不要让 Reviewer 来做,而 Reviewer 发现 CI 未过的 MR 也可以要求 Author 先解决 CI 问题。
④Self-Review
一般代码 Review 都是找他人来进行 Review,其实负责任的 Author 在邀请他人来代码 Review 前也需要自己简单 Review 一遍,即 Self-Review。Self-Review 的目的包括:
-
发现那些明显的疏忽,如代码 debug 过程中留下的不必要的痕迹,比如 fmt.Println(...),不小心注释掉的代码。
-
之前被 Reviewer 多次提出过的问题。
-
Commits 是否正常,在多人协作的情况下 MR 中否带入了不相关的 Commit。
-
Commit Message 是否合适。
Self-Review 是一个非常快速的过程,从我个人的经验,一般 1-2 分钟即可完成,所以推荐大家养成 Self-Review 的习惯。
(3)该找谁来 Review
从目的出发,可以从以下几方面考虑 Reviewer:
-
提高代码质量。所以首先应该找和代码改动紧密相关的研发人员参与 Review,比如一起开发某个功能,某个项目,或者一起参与了方案设计讨论并给出了有价值意见的研发。
-
获取意见。找有相关经验的资深研发帮忙 Review,比如 Java 语言资深的研发、写过相同或类似系统/功能的研发。
-
形成共识。如果涉及到不同团队或模块间的接口改动,或其他会影响其他人的改动,可以邀请相关团队或模块的接口人参与 Review,以对改动形成共识。
-
质量把关。对于重要的代码库,可能会执行比较严格的质量把控,如果设置了必须的 Reviewer,这些 Reviewer 也会参与进来。
-
变动告知。很多情况下一个代码库可能只有一个人维护,如果做了些比较特殊的变动,其他人很难发现。因此在做一些重要的但是理解起来不那么直接的地方的时候,最好告知一下相关的研发,以便他们能大概知道发生了什么。
(4)都 Review 些什么
经常会有 Reviewer 拿到 MR 不知道该 Review 些什么,其实无论你参与对应项目的深入如何,都可以对代码进行 Review,也鼓励不同人从不同的深度、角度去帮助 Review。代码 Review 没有固定的形式,它更像是一门艺术,唯一的提高办法就是实际参与进去。Review 的时候可以从以下几个方面入手:
①简单的 Review
在 CI 通过的情况下,最简单的 Review 方式可能只需要这样:
Reviewer:在实际环境中都验证过了吗?Author:当然验证过了Reviewer:LGTM
这是一种提醒式的 Review。确认一句:是否在环境中验证过了,或者进一步把能想到的重要的验收点提出来确认一遍。即使是这种最简单的 Review 实际上也是有价值的,很难保证所有研发都会在提 MR 前实际在环境中验证自己所做的修改,也很难保证单元测试、e2e 测试能 Cover 住所有的情况,Reviewer 基本上也不可能都自己去环境上跑一遍。让 Author 去确认实际上就是提醒 Author 去确保改动至少是真实有效的,尤其是对一些已发布版本的 Bugfix,一定要提醒实际自测通过。类似的提醒还包括:相关的文档(外部的)是否相应更新了、这个改动是否会有兼容性的问题、性能是否有影响。他们的本质就是提醒 Author 自己去思考他们可能遗漏的问题。
②常规的 Review
代码 Review 一般都会从代码风格、变量命名、语法统一处入手,当然这些应该更多的借助于 CI 等自动化手段来保证,但是在相关流程还不是很完善的前提下还是有必要进行关注。此外代码可读性、代码健壮性、代码可扩展性都是 Review 时关注的点。
(5)如何进行
Review 过程中鼓励 Reviewer 大胆 Comment,有不理解的地方,或者觉得不合适的地方都直接表达出来,Author 对 MR 的 每个 Comment 也要做出反馈,无论是展开讨论还是简单的给个 OK 都是有效的反馈。Review 的过程可以是:
-
Author 在各项确认工作完成后,发起 Review,如果比较急,可以给重要的 Reviewer 发消息请求帮忙 Review。
-
Reviewer 看到 MR 后应该先确认 MR 的背景和目的,如果不清楚也无法从 MR 中获取该信息,最好直接和 Author 沟通。
-
Reviewer 直接在 MR 上提出自己的建议或者问题。
-
Author 对每个 Comment 进行反馈,并展开必要的讨论。
-
复杂的话题可以采用线下讨论以提高沟通效率。
-
Author 处理完了所有的 Comment,也修改了代码后,需要在 MR 里 @ 一下相关 Reviewer 告知所有优化已经提交,如果时间比较急也可以直接和 Reviewer 沟通。
-
Reviewer 确认没问题,给 MR 进行 Approve,一般简单的回复是 LGTM(Lood Good To Me),也可以对 Author 的工作进行赞赏,比如 “God Job” 等。
-
Approve 后 MR 由谁来合并这个看自己选择。
-
如果 Reviewer 提供了很多有用的建议帮助优化代码,Author 也可以礼貌性地感谢一下 Reviewer。
(6)参与者该抱着怎样的心态
①Author
首先需要明确一点,是 Author 自己对代码的质量负责,因此应当怀着感恩的心去看待坚持认真帮你 Review 代码的 Reviewer,因为并不是所有你加的 Reviewer 都有时间和精力来帮你提高代码质量。
也正式因为 Author 是自己代码的 owner,所以不要依赖于 Reviewer 去帮你守代码质量的大门,像 “代码 Review 的时候你怎么就没看出来”,“这不是你建议我这么做的吗” 这样的话千万别说。Reviewer 只是帮你提高代码质量,因此我们该做的工作都要去做,比如细致的 Reviewer 可能某些情况下直接提出了代码优化的建议,Comment 时贴上了优化的代码片段,Author 不能直接假设它一定是能正常工作的,而应该对它进行完整的验证。
对 Reviewer 给出的 Comment,不要有抵触的情绪,对你觉得不合理的建议,可以委婉地进行拒绝,或者详细说明自己的看法以及这么做的原因。有时候一个你觉得不合理的建议可能代表一个新的思考角度,也可能代表 Reviewer 自身代码能力上的不足,无论是哪个,无论最终是 Author 还是 Reviewer 得到了提高,都应该是好事。
②Reviewer
Review 代码既是帮助提高代码质量的过程,也是 Reviewer 提高自己代码能力和沟通能力的过程。因此应该在 Review 的同时保持一个学习者的心态,既要发现对方代码中的缺陷,也要努力去发现代码中的亮点。切记单纯以挑毛病的心态去 Review 代码。
有不少 Reviewer 在写 Comment 的时候会犹豫,担心自己提出的问题或建议比较“蠢”,因此犹犹豫豫下看完了代码抱着一堆疑虑最终啥也没留下。其实在代码 Review 的时候大可不必有什么心里负担,有什么疑惑的、不清楚的地方或者有什么自己的想法,可以直接提出来,有时候一个简单的 Comment 就可能会激起 Author 和你的 Comment 毫不相干的新思路。再者你即使没帮 Author 提高代码,让 Author 帮你提高思考不也是建不错的事情吗。
Reviewer 也不需要去关注自己的“产出”,并不是一定要提出一堆问题才是好的代码 Review,Author 代码写得很棒也是很正常的,如果从你的角度觉得代码没问题,大胆给个 LGTM 甚至是 Approve。
()Code Review的实践
-
预留CR的时间
-
CR的形式。一种是设立一个特定时间,例如每周或者每半月等等,团队成员一起对之前的Merge Request进行CR;另一种是对每次的Merge Request都进行CR。第一种定期CR,Merge Request的数量太多,不太可能对所有的MR进行CR,如果CR之后再对之前的诸多MR进行修改成本太大;而且一次性太多的CR会打击团队成员的积极性。第二种MR相对就轻松的多,可以考虑轮班每天设置2-3人对当天的MR进行CR即可。
-
CR的时机。CR的环节应该设立在提测环节之前。因为CR后如果优化代码虽然理论上只是代码优化,但很可能会对业务逻辑产生影响,如果在提测时候,那么可能会影响到已经测试过的功能点。
-
Reviewer。指明review的级别。reviewer再给相应的代码添加评论时,建议指明评论的级别,可以在评论前用[]作出标识,例如:
-
[request]xxxxxxx:此条评论的代码必须修改才能予以通过
-
[advise]xxxxxxxx:此条评论的代码建议修改,但不修改也可以通过
-
[question]xxxxxx:此条评论的代码有疑问,需reviewee进一步解释
-
讲明该评论的原因。在对代码做出评论时,应当解释清楚原因,如果自己有现成的更好地解决思路,应该把相应的解决思路也评论上,节省reviewee的修改时间。
-
平等友善的评论。评论者在review的过程中,目的是提升项目代码质量,而不是抨击别人,质疑别人的能力,应该保持平等友善的语气。
-
5.结对编程
是一种敏捷软件开发的方法,两个程序员在一个计算机上共同工作。一个人输入代码,而另一个人审查他输入的每一行代码。输入代码的人称作驾驶员,审查代码的人称作观察员(或导航员)。两个程序员经常互换角色。在结对编程中,观察员同时考虑工作的战略性方向,提出改进的意见,或将来可能出现的问题以便处理。这样使得驾驶者可以集中全部注意力在完成当前任务的“战术”方面。观察员当作安全网和指南。结对编程对开发程序有很多好处。比如增加纪律性,写出更好的代码等。结对编程是极端编程的组成部分。
6.热点前的准备工作
(1)应急演练
无论对一个软件系统运行原理掌握得多么彻底,也不能阻止人犯意外错误。应急演练可以定期举行。前提是对各种意外情况,提前准备好了预案。预案在演练过程中,可以发现系统问题、检验相关人员SOP/EOP的操作熟练情况。
举个例子:
支付系统由于下游银行通道能力参差,需要制定关闭XX银行通道的SOP,并进行演练。
应急演练一般要求级别较高的人员进行组织,确保其对突发情况有一定的应变权利,同时也能敏锐的发现新问题,确保效果。应急演练我个人总结要分为4个步骤,实际上也是标准的PDCA方法的步骤:
-
提前通知,确保参加人员掌握了需要的知识。同时同步到应急演练的目标、相关文档、时间、地点、参加人员
-
演练开始时第一步是告知大家演练的目标、流程和检查项目,比如过程中会检查大家对SOP/EOP的操作熟练情况,如果不熟练则会进行通报。
-
按流程步骤进行演练
-
进行演练总结,制定改进计划
在实际进行过的演练中,上面提到的第二步做的不是很好。可能是作为一项例行事务,演练组织人员习惯于这项工作,认为没有必要重复说明。实际上我认为这是最重要的一步。因为第一,每次演练可能会有一些新人加入,他们不了解背景。第二,大家最后可能只记得演练的一个目标,把优化流程、找问题这些事情忽视了,演练效果大打折扣。
(2)重启服务
Java服务如果长时间不发布,没有任何bug的情况下也会内存缓慢增长。因为JVM申请了的内存,只要进程不死就不会释放。虽然咱们JVM参数里指定了堆的大小和每个线程占用的大小。但是程序运行过程中还会不可避免的申请很多堆外内存。比如数据库操作就 会产生很多堆外内存。我负责的服务就发生过一个服务近1年没有任何发布升级,内存比刚重启后一周增长5%的情况。除了内存,重启还能避免很多慢性问题在一个关键点爆发。所以也热点和秒杀保护的一个重要举措之一。
VIRT(虚拟内存)
-
进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等;
-
假如进程新申请10MB的内存,但实际只使用了1MB,那么它会增长10MB,而不是实际的1MB使用量。
-
VIRT = SWAP + RES
RES(常驻内存)
-
进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量;
-
包含其他进程的共享;
-
如果申请10MB的内存,实际使用1MB,它只增长1MB,与VIRT相反;
-
关于库占用内存的情况,它只统计加载的库文件所占内存大小。
-
RES = CODE + DATA
SHR(共享内存)
-
除了自身进程的共享内存,也包括其他进程的共享内存;
-
虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小;
-
计算某个进程所占的物理内存大小公式:RES – SHR;
-
swap out后,它将会降下来。
它们之间的关系用一张图来表示就是
(3)扩容
微博历史上曾发生过许多次服务器崩溃的情况。这种情况大多可以通过提前扩容解决的。但是一直停留在扩容状态经费上有问题:一台服务器每年成本按3万来算,100台就是300W。热点流量带来的收益并没有高。近几年容器技术突飞猛进,对于热点和秒杀等场景,有的公司已经做到了弹性伸缩。就是根据流量情况动态调整服务的集群机器数。公司还可以和云厂商合作,让厂商提供动态扩容能力。
对于大公司而言,其实像阿里云、腾讯云这种云服务器的成本要比自己管理服务器成本要高。当然最贵的是亚马逊云,这是题外话。像微博这种临时扩容场景,服务器费用收取是按秒来计费的。不管怎么说,很多热点事件来临前,提前扩容是可以解决问题的。所以,容器技术的一个重要指标就是创建容器的耗时,有的团队已经做到30s可以创建一个容器。意思是点击申请容器到容器上的业务镜像启动提供服务只需要30s!