开发小结-流程管理类-下篇
改Bug和优化要不要同时进行
个人觉的,改Bug和优化,当优点的点和改Bug的点紧密相关联时时,改Bug和优化可以一同进行。而对于那些不怎么紧密的代码,优化可有可无时,那坚决不要优化。比方说,最开始进行释放内存,使用delete p; p = NULL
;后来发现项目中已经有封装好宏,只需要一句话就可搞定。不过在使用该宏时,需要引入头文件。那么,这种情况下,就可以不进行优化,原来怎么写,现在就这么写。保持在同一个模块(.cpp)中,相关操作的一致性即可。
从冗余的实现到既可以满足业务功能,又保证每行代码最优,在下手前,需要反思思考斟酌,这是新手迈向高手的必经之路。
找Bug经验
解决Bug,很多时候,不存在既能够减少改动范围和影响范围,又能很好解决问题的方案,为了平和开发成本和测试成本,很多时候,为了控制改动影响,会倾向于选择“消除现象”,而不是找出根源来解决问题。
屏幕录像找Bug
测试一些不容易重现的Bug时,可以借用FastStone
的屏幕录像功能,来找到Bug触发的最短路径,具体操作方法如下:
通过屏幕录像,把在相关操作都记录下来,直到出现崩溃提示为止。反复观看,梳理一些不必要的动作,直到找出触发Bug的必要路径,不断精简路径,直到找到最短路径为止。
使用此种方法时,需要有以下前提:
- 测试反馈此Bug是进行了若干操作后,会有很大几率会出现,但不知是什么操作触发的,只有最后出现崩溃的画面。
- 需要使用测试人员发生崩溃的版本来测试
二分法找Bug
在开发过程中发现,A模块出现问题,而在几天前,这个模块是没有问题的。通过代码回滚,可以明确若干天前的A模块没有问题,而今天的A模块有问题,通过二分回滚查找,可以逐渐把范围缩小,最终定位到是哪一次提交造成A模块出问题,常见都是某一次不相关的提交,间接又间接的造成A模块出问题。
接口变更造成的Bug
有些Bug是因为调用其他方提供的接口,如果因为接口提供方的重构,导致接口参数改变,而调用方没有做针对性的改变,就会出现Bug。
此类Bug的修复,建议自己先排查出来,然后交由接口提供方去修改,因为这是它修改接口导致的问题,在调用方这里,只知道调用方这里的实现,而不会注意到其他开发人员调用该接口是否也会有问题出现。
有些因为接口导致的错误,由接口方来修改或者界面方来修改都可以的情况下,接口方修改,不仅仅可以针对当前这个界面,对以后其他新增界面也可以适用。如果有界面方来修改,那仅仅只能针对当前界面,如果有新增界面的话,则很有可能会遗漏. 针对这种情况,建议接口方做修改比较好。
提优化的Bug
开发事先的和需求要求的一样,不算Bug。如果测试认为需求文档上面实现的不美观提Bug修改,那这种Bug不算是我的Bug,算是需求的Bug。这种Bug的产生是需求里面没有定义的细节,而测试认为默认实现和它心里的不一样而产生的。
因此,我自身的建议是:优化类的建议和Bug需要区分开.
一是,两者判断的依据不一致,
二是,两者发起人可能不一致,优化类可能是开发人员自己发起的,也可以是测试人员主动发起的。可能某些优化,在界面的功能上是体现不出来的,需要和后台一起来做判断。可能有些优化,是各个界面上因为操作的不一致性而提出来的,这种问题的出现,是因为之前就没有统一的标准,新界面走新标准,旧界面保持不变,那么,在遇到这样的情况时,需要限定修改和测试的范围,以防止无止境的类似的优化建议提出。
进度评估
一个项目的完整流程,基本包括需求设计,视觉和交互设计,开发编码,测试,上线,运维,发布新版本等几个环节。
从用户的角度来看,如果上线后功能无法正常运行或者运行经常崩溃,那就是没正确的完成。
从开发的角度来看,自己负责的模块完成并且自测通过,后续交付给测试测试,是不是可以认为自己这部分功能已经完成了呢? 这要看完成的评估标准了,如果是以软件发布为标准,那个人模块的提交还算不上完成,得集成测试通过后正式发布,才算完成。那个人自测通过交付测试后,这个进度怎么去描述呢?量化的描述方法是不合适的,只能这样说,进度到,已完成功能的开发,并且交付测试测试阶段。
从整理角度来看待,项目进度可以从两个层面去看待,整体进度(需求设计,视觉和交互设计,开发编码,测试,上线),具体到每一个子流程中,每个人负责各自的进度(未开始、已完成A,B功能,已完成A,B,C功能,还剩D功能,已完成,这几个阶段),作为开发人员,考虑的着重点落在已分配的任务,已提交测试的任务两个点上。
无论是开发新功能,还是重构已有功能,工期估计是很重要的。虽然都说,计划赶不上变化,如果仍由变化任意发展,自己就是在进行毫无章法的工作,从时间安排上来看,就是用战术上的勤奋掩盖战略上的懒惰。下面分别谈谈新功能开发和重构的工期估算:
- 新功能开发,如果该功能是之前类似的模块,可以从项目管理工具和SVN提交记录上查看,从自己接收到此任务到完成所有功能后提测,并且最终通过测试的时间段,以该时间段作为参考因素。另外,从该功能涉及到的业务流程、依赖的第三方数据等进行综合考量,按照每天6个小时的有效工作时间来算,将得到的最终小时数再乘以1.5的系数后折算回天数,乘以系数是因为项目过程中总会有那么些意外情况发生,可能用到了自己不熟悉的库或者接口之类的。
注意:如果开发功能涉及到与其他同事合作对接,若不清楚相关业务,最好将此功能交给熟悉的同事来确认完成对接所需的时间,不能贸然代表同事回答对接时间,不能因为看起来很简单就直接确认期限。对于同事来说,也一样,大家都是为同一个目的而工作,不要因为自己的缘故耽误别人以及整个项目的进度安排。
- 重构开发,根据需要重构的功能点,每一个功能点评估下所需时间,将各个功能点的时间汇总起来,构成总共需要的时间。
影响评估
对修改要心生敬畏。评估改动影响时,可以按照如下框架来思考:
- 应用场景分析:
1.1 是否高频(例如每天5次)
1.2 是否高危(影响范围较大)
完整的场景是如何的,本次变更属于哪个环节,需要满足什么样的条件?上线后如何确认功能是否正常
- 影响范围分析:
2.1 影响哪些系统
2.2 影响哪些功能
2.3 影响哪些部门
越是临近发布时点的修改,越是严格控制修改影响范围,想清楚了再去做。
假如不能评估修改的影响,宁可不改,也不要乱改。与此同理,假如基于目前的开发进度,不能去评估完成一个新功能的工期,或者说很难去评估的准确,那么在自己的心理预期上乘以2倍或者3倍。当碰到解决不了的问题时,在自己在尝试了多种解决方法后,及时反馈上级,请求更多资源协助。
开发回顾
每做完一个功能模块,要进行复盘,梳理回顾在实施过程中,有哪些做的好的地方,哪些做的不好的地方。
对于刚开始着手做这个模块时的一些工时预估,难度的预估,沟通的预估,和真正完成这个模块后的实际估计,看看自己哪些预估是正确的,哪些预估是偏差较大的,如果偏差较大,回顾自己在开发时的工作状态,看是哪一个节点上卡壳,导致工期延长,仔细分析原因,有可能是其他人员的接口配合,后台的数据配合,也可能是自己预估的太乐观等等,开发是在不断迭代进化的,及时的复盘,对完善自身,提高自我的项目管理能力大有裨益,切记,切记。
- 对工作岗位负责
- 当在工作时,就要在规定的时间内,全神贯注的工作,哪怕事情再多,也要一件一件地进行,做完一件事情再做另外一件事情。当在休息时,就必须完全休息.
- 及时做好自我反省,记录在开发过程中的心得体会,以便在下一次任务来临时,能够精益求精,不断进步。
- 留给自己一定的思考时间,在真正着手开始干活之前,在脑海里面梳理一片 要解决的问题是什么,该如何做,怎么做才能更好,想清楚,画出来再动手。
- 失败后不要找借口,失败就是失败,没什么好推脱的,哪怕原定计划因为不可抗因素破坏而失败,不要说因为这个那个,找原因比抱怨更好。从失败中去找原因,记录这个原因,在下次做类似决定之前,回顾下自己失败的原因。因为一旦你为自己的失败找了借口,那么下次失败还会再找借口,到最后,整个项目都会失败的。
心态管理
公司不是学校,公司支付你的薪水,不是让你深造技术,而是希望你替老板解决问题。在业余时间,你可以探究喜欢的技术,但一旦到了工作场合,你就应该思考如何高效、准确、敏捷完成产品提出的需求,无论这个需求有没有技术含量,若该需求的实现会破坏现有的架构,那么从实施成本和收益上做出自己专业性的判断。
除了专业技术的进步,业务规则和业务流程也需要关注,多思考新技术与既有业务的结合点,通过代码评审、技术分享等提高其他成员的技术能力。如果能做到这一点,相信你会迅速成长为团队骨干。
分支管理
现有的开发实践中,采取开发分支和发布分支双线并行的模式。平时,大家都是在一个开发分支上工作,当项目需要对外发布版本时,从开发分支中拉取一个分支当做发布分支(例如V1.0),后续发布版本的需求和Bug修改均在V1.0分支上完成,测试同事也在发布分支上工作。
越是临近发布节点时,对发布分支上的改动越是要谨慎,改动范围能小则小,不是万不得已的修改,尽量不要提交。如有一些牵一发而动全身的修改,会造成回归测试压力过大,延误发布时机。待到发布分支逐渐稳定后,达到可以发布的状态,等发布上线后,再由各个开发人员将各自在开发分支上的提交逐次合并到主线分支上,大家继续开发下一个版本。
对于已经发布出去的版本,对应的代码库应该设置为禁止提交,要完整保留发布时的代码库以及相关的调试信息,这有助于分析已发布版本的问题。
针对开发和发布分支双线模式,我的习惯是,在本地建开发分支,重构分支和发布分子。新功能开发在开发分支上做,改Bug在发布分支上做,及时合并会开发分支。在重构分支上,做一些重构性的工作。三个分支各司其职。
每次提交作为一个最小完备的功能集合,目的唯一性。如果有些功能的实现涉及到多处改动,那么需要有计划、有意识地去划分一个大功能的各个子功能,每次提交一个明确的子功能,由此逐步构建一个大功能。
在平时的工作任务安排中,需分清轻重缓急,一定要把自己手上现有的Bug都处理完后,才去做自己任何合适的优化和重构工作,千万不要自以为是的做一些感动自己的事情。完成公司的任务是第一要紧的事情,是首要要解决的事情。
时间管理
在新接收到一个需求时,分配到 需求分析、设计、实现和自测上面的时间安排,推荐为4:3:2:1
为什么这么分配时间呢?经过多次工作实践得来的。当需求不明确,那么关于这个不明确的地方,怎么开发都是不合适的,为了解决因需求不明确导致的后续设计和实现阶段的返工,在需求分析阶段,需要根据需求画出自己理解的 用例图、状态图和主要流程图等。这些图是需求本身所涉及到的,在一个系统中,这个需求实现的功能和其他功能是有关联关系的,比如说弹出非模态框,如果程序中已有一些弹出非模态框的部分,新增的功能也要弹出非模态框,那么这两个功能就有前后的关联了,是同一时间只出现
一个,还是前后依次出现,后出现的覆盖前面出现的,还是新增功能的框始终在顶部,其他框在后面,等等涉及到与已有实现的关联关系,这些都需要进行额外的确认。
产品人员给出的需求,很大程度上,不可能考虑所有与之相关的其他对象的交互,而在整体行为上,该框的出现,影响了什么,只有到开发阶段才能发现。
引入第三方库
对于引入的第三方代码,一定要全部吃透,或者说是对可能的异常进行捕获处理(缓冲区溢出无法捕获)。
要不要引入一些 难以维护的第三方代码?或者说,在引入第三方代码时,需要注意些什么?
- 看应用场景。
如果是关键路径上的关键应用,对于引入的第三方,务必要完全吃透。这里吃透的意思指的是,不光是看它能够实现什么,更重要的是看它没能实现什么,后者往往在业务中是很重要的。它不能做什么比它能够做什么更重要。
如果是非关键路径上的应用,对于第三方要进行自己的封装,并且尽量少用第三方的高级功能,而是自己通过简单功能来组合实现。
- 考虑引用第三方库的一些负面效应
比如,第三方库使用的 运行库配置 需要和调用方保持一致,这可能会影响主工程的相关配置。
商业提供的第三方库支持,如有必要引入,则可以引入。
对于开源的第三方库,有几点需要考虑的地方: - 是否一直有技术支持
- 文档是否齐全
- 使用以后,组内是否有人能够hold主,如果hold不住,果断放弃,找一个能hold主的
- 该第三方库是否有其他公司在使用,是否有经验可以借鉴
- 社区是否活跃
在调用第三方服务时,要时刻保持怀疑态度,不能因为第三方的原因,而拖垮自己的服务,做好超时机制以及重试机制的处理。重试机制要合理设置,若是因为是业务导致出错的,在UI上面要做好控制,防止用户重复操作。若是因为网络原因导致的,则需要选择合适的超时策略和提示机制。
任务管理
一个大的任务往往可以细化为几个子任务,设定规划好子任务的目标和时间安排,分派子任务给其他人员去做。
自己在工作时,讨厌别人在旁边指指点点。这一点,作为干活的人和指导的人,都是一样的。干活的时候,不喜欢别人对自己的工作方法和工作流程的指点,而人人都有一种好为人师的心态,在看到别人低效的工作方式,往往会忍不住去说两句,起到兴头上面,还会主动出手去干预,纠正。
对于指导者来说,这好像是一种经验上的优势带来的心理愉悦感,而对于被指导者来说,这像是在被打脸,内心深处有一种压迫感和强制打断感,往往会引起厌恶
即使这个时候给出的建议的确是有效的,但是也往往带来不了切实的效果,别人还是用他一套旧的方法。
提意见的方式很重要,基于上述的考虑,结合自己看的书籍,得出了几点心得:
- 在自己工作或者帮别人干活时,先听清楚别人的需求,然后说,我在干活途中,请不要打扰我!每一个小的阶段,我干好了,会主动给你看阶段性的成果。
- 在别人正在干活时,即使别人的工作方式不切当,千万不要当场指出,而是在心里或者找个东西记录一下低效工作的步骤,
重点分析在哪几步耽搁了时间,就像profile一个程序一样,找出花费时间最长的函数,然后专门优化此函数。针对最影响效率
的操作,提出有可操作性的改进方法。如果可以的话,可以主动演示操作,让别人体会到使用新方法而带来的好处。
作为管理者,面对手下员工的工作,自认为想到的第一件事不是优秀,而是可控。可控的意思是,他们在做自己安排给他们的事情,
一旦他们做完了,能够得到及时的反馈和通知,当他们遇到问题时,他们能够主动的去向我寻求帮助,而我也可以适时的给出专业性
的方向. 作为下属,如果做完了上司交代的工作,需要主动告知,还需要做什么?如果有新的任务安排,就取做新的任务,如果没有,
那就做自己的。
表达管理
要讲清楚一件事情,首先自己要深入、细致地了解这件事情,其次在自己的大脑里面要梳理总结关于这件事的重点信息,条理清晰的列出来,划分主次,分清重点,考虑到讲解对象的理解程度。
在一件事情尚未能明确拿下之前,不要贸然对外宣布,一旦答应客户的事情,就一定要尽全力去做到,定期跟踪客户反馈的事情,及时作出回复。面对他人的请求,拒绝是常态,坦然面对拒绝,理解拒绝,正确处理拒绝,抓住需求点,持续提供服务。
思维模式和心态比才华更为重要,注重自我内驱力的培养,自我激励,敢于承担责任。
刻意培养对外的表达能力,一个公司是各种角色的集合,像老板、设计、HR、外包乃至前台测试,仍然要通过自然语言而不是机器语言的实现,能够适时把肚子里的聪明才智绣出来,能够恰当的把功劳业绩拿出,自然而然会成为受欢迎的人。随着平台的扩大,表达也不限于一对一的沟通,向上汇报、规划脑图、总结邮件、技术指南、PPT演示等等,是专业职场人士必须要精通的技艺。
将复杂问题深入浅出,说的清楚生动,是一门很重要的能力。
开发的品味
实现一种功能可能有多种实现形式,有简单的,也有繁杂的。在开发过程中,可能是基于现有代码进行二次开发,也可能是另起炉灶开发,不管如何,在保证正确性的前提下,争取写出简单直接,逻辑清晰明了的代码。在阅读代码时,看到已有代码是如何实现业务目标时,要有自己的品味,在实现类似功能时,不能一味照搬借鉴,而是选择性的吸收改进。
可在团队中,定期选择一个工作认真的人,每周选取一个时间段,专门做代码规范和最佳实践检查,坚持一段时间后,整个团队的代码规范执行力度将会得到明显提升。
团队的每日构建,规定,无论是谁提交的代码导致无法编译通过,第一次口头警告,第二次请整个项目组喝咖啡,目的是不是为了请喝咖啡,而是真正做到令行禁止,让所有人在提交代码时,对自己提交的代码有顾忌,慎重,从整个团队上来看,可以较好的实时规章制度。
我今天写的代码,如果遇到功能改动,会不会修改起来很困难?如果可维护性差,那么该如何改进?然后再进一步考虑下,当前面临的问题场景是否能够与设计模式中的一种或多种匹配上?如果能的话,该怎么用设计模式的思路来改进?
不能仅仅只是做好当前任期的事情,每个人在公司内都有一个定位,做好自己职责范围内的事情是理所当然的,但这仅仅只能保证你不失业,想往前走,还远远不够。所以我们平常做事,要从这你的下一个职业去做,机会永远只留给有准备的人。
带着问题去学习:学习东西不能为了学而学,必须要有自己的目的,不然你都不知道你学习的边界在哪里了。从边界这个角度出发,改Bug的边界和重构的边界,他们需要清晰的确定吗?我的回答是,需要,特别需要。
每过一段时间,回过头来看之前写的代码,一定会有想要修改的冲动,此时,绝对不能修改已经过测试的代码,在既是优化改进不会影响到关键业务,也不要修改。取而代之的是,在收到新需求时,吸收旧代码的经验教训,每次写的比上次更好一些。
在同一个项目中,保持简单一致性,如果使用printf+read/write,那为了规整,在该项目的其他地方保持一致。如果使用了c++的ios流,那么也保持一致。
版本号管理小结
Windows风格的版本号一般形如A.B[.C[.D]],其中,A为主版本号,B为子版本号,C为修正版本号,D为编译版本号。
- 当项目进行了局部修改或者Bug修正时,修正版本号可加1;
- 当项目在原有基础上增加了部分功能时,子版本号可加1,修正版本号归0;
- 当项目进行了重大修改或者局部修正积累较多,导致项目整体发生全局变化,主版本号加1.
- 编译版本号一般是跟随编译过程自动生成的,常见的有取当前svn的提交编号或则git的提交编号,便于跟踪定位发布版本。
如果是较小的工具程序,可以只保留一份最新程序即可。
如果是跟随主程序一同对外发布的小程序(比如升级程序、卸载程序、注册程序等),则需保存历史发布版本,以备查问题,自己的工程实践目录结构如下,可供参考:
---tools
------history
------------1.0.0.123(123为SVN提交编号)
-------------------a.exe
-------------------b.dll
-------------------c.pdb
------------1.0.0.124
------release
------------a.exe
------------b.dll
------ReadMe.txt
对于对外提供的小工具,需要给出相关的使用说明,具体提供方式,可以是截图+说明文字的方式,也可以是简要的帮助文档等,便于他人使用。
针对工具类小程序,每发布一次程序,都要写好ReadMe.txt
,作为版本发布记录,该文件中大概有如下内容:
- 使用方法
- 程序维护人以及联系方式(邮箱、电话等)
- 源代码的SVN库路径、最新发布程序路径
- 各个版本的更新记录