看Bob大叔的书,还要追溯到《敏捷软件开发——原则、模式与实践》。这是一本改变我对软件看法的书,也使得我彻底摆脱了一个纯编码者的思维,继而转向以研究设计架构、分析用户需求为中心的软件开发方式,可谓一部有重要影响力的书。这个以后会有专文描述,在此不赘述啦。

  其后看了《Clean Code》(干净代码),此书可以认为是敏捷软件开发一书的具体化。那本以思想为主,这本以代码细节为主。看完之后对自己编码质量的要求又更进了一步。可以说是打开了激发了我精进代码质量的动力。

  这次看到这本虽然正文加附录仅仅二百零四页的《Clean Coder》(干净编码者——专业级程序员编码法典), 心里异常激动,前两本如果说侧重点还偏于原理和技术的话,这一本从名字上看,就是偏重人的。本来想翻译一下给朋友看,后来发现国内的出版社有出版计划,我 就决定先看完英文版,等中文版出来再和朋友们一起讨论、学习。读书的时候做了很长的笔记,如果全写出来,恐怕抓不住重点。这里就根据几条主要的线索把一些 重要的问题整理出来,以辅助大家阅读和理解此书。

  全书仅仅十四章。我自己是在顺序阅读中,是沿着三大主线进行思考的:学习、纪律、交流。

  前三章可以作为一组,从“职业精神、学会拒绝、学会承诺”三个切入点,讲述了作为一个职业程序员,要学会从工作经验中学习为人处世之道。具体说来,要 会依据一些周围的情势、同事的语气、自己的能力与时间安排等因素,决定是应该拒绝一个新功能的加入还是应该承诺在一个给定的时间内按时交付它。我在学会拒 绝和承诺新需求的方面,一直做的很不到位。看了此书我才发现,要根据整个工程所处的状态,向队友陈述工程的实际情况。只有大家瞭解了实际情况,才能作出一 个建设性的答案,以决定一个新功能是应该在下一版在做,还是应该加班做好,抑或采用一些临时方案先使它上线。关于工程进度,表面的和谐和不够深入的交流, 都是导致工程延期的重要因素。

  中间六章可以作为一组,从“编码、测试驱动开发、例行代码功力训练、验收测试、测试策略、时间管理”等六个方面讲述了一个专业程序员(即本书标题所谓的“干净编码者”)所应具有的工作行为准则。

  在编码这章中,作者讲述了专注编码的重要性。同时也强调了过于专注,而不时时用代码审查或测试用例来辅助督促代码质量的话,也会导致代码细节美丽但是大方向走偏。编码应当是短时间,高效率的作业,如果思维受到阻滞,应当及时放松,不能强求。

  第五章讲述了测试驱动开发(TDD)的好处,这可以认为是一个介绍性的文字。TDD新手要入门的话,推荐Kent Beck的《测试驱动开发》一书。关于TDD,一些网友以及我都曾表示过,它不宜被无条件的套用。其实TDD的核心意图,还是为了以测试用例保证代码质量,同时以测试用例作为需求文 档规格书(这一点我原来未能认识到,本书第七章明确提及)。只要把握住这一点,在具体的实践中,可以对测试策略进行灵活调整。(参看拙作:测试驱动开发到底好不好

  第六章讲到了一些例行的代码功力训练。的确,作为一个技术行业,长时间脱离编码实践是不行的。即便有朋友进入了管理层,我也还是坚持建议大家应该做例 行的代码训练。书中推荐设定一个“代码道场”做练习环境,通过“形”(单人代码练习,推荐Bob大叔在《敏捷软件开发》中所举保龄球的例子)、“技”(双 人结对编码练习)、“自由格斗”(多人轮流代码训练)来进行例行练功。我认为具体形式上可以不必拘泥,但是每隔固定时间,如一周左右,应该针对一些小问 题,比如排序、搜索、小应用、小游戏等,进行代码训练,其实也是一个将软件设计思路通过代码练习凝固的过程。

  第七章讲了验收测试的重要性。业务和技术人员通常会对一个需求的描述与实现进度产生理解分歧,以致交付的产品未能满足客户需求。这就需要双方用验收测 试来消除对于需求描述和进度所产生的歧义。由于GUI测试的易变性,针对GUI的测试应当尽可能的少。首先应将GUI下面的业务规则测试和GUI测试本身 分离,这一点很多同学都没能做到。其次,针对GUI自身的绘制逻辑与客户响应进行测试,底层业务逻辑可以用空实现代码填充。

  第八章说,专业级程序员应该及时发现产品问题,而不是一味推给QA(质保人员)。程序、QA、商务应当合作。在验收测试中,QA测试极端路径,商务测 试(或通过程序员测试)正常路径,两者互补。在作者构想的“测试金字塔”中,单元测试覆盖率应接近100%,针对API的组件测试应占50%,同样针对 API的集成测试应占20%,主要针对GUI的系统测试应占10%,为了探究系统运行特性所写的探索测试应占5%。

  第九章讲时间管理。不能快速解决的争议,一定是双方论点均有立足点的议题,此时不应浪费过多时间争论,而应拿出数据,用理性说话。其后讲到用番茄法进 行时间管理的一些窍门。最后提及一个重要问题:如果发现当前工程的发展方向已经无法灵活满足需求,则应及时重构甚至重新设计,否则将来等缺陷积累到一定时 点,必将花费更多时间去返工。此一点可谓切中要害,希望大家牢记在心,不要因为对工程缺陷一时的放纵而导致大方向走偏。

  最后五章可作为第三部分,主要讲述了“工程估算”,“应对压力”,“协同工作”,“团队与工程”,“督导、学徒制与代码技艺”等五大涉及交流的问题。

  PERT估算法是应重点掌握的知识。在估算中,针对某一任务在“一般情境”(相对于最坏情境和最好情境)下所需时间的估量,可以通过宽频预测法及其变体(Flying Fingers, Planning Poker, Affinity Estimation等)来讨论出共识。大数法则对于估量大型任务很有帮助。

  应对压力一章得出的结论是,在重重压力下,保持工程干净,不走样的唯一办法,就是坚持自己知道的且真正管用的工作守则,还应注意保持冷静,沟通,及时寻求帮助。

  协同工作一章讲述了代码评审:系统绝不应含有未被评审的代码。代码评审有很多种方式,它们大多极端低效。最优效率的、最有用的方式就是一起写代码(即 结对编程,一人写代码,另一人当场评审,过一定的时间二人交换)。还讲了专业程序员互相交流的方式:他们能互相感知对方的恐惧;能不经意地听到某人沮丧的 牢骚;时而不时的交流一下子,要有通过说话进行的交流,也要有通过肢体语言进行的;要做为团队的一份子去交流。

  团队与工程一章,作者提出了自己构想的一个优化配置过的团队模型(我称之为“胜利十二人”):七个程序员,两个测试,两个系统分析员,一个项目经理。 更重要的是,明确论证了一个结论:要先建立有凝聚力的团队,此后才能将工程根据团队成员的特性分配给他们。针对团队的培养才是使得工作能够高效、可持续进 行的一条正道。

  最后一章中,作者通过与医疗行业的类比,建议公司都应设立针对软件开发者所进行的合理培训期与督导实习制度。这个我想很多国内工作环境未必能保证。接 下来作者构想了一个用“大师——熟练工——学徒工”三阶段来指示软件开发者职业生涯的路线图。软件高手(大师)应当拥有至少10年工作经验,能够坚守自己 的技术角色而不醉心于管理职位;熟练工应具备五年工作经验(原来我同事小利和小爱本人都可算熟练工,小小的自满一把,嘿嘿),他们专精于一门语言,一个系 统和一个平台,但是愿意学习更多知识。他们中的高水平者可不需大师监督自行做软件,初级水平者尚需高手监督与代码审查。熟练工之间应互相审查代码;学徒工/实习生则必须在熟练工的带领下做事,且至少一年。作者说现实中的公司和这个设想制度的主要差别即是缺乏老手教导新手的责任观。

  文末作者总结了代码工匠和代码技艺的定义:代码工匠掌握了技巧和质量。其工作快速而不忙乱。提供合理的工期估量,按时交付。知道何时该拒绝,但也会努 力去完成力所能及的任务。一个代码工匠必是一个专业人员。代码技艺是代码工匠所具有的意识。是一种包含价值观、原则、技术、态度与问题解决办法的文化基 因。同时作者作出了呼吁:要劝说他人接受代码技艺的思维模式,首先自己要作为一个行为榜样,成为一个代码工匠,将代码技艺展示出来,这样文化基因自然就会 发生作用。在软件行业的我们应当面对现实,教导下一批软件开发者直至其成熟。这个责任落在我们的身上,而不是大学的身上。

  很少有书的附录能像本书这么有内容。除了一些颇为有用的工具介绍之外,还告诉我们,一个工程的待做任务与Bug不能积累太多,否则“事务追踪”便失去其“追踪”的意义了。还强调了测试用例之间不能有依赖性。这是个大问题,可以参考《xUnit Test Patterns》 一书。作者还提及,编程要解决的问题不在代码,而在细节,UML等模型驱动架构(MDA)无法将细节彻底从代码中剥离,因而无法成功。实际上也不可能剥 离。将来即便有成功的MDA,也是来自程序员而非架构师,他们将会把UML转变成一种新的能够描述细节的编程序语言。这一点我本人不太理解和赞同,希望与 大方之家讨论。

  纵观全书,很少有一本著作能够教给我们这么多有关软件设计行业的心得体会。这些心得还需随着实践去加深和调整。一个专家级程序员,必然是不停地从工作经验中学习,在工作中坚守行业质量准则,并且愿意与工作夥伴密切交流的人。

  本文为原创,如需转载请联系作者(Email eastarstormlee@gmail.com 微博 http://weibo.com/eastarlee)