最近和几个刚毕业的同学聊天,谈到优秀程序员的标准,即兴讲了几点。事后想想这个问题还挺有普适性的,值得记录下来与大家分享。
总的来说,我觉得优秀程序员与普通程序员相比,在四项能力上有明显的差异,分别是有单元测试习惯,代码可读性高,高质量的重构能力,良好的抽象思维能力。
1. 单元测试
程序员的基本要求是完成代码开发工作,让代码正行运行起来。在我们尝试运行一次,刚好得到预期的输出结果,到这里工作只完成了一半。
因为还有若干输入,会让程序得到错误的输出或者说是不在开发者预期范围内的输出。而单元测试的目的是为了证明在各种输入情况下,程序代码几乎都能够按照预期运行。
可以说,单元测试是从程序偶然正确到程序大概率正确之间的最重要方法,是优秀程序员最基本的要求。
单元测试是最典型的白盒测试,对Java技术栈来说,测试工具就是JUnit,其提供了测试代码的编写框架。单元测试完成情况的主要度量指标是代码覆盖率,又可以细分为行覆盖率,分支覆盖率,方法覆盖率等等。
覆盖率的统计有成熟工具支持,如JaCoCo,通过Maven配置即可使用。单元测试的覆盖率一般要求较高,就重要模块来说,“行覆盖率”应该在90%甚至95%以上。
2. 代码可读性高
很多程序员有个误区,觉得代码越容易被别人看懂,自己就越容易被替代。这个观点貌似是有逻辑的,但其实挺妨碍个人成长。软件工程之所以称为工程,很重要的一点就是需要大规模团队协作。
这个协作过程是需要互相补位的。极限编程思想中也强调集体代码所有权,即整个团队共同拥有和维护的概念,任何团队成员都可以修改任何部分的代码、改进代码库、提高软件质量。
同时,软件工程和任何重要系统一样,不能不应该存在单点的。如果一段代码只有开发者自己能看懂,能维护,那么这个系统就会无比脆弱。某些可读性差的代码,即使开发者本人也是当时能够看懂,半年之后对自己来说都是天书。
真的有用代码可读性差这点来保障职业安全的想法,那大概率不会被安排承担重要的开发工作。
3. 重构能力
重构是保持软件生命力的重要手段。程序诞生后,不是一成不变的,修改Bug、增加新功能都会打破原有的设计预期。这时最安全的方法是通过叠加补丁的方式编写增量代码,尽量不修改主干逻辑。
但是,这种方式持续一段时间后,代码的框架结构就会遭到破坏,各种杂乱的分支让程序的可读性、可维护性急剧下降。
而重构则是将后续产生的需求进行整体考虑,在保证结果正确的前提下,维持甚至提升了代码框架结构的合理性。可以说,能够完成高质量的重构是优秀程序员的试金石。
重构不只需要勇气,还需要方法。很多程序员不做重构,是因为其风险性高,毕竟是经过了实际生产环境的验证,稳定性有保障。所以,代码重构要有全量迭代测试作为验证手段,而为了在成本上可行,这个全量迭代必须是自动化的。
优秀的程序员,应该在开发过程中有意识的积累测试案例脚本,能够通过自动化的方式进行功能上的全量迭代测试。如果你开发的是后台应用服务,那就应该将各种请求报文、响应报文和上下文等数据积累下来。如果有完善DevOps流程,则是对高质量重构的一种组织级保障。
4. 抽象思维能力
程序开发中面临很多具体问题,看似各不相同,需要从头思考方案。但是,优秀程序员应该善于对问题进行抽象,从具体的业务场景中将问题的本质抽离出来,这个有点像数学建模过程。抽象后,更容易找到经典解体思路。
所谓太阳底下无新事,我们面临的问题几乎都有经典的处理方法。没有抽象思维能力,则只能自己或者小范围几个人闭门造车式的研究,当事人觉得是奇思妙想,但其实是重复发明轮子,这个轮子可能还是方的。
在我看来,养成抽象思维的方法有两个,第一是多阅读基础软件的设计方案和代码,因为他们是与具体业务无关,技术方案必须有更强的通用性,往往可以兼容我们的业务场景。或者说,应用软件的解题方法基本上就是基础软件的方法上再附加业务场景的约束。
第二是多读相关领域的顶会论文,积累抽象问题的解决方案,有点像武侠小说中的高手练习内力,只要内力足够强,摘叶飞花皆可伤人。这是从抽象到具体的过程,开始的体验可能会稍微痛苦些,推荐从工业界论文入手会降低些难度。从这点来说,抽象思维也是连接工业界现实问题与学术界研究成果的重要桥梁。
最后总结一下,
四种能力分别是有单元测试习惯,代码可读性高,高质量的重构能力,良好的抽象思维能力。四种能力的背后更是体现了程序员的自我修养,单元测试背后是靠谱的工作态度和专业精神,代码可读性背后是协作意识和开放心态,重构能力的背后是追求卓越的精神和自我迭代的勇气,抽象思维能力的背后是扎实的理论基础和宽广的技术视野。