Practices of an Agile Developer

—— Venkat Subramaniam,Andy Hunt

一句话,这本书算是程序员的心灵鸡汤。书中所写所引,不少箴言/警言,收获多少,存乎一心。

本书许多条目其实与敏捷无关,但为了吸引眼球,让内容敏捷,纷纷在前头加上“敏捷”二字。《高效程序员的45个习惯》似乎是在向《程序员修炼之道》致敬,前者45条,后者46条,但看下来,前者远不如后者精致。整本书读下来,个人觉得此书主笔只有Venkat,封面上的Andy貌似只是打酱油,为自家出版的书充一下门面。


1. 做事

如果你说的话只是让事态更复杂,或者只是一味地抱怨,或者伤害了他人的感情,那么你无意中在给问题火上浇油。相反,你应该另辟蹊径,问问“为了解决或缓解这个问题,我能够做些什么?“在敏捷的团队中,大家的重点是做事。你应该把重点放到解决问题上,而不是在指责犯错者上面纠缠。

Blame doesn't fix bugs 指责不会修复bug

把矛头对准问题的解决办法,而不是人。

勇于承认自己不知道答案,这会让人感觉放心。一个重大的错误应该被当作是一次学习而不是指责他人的机会。团队成员在一起工作,应该互相帮助而不是相互指责。

如果你没有犯过任何错误,就说明你可能没有努力去工作。

如果一个团队成员误解了一个需求、一个API调用,或者最近一次会议做的决策,那么,也许就意味着团队的其他成员也有相同的误解。要确保整个团队尽快消除误解。

如果大部分团队成员(特别是开发领导者)的行为都不职业,并且他们对团队目标不感兴趣,你就应该主动从这个团队中离开,寻找更适合自己发展的团队(这是一个有远见的想法,没必要眼睁睁地看着自己陷入一个“死亡之旅“的项目中)。

2. 欲速则不达

Beware of land mines 防微杜渐

在工作压力之下,不去深入了解真正的问题以及可能的后果,就快速修改代码,这样只是解决表面问题,最终会引发大问题。快速修复的诱惑,很容易令人把持不住,坠入其中。短期看,它似乎是有效的。但从长远来看,它无异于穿越一片流沙,你也许侥幸走过了一半的路程(甚至更远),一切似乎都很正常。但是转眼间悲剧就发生了……

Don't code in isolation 不要孤立地编码

孤立非常危险,不要让开发人员完全孤立地编写代码。如果团队成员花些时间阅读其他同事写的代码,他们就能确保代码是可读和可理解的,并且不会随意加入这些“+1或-1“的代码。阅读代码的频率越高越好。实行代码复审,不仅有助于代码更好理解,而且是发现bug最有效的方法之一。

所有的大型系统都非常复杂,因此没有一个人能完全明白所有的代码。除了深入了解你正在开发的那部分代码之外,你还需要从更高的层面来了解大部分代码的功能,这样就可以理解系统各个功能块之间是如何交互的。

3. 对事不对人

对一个明显的错误有哪些常见的反应:

  • 否定个人能力。(那样很蠢!) 无助于提高他的水平,反而会令他以后不再提出自己的任何想法。
  • 指出明显的缺点,并否定其观点。(那样很蠢,你忘记考虑它要线程安全。) 至少观点明确,但也不能给Lee太多帮助,甚至可能会让自己惹火上身,毕竟智者千虑必有一失。
  • 询问你的队友,并提出你的顾虑。(谢谢,Lee先生。但是我想知道,如果两个用户同时登录会发生什么情况?) 没有指责,没有评判,只是简单地表达自己的观点。让Lee自身意识到这个问题,而不是扫他的面子,(通常这是个很好的技巧:用引导的方式地提出疑问,让被问者自己意识到问题。)负面的评论和态度扼杀了创新。

我们每个人都会有好的想法,也会有不对的想法,团队中的每个人都需要自由地表达观点。即使你的建议不被全盘接受,也能对最终解决问题有所帮助。不要害怕受到批评。记住,任何一个专家都是从这开始的。用Les Brown的一句话说就是:“你不需要很出色才能起步,但是你必须起步才能变得很出色。“

You don’t have to be great to get started, but you have to get started to be great. - Les Brown

It is the mark of an educated mind to be able to entertain a thought without accepting it. - Aristotle

能容纳自己并不接受的想法,表明你的头脑足够有学识。 - 亚里士多德

团队决策的若干技术:

  • 设定最终期限 避免陷入无休止的理论争辩。
  • 逆向思维 找出优点最多缺点最少的那个方案。
  • 设立仲裁人 确保每个人都有发言的机会,并维持会议的正常进行。防止明星员工操纵会议,并及时打断假大空式发言。
  • 支持已经做出的决定 一旦方案确定,每个成员都必须通力合作,努力实现这个方案。

不带个人情绪并不是要盲目地接受所有的观点。用合适的言语和理由去解释为什么你不赞同这个观点或方案,并提出明确的问题。

4. 排除万难,奋勇前进

假如要你修复其他人编写的代码,而代码很难理解也不好用。你是应该继续修复工作,保留这些脏乱的代码呢,还是应该告诉你的老板,这些代码太烂了,应该通通扔掉呢?

也许你会跳起来告诉周围的人,那些代码是多么糟糕,但那只是抱怨和发泄,并不能解决问题。相反,你应该重写这些代码,并比较重写前后的优缺点。动手证明(不要只是嚷嚷)最有效的方式,是把糟糕的代码放到一边,立刻重写。列出重写的理由,有助于你的老板(以及同事)认清当前形势,帮助他们得到正确的解决方案。

5. 跟踪变化

如何才能跟上技术变化的步伐呢?下面是一些建议:

  • 迭代和增量式的学习 每天计划用一段时间来学习新技术,不需要很长时间,但需要经常进行。记下那些你想学习的东西——当你听到一些不熟悉的术语或者短语时,简要记录下来,然后在计划的时间里加以深入研究。
  • 了解最新行情 选择一些公认的优秀技术博客,经常去读一读,以了解那些顶尖的博客作者都在关注什么。
  • 参加本地的用户组活动 积极参与问答环节
  • 参加研讨会 许多知名的顾问或作者主持的研讨会或课程。
  • 如饥似渴地阅读 一些关于软件开发和非技术主题的好书,专业期刊和商业杂志,甚至是一些大众媒体新闻

跟踪技术变化。你不需要精通所有技术,但需要清楚知道行业的动向,从而规划你的项目和职业生涯。

6. 对团队投资

每周,要求团队中的一个人主持讲座,给大家介绍一些概念,演示工具,或者做些团队感兴趣的事情。也可以挑一本书,给大家说说其中一些特别的内容、项目或者实践。无论什么主题都可以。从每周主持讲座的人开始,先让他讲15分钟,然后进行开放式讨论,这样每个人都可以发表自己的意见,讨论这个主题对于项目的意义。

坚持有计划有规律地举行讲座,持续、小步前进为上,稀疏、间隔时间长的马拉松式会议不可取。

享有盛名的爵士吉他手Pat Methany说过这样一句话:“总是要成为你所在的那个乐队中最差的乐手。如果你是乐队中最好的乐手,就需要重新选择乐队了。我认为做其他事情也是同样道理。“

7. 懂得丢弃

学习一门新技术时,多问问自己,是否把太多旧的态度和方法用在了新技术上。学习面向对象编程和学习面向过程编程是截然不同的。很容易发现有人用C语言的方式编写Java代码,用VB的方式编写C#代码。这样,你辛辛苦苦转向一门新的语言,却得不到期望获得的好处。

沉舟侧畔千帆过,病树前头万木春。要果断打破窠臼,一味因循守旧会危害你的职业生涯。

对于所使用的语言,要总结你所熟悉的语言特性,并且比较这些特性在新语言或新版本中有什么不同。

24. 倾听用户的声音

每一次抱怨的背后都隐藏了一个事实。找出真相,修复真正的问题。

25. 代码要清晰地表达意图

Hoare on Software Design

by C.A.R. Hoare

There are two ways of creating a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.

软件设计有两种方式。一种是把软件设计得尽量简单,并且明显找不到缺陷;另一种是设计得尽量复杂,并且找不到明显的缺陷。

开发代码时,应该更注重可读性,而不是只图自己方便。代码阅读的次数要远远超过编写的次数,所以在编写的时候值得花点功夫让它读起来更加简单。实际上,从衡量标准上来看,代码清晰程度的优先级应该排在执行效率之前。

26. 用代码沟通

用注释沟通。使用精心挑选、含义明确的命名。用注释描述代码意图和约束。注释不能替代优秀的代码。

解释代码做了什么的注释用处不那么大,相反,注释要说明为什么会这样写代码。

28. 增量式编程

在编译和测试的空档,停下来想一想,并暂时远离代码细节,这是保证不会偏离正确方向的好办法。

要休息的话,就要好好休息。休息时请远离键盘。

29. 保持简单

Andy曾经认识一个家伙,他对设计模式非常着迷,想把它们全都用起来。有一次,要写一个大概几百行代码的程序。在别人发现之前,他已经成功地将GoF那本书中的17个模式,都运用到那可怜的程序中。

简单并不意味着简陋、业余或是能力不足。恰恰相反,相比一个过于复杂、拙劣的解决方案,简单的方案通常更难以获得。

Simple is not simplistic 简单不是简陋

代码几乎总是可以得到进一步精炼,但是到了某个点之后,再做改进就不会带来任何实质好处。这时开发人员就该停下来,去做其他方面的工作了。

要将目标牢记在心:简单、可读性高的代码。强行让代码变得优雅与过早优化类似,同样会产生恶劣的影响。

30. 编写内聚的代码

Charles Hess先生1866年申请的专利,“可变换的钢琴、睡椅和五斗柜“。

33. 记录问题解决日志

维护一个日志,保存遇到过的问题以及对应解决方案,可以选择符合需求的任何格式,比如:

  • 问题发生日期
  • 问题简述(硬件平台、设备型号、应用版本、内核版本)
  • 解决方案详细描述
  • 参考文章或网址,以提供更多细节或相关信息
  • 代码片段、设置或对话框截屏,只要它们是解决方案的一部分,或者有助于更深入地理解相关细节

日志应保存为计算机可搜索的格式,以便用关键字搜索并快速定位。如果遇到的问题在日志中找不到解决方案,在问题解决之后,记得马上将相关细节记录到日志中去。

日志应与他人共享,而不仅仅是靠个人维护。把它放到共享的网络驱动器中,以供其他人使用。或者创建一个Wiki,并鼓励其他开发人员使用和更新其内容。

要记录团队做出一个重要决策的原因。否则,在6~9个月之后,想重新回顾决策过程时,相关细节可能很难记起来,很容易出现扯皮现象。

34. 警告就是错误

将警告视为错误。签入带有警告的代码,就跟签入有错误或者未通过测试的代码一样,都是极差的做法。签入构建工具中的代码不应该产生任何警告信息。

35. 对问题各个击破

识别复杂问题的第一步,是将它们分离出来。既然不可能在半空中试图修复飞机引擎,为什么还要试图在整个应用中,诊断其中某个组成部分的复杂问题呢?当引擎从飞机中取出来,而且放在工作台上之后,就更容易修复了。同理,如果可以隔离出发生问题的模块,也更容易修复发生问题的代码。

Prototype to isolate 用原型进行分离

在模块化不足,分离特别困难时,最好花一些时间把关注的代码提取出来,而且创建一个可让其工作的测试环境。

对问题各个击破,这样做有很多好处:通过将问题与应用其他部分隔离开,可以将关注点直接放在与问题相关的议题上;可以通过多种改变,来接近问题发生的核心——你不可能针对正在运行的系统来这样做。可以更快地发现问题的根源所在,因为只与所需最小数量的相关代码发生关系。

以二分查找的方式来定位问题是很有用的。也就是说,将问题空间分为两半,看看哪一半包含问题。再将包含问题的一半进行二分,并不断重复这个过程。

在着手处理问题之前,先查找你的问题解决日志。

38. 定期安排会面时间

坐着开的会议通常会持续更久,大部分人不喜欢站着进行长时间的谈话。

要保证会议议题不发散,每个人都应该只回答下列三个问题:

  • 昨天有什么收获?
  • 今天计划做什么?
  • 目前有哪些障碍?

通常,立会都是在每个工作日的早些时候,且大家都在上班时举行。但是不要把它安排为上班后的第一件事。要让大家有机会从刚才混乱的交通状况中恢复状态,喝点咖啡,删除垃圾邮件什么的。一般来说,在大家到公司之后的半小时到一小时之内举行,是个不错的选择。

每日立会有诸多好处。

  • 让大家尽快投入到一天的工作中来。
  • 如果某个开发人员在某一点上有问题,他可以借机将问题公开,积极寻求帮助。
  • 帮助团队带头人或管理层哪些部分需要更多协助,并重新分配人手。
  • 让团队成员知道项目其他部分的进展情况。
  • 帮助团队识别是否在某些东西上有重复劳动而耗费了精力,或者是不是某个问题已有现成的解决方案。
  • 通过促进代码和思路的共享加快开发速度。
  • 鼓励向前的动力:看到别人报告的进度都在前进,会激励彼此。

40. 实行代码集体所有制

要强调代码的集体所有制。让开发人员轮换完成系统不同领域中不同模块的不同任务。

任何人都可能遭遇到诸如车祸等突发事故,或者有可能被竞争对手挖角。如果不向整个团队分享知识,反而增加了丧失知识的风险。

41. 成为指导者

Knowledge grows when given 教学相长

好的想法不会因为被许多人了解而消弱。当我听到你的主意时,我得到了知识,你的主意也还是很棒。同样道理,如果你用你的蜡烛点燃了我的,我在得到光明的同时,也没有让你的周围变暗。好主意就像火,可以引领这个世界,同时不削弱自己。 - 托马斯·杰斐逊

通过详细解释自己知道的东西,可以使自己的理解更深入。当别人提出问题时,也可以发现不同的角度。也许可以发现一些新技巧——听到一个声音这样告诉自己:“我以前还没这么思考过这个问题。“

多数时候,成为指导者,是指在帮助团队成员提升水平的同时也提高自己。

成为指导者意味着要分享——而不是固守——自己的知识、经验和体会,要对别人的所学和工作感兴趣,同时愿意为团队增加价值。一切都是为了提高队友和你的能力与水平,而不是为了毁掉团队。

42. 允许大家自己想办法

授人以鱼,莫若授人以渔。

不要直接给出答案,而应给于指引,这么做有如下好处:

  • 你在帮助他们学会如何解决问题。
  • 他们可以学到答案之外的更多东西。
  • 他们不会再反复问你类似的问题。
  • 这样做有助于他们在你无法回答问题时自己想办法。
  • 他们可能会想出你没有考虑到的解决办法或者主意。这是最有意思的,你也可以学到新东西。

用问题来回答问题,可以引导提问的人走上正确的道路。

如果有人真的陷入胶着状态,就不要折磨他们了。告诉他们答案,再解释为什么是这样。

44. 代码复查

最基本的检查单:

  • 代码能否读懂和理解?
  • 是否存在明显的错误?
  • 代码是否会对应用其他部分产生不良影响?
  • 是否存在重复的代码(在复查的这部分代码中,或是在系统的其他部分代码)?
  • 是否存在可以改进或重构的部分?