软件开发的挑战
自软件工程诞生以来,人们一直在研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件,尝试建立并使用完善的工程化原则,以较经济的手段获得能在实际机器上有效运行的可靠软件。
但是,软件开发在过去几十年的发展中,并没有像其它工程领域一样,在生产效率和质量上取得突破性的提升。在很大程度上,软件开发还是一个严重依赖于“人”的行业。
首先,从软件开发的成本构成上来看,花在维护上的比重远远超过用于开发的比重。据不完全统计的数据,软件项目花在维护成本上的投入占到了八成。
随着项目开发的深入进行,我们经常发现,开发速度越来越慢,代码的质量越来越差,导致后期开发的效率和质量不断下降。
其次,从软件开发人员的投入来看,花在“读”代码上时间和精力要远远超过投入到“写”代码。
作为一线的开发人员,我们可以尝试统计出个人在过去一个单位月、季度或年度区间内,实际产出的有效代码量。然后,从“单位时间内的代码产出”这个维度上去看看,我们在“写代码”这件事情上投入的成本占比究竟有多少。
第三,代码质量的高低对于团队协作具有十分重要的意义。在Bob大叔的经典书籍《Clean Code》中有这样一幅漫画。
这幅漫画提出了一个衡量代码质量的唯一有效标准:团队在代码走查的过程中爆出粗口的次数或者频率,即WTFs/Min。在我们的日常工作中,抱怨别人代码太烂的经历屡见不鲜。从这个角度来说,良好的代码质量对于促进软件开发团队的协作很有必要。
综合以上几个方面的因素,编写可维护、可理解、可读的代码,对于降低软件项目的成本、提升团队协作的效率,具有十分重要的意义。
Clean Code, who cares?
回首我们的软件开发生涯,有多少人遇见到下面这些情形:
半夜或者休假时被电话骚扰
来自用户的质量投诉
漫长的debugging
抱怨其他人的代码太差了,不如我重写一遍
……
在痛苦的经历之后,我们是否思考过这些问题背后的原因,思考这些问题与代码质量之间的关联。
这里总结了日常软件开发过程中存在的几种常见的偏见和认知误区。
我已经实现了功能,你管我代码怎么写呢?
在平时的软件开发过程中,我们更加关注于需求实现,而不太关注如何实现。
这样带来的后果便是,这一次也许按照预期交付了客户需要的功能,但是糟糕的代码实现会制约后续功能修改和扩展。正所谓“欲速则不达”。容易读懂的代码 vs. 高质量的代码
容易读懂的代码不一定是高质量的代码,高质量的代码不容易一下子读懂,但一旦读懂则很容易理解和维护。
通常,为了快速实现功能,我们会采取"复制+粘贴"的策略,导致代码中存在大量重复的逻辑。这样的代码也许更加容易读懂,尤其是对于刚接触这块代码的人。但是这样的代码往往缺乏抽象,很容易在后续的修改中引入bug,尤其是多处修改不一致导致的低级故障。
就如同小学生写出的作文往往会像流水账,阅读的人很容易看明白,但是缺乏美感;而大作家写出的文章,简短精炼,读者需要不断揣摩,才能领域其中的美感。-
代码已经很差了,我也无能为力!
编写代码的过程中也存在着破窗效应:看起来是偶然的、个别的、轻微的“过错”,如果对这种行为不闻不问、熟视无睹、反应迟钝或纠正不力,就会纵容更多的人“去打烂更多的窗户玻璃”。
勿以善小而不为,勿以恶小而为之。
写测试用例浪费时间!
有一些行之有效并且在业界已经证明有效的工程化方法,可以帮助我们提升代码的质量,减少代码中存在的bug,尤其是低级bug;如单元测试、TDD等。
一种典型的误解是:我们往往会认为编写测试用例会浪费额外的精力和时间,认为这部分代码并不创造价值。-
时间紧,任务急!
我们不能以牺牲质量为代价,而要求团队必须在预定的期限内交付所有约定的功能。
在项目管理中,面对着成本——交付范围——交付时间这三个因素的制约,其中成本和交付时间是无法改变的。为了不以质量为代价的交付,唯一能改变的只有范围。
在某些情况下,我们可以与客户进行协商,管理好团队内需求的输入;对交付的范围进行适当缩减,以保证交付的质量。
管理者不太关注实现细节,我也不想在这方面花精力!
在软件开发团队的管理中,我们往往关注于交付了多少个功能,而不太关注功能的实现细节。短平快的修改方式可以让我们很快完成任务,却容易忽略欠下的技术债务。
因此,从激励的角度出发,我们应该建立起鼓励开发人员高质量交付的导向,破除“烂代码也不会影响绩效”的导向。
什么是好代码?
好的代码具有以下几个特征:
- 可读的(Readable)
- 可维护的(Maintainable)
- 可扩展的(Changeable)
- 可测试的(Testable)
- 安全的(Secure)
其中,编写可读的代码是Clean Code的基础:
有意义的命名(变量、函数、类型)
减少大结构、大函数、大文件(职责分明)
参数不要太多
一段代码只干一件事情
减少多层嵌套
减少重复代码
有效的注释
格式友好
……
“我们是程序员,而非考古学家”。代码应该直观、准确地展现出业务领域的知识,而不是让后来者通过猜测、臆断的方式去理解和维护。
软件开发人员应该致力于让代码更容易阅读和理解,具有更好的抽象层次。并以此为基础,不断追求软件设计的“简单性”,追求个人的“软件匠艺”。
我们能做什么?
实践Clean Code,我们应该从每天的开发工作做起,从每一个小的任务做起。
童子军原则
代码每次改动之后都变好一点点,那会怎么样?
持续地把事情向好的方向变化,并不回避那些不足以用增量改动完成的大型和严重的遗留问题。
每天我们都有机会成为童子军。-
代码走查
代码走查是已经业界证明的、行之有效的提升代码质量的方法。
通过代码走查,可以实现以下几个方面的收益:
1.保证代码质量,提高代码的可读性。
2.使得团队成员之间建立信任。
3.指导初级程序员,提升团队的能力。
-
学习与实践
从程序员个人角度出发,我们应该不断加强个人的学习和实践,学习新的语言、工具、技术等,并将其应用于日常的开发工作中;积极参与公司内部、外部的各种交流和研讨,不断提升个人的软件设计水平,个人能力的能力是团队和项目战斗力的保证。
软件匠艺的提升没有止境,我们应该保持一种谦虚和求知的心态。正如乔布斯的名言所说,“Stay hungry, stay foolish”。