职业程序员的克制与放纵
程序员有哪些职业素养?关于这个话题已经有很多资料,前段时间章显洲和我一起翻译了Uncle Bob的Clean Coder(中文名《程序员的职业素养》),通篇谈的都是程序员的职业素养,而且讲的很在理。不过今天,我想根据自己的经验和观察,谈“程序员的职业素养”的两个方面:克制和放纵。这里说的“克制”,指的是要克制自己敲代码的冲动;而“放纵”,指的是要放纵自己关于程序本身的思考。下面先从克制说起。
许多年前我刚开始学编程时,朋友曾说过一个笑话:差劲的程序员有两种,一种是开始就写main函数的;还有一种是上来就上网找各种类库源代码的。当时我并不能完全理解:编程序,不去找类库源代码,不从main函数开始,还要怎么做呢?后来才逐渐明白,上来就写main函数,或者上来就找类库找源代码,归根到底都是不能克制关于代码的冲动。直接写代码当然很“爽”,很有“成就感”。可是,这样做真的是好事吗?
在现实生活中,我确实看到相当多的程序员写代码的冲动相当强烈,难以克制。这可能是因为任何软件都需要落实为代码,拿到一个任务,直接写代码可以赋予程序员充足甚至全部的成就感。在心里想个明白,在纸上写写画画,反而成了一种难以克制的煎熬。但有经验的人都知道,程序不等于代码,程序的含义和复杂性远远超过代码;没有明晰的需求,没有清楚的头脑,没有良好的规划,写出来的代码就成了无源之水,无本之木,写的越爽,后果可能越严重。
我曾经见过一套系统,其中充满了各种状态码的条件判断,这种情况本来很正常,不幸所有的状态码都是硬编码的数字,整个系统就是一本天书:一会儿判断这里是否等于2,一会儿判断那里是否大于7……究其原因,是程序员觉得这些状态码无非就是“用数字代表状态”,所以随便选些数字就好了:2代表什么,7对应什么,自己记得就好;更重要的是,硬编码的状态码“用起来方便”,敲代码的速度大大提升——不需要查找变量,也不需要输入整个变量名。这种系统的问题相信大家都猜得到,维护和修改起来无比痛苦。所以,尽管写这些程序的程序员已经有了一两年甚至更多的工作经验,但他们身上很难说有“职业素养”。
与此相反,重构的人员采取了完全不同的方法:虽然全部硬编码看起来不爽,用起来更不爽,人人都有立刻动手改掉它的冲动,但重构时首先要做的并不是直接修改代码,而是仔细阅读整个程序,编写了一份所有状态码的图表(并且打印出来供随时查阅),再根据状态码的意义和使用场景,重新设计状态码(因为各个状态之间还存在逻辑关系,所以需要以自定义类型表示状态),最后才动手编码完成重构。事实证明,这种策略是非常成功的:阅读代码、制定图表、重新设计需要三周的时间,真正的重构只用几天就顺利完成了,而且从此以后维护和修改的难度大大降低,真正达到了重构的目的。完成重构工作的程序员,工作经验并不比最初编写程序的人要多,他们没有一开始就写代码,甚至没有花太多时间在代码上,更没有用到高深莫测的技术,但他们身上恰恰体现出了程序员的职业素养。
身为程序员,大概人人都喜欢狂敲代码带来的快感;但身为职业程序员,必须要克制写代码的冲动,在写代码之前花更多时间理解需求,设计系统,制定规划,这样写出来的代码才会更加精炼,整个程序才更有价值。我们甚至可以说,拿到需求就动手敲代码的程序员,无论有多少年经验,仍然不过是楞头青。
说完了克制,下面说放纵。此处的“放纵”其实是一个比较夸张的说法,但依我所见,用“放纵”非常有必要,因为不少程序员写的程序实在太“保守”了,矫枉必须过正。
我刚刚工作时,项目经理分给我的任务是从网络上抓些特定的信息存到数据库。这个任务我花了不少工夫完成,本以为可以赢得项目经理的表扬,结果却是劈头盖脸的苛责:“你当这是学生写程序吗?什么异常情况都没考虑?网络断了怎么办?数据库连不通怎么办?……”虽然在学校写过不少程序,但这些问题我真是没处理过,甚至完全没考虑过。可以说,在那一刻,我才真正开始理解,为什么要有异常,为什么会有强制异常处理。
本来我以为这只是自己经验不足的教训,但后来我逐渐发现,不少程序员对异常处理都相当吝啬,更乐意让自己的程序呆在舒适安逸的温柔乡里,走在万事俱备的康庄大道上——用户的输入永远是符合预期的,程序的计算永远不会出任何误差,网络和数据库连接永远是稳定可靠的……这样做最明显的后果就是,对程序员意料之外的情况,程序做不了任何处理,只能交由它所依赖的类库或者运行平台来显示最原始的错误信息,而这些信息直接暴露给客户——比如明明是网络不通,却提示 “无法解析域名”(对普通人来说,“解析域名”简直就是天书);明明是客户输入有错误,却直接抛出最底层异常(即便大公司也会犯这种错误)。
每次遇到这种情况,用户即便有能力解决问题,也不知所措,只能找程序员本人来处理。如果某人开发的程序发布之后经常需要在线调试、现场维护,开发效率和质量就会大打折扣,我们也很难说哪里体现了“职业素养”。相反,足够职业的程序员,哪怕开发一个非常简单的程序,必然不会局限于正常的逻辑,而会“放纵”自己的时间精力,去考虑各种异常情况,做出合适的处理,他开发的程序就像优秀作家的作品,可以简单,也可以复杂,可以平实,也可以高深,但一定不会轻易倒下。
武侠小说里常见一些顶尖高手,用平凡无奇的招式,轻松击败对手,那是因为比起招式,“功力”和“应对”是更重要的因素,其实程序开发也是这个道理。如果我们把看得见、摸得着的代码比作某种招式,那么程序员越能克制写代码的冲动,花越多的时间思考和设计,此招式的功力就越深厚;另一方面,程序员越能放纵自己对各种意外的考虑和处理,此招式的应对能力就更强。如果成为武林高手必然有深厚的功力,有丰富的应对经验,那么要成为职业程序员,也必然要花大量精力思考代码之外的问题,处理意料之外的情况。
From Life Sailor, post 职业程序员的克制与放纵
第五自然段:“但重构时不是首先要做的并不是直接修改代码”,语句不通顺了,多了一个“不是”。
是的,这里写错了,多谢指正