• 开发实践思考(二)


    本篇接上一篇《开发实践思考(一)》,继续将之前散落的思考点汇总,每篇10条。

    1. 同层级的判断只在当前层级生效,不能跨层级保证

    举一个简单的例子:

    
    bool Fun1(const char* pData)
    {
    	if (NULL == pData)
    	{
    		assert(0);
    		return false;
    	}
    
    	// XXXXXX处理
    
    	DetailFun(pData);
    }
    
    bool DetailFun(const char* pData)
    {
    
    }
    
    
    

    提问,在DetailFun函数中,需不需要对pData再做非空判断?
    观点A:外层调用者已经保证pData的有效性,DetailFun内部无需再次处理。
    观点B:DetailFun函数内部对入参也要做有效性判断,因为不能保证它被其他函数调用时,其他函数也做了同样保证。

    笔者的看法:同层级的判断,只能保证同层级的有效性,一旦将数据传给其他模块,合法性就交给其他模块来鉴别,而不要自身在多做一层判断,如果有效就传给其他模块,如果无效就不传。

    小结:每个函数只需要关注自身入参的有效性,要做到,无论在什么环境,都不会因为外部入参的错误而导致自身出错。

    2. 不要被别人写的代码误导

    别人写的不一定是最好的,如果只是简单的仿照继承,那无助于成长。

    在平时工作中,免不了维护旧代码。对旧代码有两种态度:

    态度1:旧代码跑了这么旧,它这样写,猜测应该是有它的意图,可能是应对某种特殊情况之类的吧,目前不知道,因此,新的实现照搬原来的写法。

    态度2:在仔细分析旧代码流程发现,原来的写法是暂时性的解决方案,有一股“弄巧成拙”的碰巧感和“短平快”的紧急解决方案。

    笔者的看法偏向于态度2,很多时候,面对问题,通常有两种处理方向:

    1. “短平快”的解决方案,一般改动范围小,加个else/case,加个虚函数重写之类的,能屏蔽或绕过问题的触发条件,使其缓解,但通常不优雅,加大耦合。

    2. “彻底的”的解决方案,从问题发生点逐层上推,直到问题根源,一路顺着调用关系链条来彻底改正。同时,检查工程中其他类似的地方,将同类型的问题一并解决掉。

    这两种处理方向都有各自的使用场景。从长远来看,应尽量少一些特例、特殊处理,更多的是通用问题的通用方法。如果当时迫不得已那样做,后续也要标记下,用更为通用、优雅的方法来解决。

    3. 代码提交保持单一职责

    每次提交只保证做一件事,提交的所有修改都聚焦于这件事。根据自己的经验,可将代码提交按照目的分为以下三类:

    1. 改Bug
    2. 实现新功能
    3. 代码重构

    在提交代码时,针对以上三类目的,要有明确区分,尽量不要混在一起提交。

    有时候,场景1和3可以一并提交,但要限制重构范围,重构与此Bug密切相关的地方,那些不相关的重构,不要混杂在一起。

    4. 程序正确性问题

    从测试的角度来说,要证明程序有问题,很简单,构造各种场景,看实际输出与预期输出是否一致,只要不一致,那就说明程序是有问题的。

    从开发的角度来说,如果想向别人证明,自己的程序是很少问题甚至是没有问题,是非常难的。

    因为从逻辑上来看,这个类似于有罪判定。默认情况下,人都是无罪的(类似于程序都是正确的),谁怀疑他有罪,谁就提供证据,将举证责任交给提出假设的一方是惯例。

    还有一点,从逻辑上说,证有不证无。你只能证明某一个人有罪,无法证明一个人无罪。

    回到开发上看,开发自测时,只能尽可能测试所有能想到的可能场景,在已列出出的场景范围内,可证明是没问题的。测试要做的是穷举尽可能多的场景,至于到底有多少个场景,有多少个路径,每个人的经验、看法不同,难以达成一致。

    开发和测试能做到的,在自己能力范围内,尽可能构造场景并发现错误,但无法杜绝问题的产生。

    5. 枚举定义以及辅助函数定义在一起

    定义枚举时,建议将对应的辅助抓换函数写在一起,这样的好处是减少后续新增定义时,忘记在转换函数中添加对应入口造成的潜在的错误。

    6. 显式送参优于隐式

    当接口文档中有这样描述入参,“送空和送0是一样效果”,那建议显式的送0,而不是送空。这样做有如下好处:

    1. 清晰直接
    2. 如果后续结构有新增入参,那么之前的入参可以一一对应地上,而不靠着隐含的空字符串

    此条同样适用于函数默认参数,笔者觉的,函数默认参数会加大调用者的心智负担,在传参数时,显式送参优于默认参数,少用默认参数。

    7. 谨慎处理特殊值

    针对"0"、""、" "和"-1(无效值)"等特殊数值,在业务判断中要特别处于,要明确区分上述情况下的处理。

    8. 提交Bug时关联类似Bug

    在解决Bug时,如果感觉之前有解决过类似Bug,这种情况,可以在此Bug的备注中,注明与之关联的Bug号,提醒测试在测试时注意下。

    如果此BugA是因为修改另一个BugB导致的,那更需要在备注中,将BugB的改动导致BugA的修改简要说明下,有助于完整描述BugA的生命周期。

    9. 会议的会后总结

    凡是进行会议,无论是电话会议还是现场会议,在大家讨论过后,需要有会议记录员记录在会议上的决定,记录哪些问题是在会议上确定的,哪些是待定的,哪些是新增的,这些由会议记录员来记录,并将上述事项发给参会人员以及那些无法参会但有重要关联的人员,同时@相关人员,将会议上已确定的事项进行分派,便于问题推动以及跟进。

    10. 沟通转述问题

    在答复测试的疑问,有些点需要向其他人员进一步询问再答复给测试。在得到其他人员的回复后,在转述会给测试时,不要简简单单的截一个与其他人员的沟通截图,让测试自己去揣摩结果,也不要将其他无关的沟通细节回复给测试,应当提炼与此问题紧密相关的结论,并以简洁精炼的方式来回复。

    在给别人传输文档时,除了文档名称要见名知意外,还要附加一句简短的文档说明。

    在传给别人图片时,较好的操作是在图片中添加说明,以画框、高亮、简洁文字说明等方式都。

    为了防止沟通中的理解偏差,可以将别人给的答复,用自己的话转述一片,让别人再次确认,类似于TCP的三次握手中的第三次确认过程,达到对该问题的一致理解。

    作者:浩天之家
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
    Top
    收藏
    关注
    评论
  • 相关阅读:
    访问修饰符的权限。
    字符编码
    3/11 作业
    3/10 作业
    作业 3/9
    流程控制之for循环
    Exception in createBlockOutputStream
    windows上传文件到 linux的hdfs
    win10 配置 hadoop-2.7.2
    hadoop 源码编译
  • 原文地址:https://www.cnblogs.com/cherishui/p/15129003.html
Copyright © 2020-2023  润新知