在发现自己能够将旧的Python代码库移植至Node中时,我感到兴奋莫名。相较于普通代码维护工作,这类移植任务往往拥有更多创作自由与发挥空间,且在乐趣层面远远超过修改他人留下的代码烂摊子。
然而在开始实际工作之后,这种兴奋感迅速消失。虽然我已经拥有15年的编程从业经历,但其中的遗留代码仍然相当恐怖,甚至可以说是我所见过的最糟糕的代码库之一。原作者构建起自己的框架,且其模式与完美一词基本背道而驰:关注点未进行拆分、缩进时乱用空格/tab、同一概念拥有多个名称、来自内容几乎相同的不同方法的同一数据多次覆盖变量以及魔幻般不可解读的字符串……这一切都证明,这套代码库绝对是之前某位码农通过复制谷歌查询结果拼凑出来的成果。
然而,这种彻底违背编程规范的状态反而引发了我的兴趣,并促使我写下这篇文章。经过几个月的工作之后,我发现原作者实际是一位经验丰富的高级开发人员,且拥有出色的技能水平。那么到底是什么原因导致这位主管人员编写出如此垃圾的代码?立足于此案例,我整理出一份原因清单。 其中条目为即使是经验丰富的团队中也普遍存在的种种坏习惯,其会直接体现在最终产品当中,且任何静态代码检查工具或者开发方法都无法对其加以纠正。
1.对重要性太过高估
此项目中的一大缺陷在于过度关注截止期限,甚至以损害代码质量为代价。如果开发者过度关注项目本身的重要性与交付时间,而非编写良好代码,那么其最终结果绝对会令企业管理者更加头痛。造成这种问题的根源有二,其一为过度估量、其二为过度承诺,而二者皆会增加开发者负担。
一般来讲,过度估量的可能性相对较低,因为项目成本往往能够说明一切。因此,开发者可能选择过度承诺,而后因此思路思考架构选择或者任务自动化等重要议题,旨在满足不切实际的项目周期要求。这些任务通常被视为附加价值,因此往往会被不假思索地砍掉。产品质量则将随着技术债务的积累而下降,因为项目后期代码重组的成本将成倍提升。
举例来说,我在此项目中发现一部分代码明显被到处复制,但看起来开发者同时又急于交付且根本没时间理会此前是否已经有人编写过同样的方法或者SQL查询。
有时候评估本身还存在误导性。就如,敏捷性原则中有“速度”这样一项术语,其思路是计算团队的交付速度,并作出必要调整以提升速度。问题在于,我们根本不可能立足中、短期给出准确的速度评估结果。平均法则告诉我们,我们无法根据以往的表现来衡量自己未来能够推进得多快,因为这样的已知指标并不足以指导未知。
平均法则:小样本成员间的分布统计结果必须反映在总体成员的分布结果当中。
事实上,一位开发者可能在一天之内编写大量代码,也可能在与同事配合的情况下一天只写出三、五行代码——其余时间则用于编写说明文档及相互沟通。
平均值并不能代表中、短期内的有价值信息净值。其对于项目而言不具备参考价值。
2.不重视项目相关知识
随着项目的推进,团队对于业务、其深层概念以及各元素间的联系方式亦更为了解。与此同时,各成员亦更为明确如何编写代码,这种循序渐进式的认知与问题解决途径是种必然。某些业务领域甚至存在着固有复杂性,要求开发团队拿出大量时间进行消化。
这一点在对旧的代码进行完整重写方面体现得尤为突出,也反映出您的团队是否了解项目相关知识。 如果您身处某个大型项目内且其中包含无人了解且无人可以解答的功能模块,那么结果无疑相当危险。重写代码的价值完全取决于您业已掌握的专业知识,因此知识就是力量所言非虚。
如果大家指派另一支队伍进行重写,正如我所遇到的情况,则意味着您忽略了原有学习及积累成果,而单纯依靠新团队的自有技能水平。 如果由同一位程序员对自己编写的原有代码进行重写,那么即使其水平平庸亦可带来更出色的效果及完成速度。在这一点上,利用全新团队接手绝非良策。
甚至人员招聘工作也与项目知识密切相关。项目负责人掌握的信息越多,其加快项目推进速度的经验就越丰富,因此除了知识本身的价值之外,这还有助于其招纳更为出色的参与人才。如果大家的人员选择决策不力,那么糟糕的团队很可能耗时数个月却一无所获。
3.关注错误的指标取向,例如“已解决问题”或“每天提交数量”
古德哈特法则:当衡量变成目标,其就不再是良好的衡量方式。
在尝试进行项目提速时,有人问我既然快速交付非常重要,为什么其他开发者能够比我更快进行代码提交。然而可以想象,我马上就从他的一行代码中找到了四处bug。 专注于代码提交数量这种不可靠的指标会彻底毁掉整个项目,并使得成员面临更为巨大的开发周期压力。
人们普遍忽略了问题回归率这个问题。像空指针异常这类错误往往会在缺少回归率追踪的情况下反复出现,并导致整个项目“四处漏风”。在这种情况下,由于着眼点有误,大家将永远找不到问题的根源。
最后,真正重要的是我们将怎样的成果交付给客户、对方对产品的满意程度以及成果为其带来的业务价值,但这要求我们投入大量精力以确保成果质量,而非提交速度或者已解决问题量这类无用的指标。
理想的指标差别方式之一在于了解成员个人的价值观。注重细节、具备良好的沟通技巧与端正的处理态度非常重要,特别是考虑到如今有很多开发者不惜以欺诈的方式求得所谓效率提升。
4.假设良好的流程能够弥补个人错误
良好的流程虽然极具价值,但其实际效果却往往受到高估。根据我的个人经验,相当一部分企业在人才招聘方面处理不当,这迫使其不得不采用越来越严苛的执行流程以降低个人错误的可能性,而这反过来又限制了团队的自由创造能力。不仅如此,即使拥有良好的流程,个人因素仍然在其中扮演着重要角色。
这方面追求应当始终得到保持,而良好的招聘机制则能够在很大程度解决问题。卓越的人才能够弥补团队中其它形式的效率低下问题。总体而言,聪明地工作比勤奋地工作更加重要。
开发者往往缺乏良好的沟通能力。在这类复杂的代码库中,我需要不断向他人寻求帮助,但同事们往往没时间及时伸出援手。他们有时候态度恶劣,而且在提出的问题较为复杂时,几乎没有同事具备将其解决的知识与耐心。
我们需要拥有出色知识储备及良好心态的人员,他们会在进程缓慢时及时发出提醒。 每一款构建工具、每一种静态检查工具乃至每一类通讯工具都存在优势与弊端,大家需要结合各方面意见,而非盲目引入看起来不错的选项。
5.忽略代码审查与单元测试等最佳实践
在现代软件开发流程当中,保持时间进度已经不足以确保项目处于推进正轨之中,但这至少能够让我们的团队保持竞争力。着眼于最佳实践指导,测试驱动型开发方法能够将缺陷率降低40%至90%,而开发时间则仅增加15%到35%代码审查亦可有效降低缺陷率,有时甚至能够较手动测试提升80%的错误发现比例。
想象一下,在与同事协作时,我只能被迫使用遗留项目加记事本这种上个世纪的处理办法。因此,使用现代IDE、版本控制以及代码检查等功能将有效提升工作效率。 这些并不是什么高新科技,而且必须被应用于各类规模的项目当中。
6.雇用那些完全没有“人际”技能的开发者
这并不是说开发者就无法与他人交流。我自己也曾经相当害羞内向,但通过强迫性训练,如今我已经能够较为顺畅地完成沟通甚至演讲。
问题在于,当人们压根不想尝试沟通或者为此而烦躁时,结果必然极为糟糕。身为开发者,我们必须刻意培养自己的交流能力,甚至将其视为位于开发技能的重要事务。只有这样,大家才能在工作环境中获得更为热情且清晰的意见交换结果。 交流对象身在何处并不重要。一通Skype语音即可将复杂的编码难题转变为简单的五分钟小问题。
总结
在配合最佳工具、成熟的技能以及卓越的沟通能力之后,软件开发工作将变得顺畅而轻松。 我们不能仅仅因为引入了敏捷性或者其它工具而指望问题瞬间消失,毕竟其仅仅是辅助手段而非包治百病的大力丸。 只要设置得当,它们将建立起协同作用并使团队的执行效率成倍提升; 然而,如果决策草率及粗暴忽略各种细节,那么项目仍将陷入恐怖的泥潭。