设置 搜索

《高效程序员的45个习惯》之读书笔记

nd | | 访问(169)

  1、不管路走了多远,错了就要重新返回。

  2、开发要持续,切勿时续时断,我们进行的是持续开发、持续反馈。你不需要等到好几个月之后才发现问题:越早发现问题,就越容易修复问题,所以应该就在此时此刻把问题修复。

  为什么要进行持续开发呢?因为软件开发是一项非常复杂的智力活动,你遗留下来的任何问题,要么侥幸不会发生意外,要么情况会变得更糟糕,慢慢恶化直到变得不可控制。当问题累积到一定程度的时候,事情就更难解决,最后无法扭转。面对这样的问题,唯一有效的解决办法就是持续地推进系统前进和完善。

  危机管理是指问题累积并且恶化,直到它们变得非常严重,以至于你不得不立即放下一切正在做的工作来解决危机。而这样又会带来其他的负面影响,你就会陷入危机和恐慌的恶性循环中。这些正是你要避免的问题。所以,你要防微杜渐,把问题解决在萌芽状态,你要探索未知领域,在大量成本投入之前先确定其可行性。你要知错能改,在事实面前主动承认自己的所有错误。你要能自我反省,经常编码实战,加强团队协作精神。一开始你可能会觉得不适应,因为这同以往有太多的不同,但是只要能真正地行动起来,习惯了,你就会得心应手。

  3、你要不断从自己写的代码中得到反馈,并且使用自动化工具不断地构建(持续集成)和测试系统。在前进过程中,你都会有意识地修改一些代码:在功能不变的情况下,重新设计部分代码,改善代码的质量。这就是所谓的重构,它是软件开发中不可或缺的一部分——编码永远没有真正意义上的“结束”。

  下面开始描述这45个习惯

  1、做事

  “出了问题,第一重要的是确定元凶。找到那个白痴!一旦证实了是他的错误,就可以保证这样的问题永远不会再发生了。

  [正解]

  先做事,追究元凶的责任会另事情更遭。

  2、欲速则不达

  “你不需要真正地理解那块代码,它只要能够工作就可以了。哦,它需要一个小小的调整。只要在结果中再加上几行代码,它就可以工作了。干吧!就把那几行代码加进去,它应该可以工作。”

  [正解]

  问题暂时解决了,但可能会有隐藏危机,只有读懂它理解它才能对症下药(培养阅读他人代码的能力,确保自己代码的可读性)!大型系统,除了处理好自己的代码部分外,还要去熟悉其他部分,这样才能理解整个系统是如何运转的!

  3、对事不对人

  你在这个设计上投入了很多精力,为它付出很多心血。你坚信它比其他任何人的设计都棒。别听他们的,他们只会把问题变得更糟糕。”

  [正解]

  出现明显错误,我们都有哪些反应?

  (1)否定个人能力。

  (2)指出明显的缺点,并否定其观点。

  (3)询问你的队友,并提出你的顾虑。

  在一个需要紧密合作的开发团队中,如果能稍加注意礼貌对待他人,将会有益于整个团队关注真正有价值的问题,而不是勾心斗角,误入歧途。

  不能怕被嘲笑怕丢面子,也不能嘲笑别人,分享并融合各种不同的想法和观点,远远胜于单个想法为项目带来的价值。

  你必须把重点放在解决问题上,而不是去极力证明谁的主意更好。

  工作中不感情用事是需要克制力的,而你若能展现出成熟大度来,大家一定不会视而不见。这需要有人带头,身体力行,去感染另一部分人。

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

  4、排除万难,奋勇前进

  “如果你发现其他人的代码有问题,只要你自己心里知道就可以了。毕竟,你不想伤害他们,或者惹来麻烦。如果他是你的老板,更要格外谨慎,只要按照他的命令执行就可以了。”

  [正解]

  做正确的事。要诚实,要有勇气去说出实情。有时,这样做很困难,所以我们要有足够的勇气。

  5、跟踪变化

  “软件技术的变化如此之快,势不可挡,这是它的本性。继续用你熟悉的语言做你的老本行吧,你不可能跟上技术变化的脚步。”

  [正解]

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

  6、对团队投资

  “不要和别人分享你的知识——自己留着。你是因为这些知识而成为团队中的佼佼者,只要自己聪明就可以了,不用管其他失败者。”

  [正解]

  如果你是团队中最好的队员,就没有动力继续提高自己。如果周围的人都比你厉害,你就会有很强的动力去追赶他们。你将会在这样的游戏中走向自己的顶峰。

  提供你和团队学习的更好平台。通过午餐会议可以增进每个人的知识和技能,并帮助大家聚集在一起进行沟通交流。唤起人们对技术和技巧的激情,将会对项目大有裨益。

  7、懂得丢弃

  “那就是你一贯的工作方法,并且是有原因的。这个方法也很好地为你所用。开始你就掌握了这个方法,很明显它是最好的方法。真的,从那以后就不要再改变了。”

  [正解]

  学习新的东西,丢弃旧的东西。在学习一门新技术的时候,要丢弃会阻止你前进的旧习惯。毕竟,汽车要比马车车厢强得多。

  8、打破砂锅问到底

  “接受别人给你的解释。别人告诉你问题出在了什么地方,你就去看什么地方。不需要再浪费时间去追根究底。”

  [正解]

  不停地问为什么。不能只满足于别人告诉你的表面现象。要不停地提问直到你明白问题的根源。

  9、把握开发节奏

  “我们很长时间没有进行代码复审,所以这周会复审所有的代码。此外,我们也要做一个发布计划了,那就从星期二开始,用3周时间,做下一个发布计划。”

  [正解]

  解决任务,在事情变得一团糟之前。保持事件之间稳定重复的间隔,更容易解决常见的重复任务。

  在每天结束的时候,测试代码,提交代码,没有残留的代码。不要搞得经常加班。以固定、有规律的长度运行迭代。如果开发节奏过于密集,你会精疲力竭的。一般来说,当与其他团队(或组织)合作时,你需要减慢开发节奏。有规律的开发节奏会暴露很多问题,让你有更多鼓起勇气的借口。一点点的成功也是一个很大的激励。小而可达到的目标会让每个人全速前进。

  10、让客户做决定

  “开发者兼具创新和智慧,最了解应用程序。因此,所有关键决定都应该由开发者定夺。每次业务人员介入的时候,都会弄得一团糟,他们无法理解我们做事的逻辑。”

  [正解]

  让你的客户做决定。开发者、经理或者业务分析师不应该做业务方面的决定。用业务负责人能够理解的语言,向他们详细解释遇到的问题,并让他们做决定。

  11、让设计指导而不是操纵开发

  “设计文档应该尽可能详细,这样,低级的代码工人只要敲入代码就可以了。在高层方面,详细描述对象的关联关系;在低层方面,详细描述对象之间的交互。其中一定要包括方法的实现信息和参数的注释。也不要忘记给出类里面的所有字段。编写代码的时候,无论你发现了什么,绝不能偏离了设计文档。”

  [正解]

  好设计是一张地图,它也会进化。设计指引你向正确的方向前进,它不是殖民地,它不应该标识具体的路线。你不要被设计(或者设计师)操纵。

  好的设计应该是正确的,而不是精确的。也就是说,它描述的一切必须是正确的,不应该涉及不确定或者可能会发生变化的细节。它是目标,不是具体的处方。

  12、合理地使用技术

  “你开始了一个新的项目,在你面前有一长串关于新技术和应用框架的列表。这些都是好东西,你真的需要使用列表中所有的技术。想一想,你的简历上将留下漂亮的一笔,用那些伟大的框架,你的新应用将具有极高技术含量。”

  [正解]

  根据需要选择技术。首先决定什么是你需要的,接着为这些具体的问题评估使用技术。对任何要使用的技术,多问一些挑剔的问题,并真实地作出回答。

  13、保持可以发布

  “我们刚试用的时候发现了一个问题,你需要立即修复它。放下你手头的工作,去修复那个刚发现的问题,不需要经过正规的程序。不用告诉其他任何人——赶快让它工作就行了。”

  [正解]

  任何时候只要你没有准备好,那就是敌人进攻你的最佳时机。在团队里工作,修改一些东西的时候必须很谨慎。你要时刻警惕,每次改动都会影响系统的状态和整个团队的工作效率。

  下面是一个简单的工作流程,可以防止你提交破坏系统的代码。

  (1)在本地运行测试。先保证你完成的代码可以编译,并且能通过所有的单元测试。接着确保系统中的其他测试都可以通过。

  (2)检出最新的代码。从版本控制系统中更新代码到最新的版本,再编译和运行测试。这样往往会发现让你吃惊的事情:其他人提交的新代码和你的代码发生了冲突。

  (3)提交代码。现在是最新的代码了,并且通过了编译和测试,你可以提交它们了。

  保持你的项目时刻可以发布。保证你的系统随时可以编译、运行、测试并立即部署。

  14、提早集成,频繁集成

  “只要没有到开发的末尾阶段,就不要过早地浪费时间去想如何集成你的代码,至少也要等开发差不多的时候,才开始考虑它。毕竟,还没有完成开发,为什么要操心集成的事情呢!在项目的末尾,你有充裕的时间来集成代码。”

  [正解]

  提早集成,频繁集成。代码集成是主要的风险来源。要想规避这个风险,只有提早集成,持续而有规律地进行集成。

  15、提早实现自动化部署

  “没问题,可以手工安装产品,尤其是给质量保证人员安装。而且你不需要经常自己动手,他们都很擅长复制需要的所有文件。”

  [正解]

  一开始就实现自动化部署应用。使用部署系统安装你的应用,在不同的机器上用不同的配置文件测试依赖的问题。质量保证人员要像测试应用一样测试部署。

  一般产品在安装的时候,都需要有相应的软、硬件环境。比如,Java或Ruby的某个版本、外部数据库或者操作系统。这些环境的不同很可能会导致很多技术支持的电话。所以检查这些依赖关系,也是安装过程的一部分。

  (1) 在没有询问并征得用户的同意之前,安装程序绝对不能删除用户的数据。

  (2) 部署一个紧急修复的bug应该很简单,特别是在生产服务器的环境中。你知道这会发生,而且你不想在压力之下,在凌晨3点半,你还在手工部署系统。

  (3) 用户应该可以安全并且完整地卸载安装程序,特别是在质量保证人员的机器环境中。

  (4) 如果维护安装脚本变得很困难,那很可能是一个早期警告,预示着——很高的维护成本(或者不好的设计决策)。

  (5) 如果你打算把持续部署系统和产品CD或者DVD刻录机连接到一起,你就可以自动地为每个构建制作出一个完整且有标签的光盘。任何人想要最新的构建,只要从架子上拿最上面的一张光盘安装即可。

  16、使用演示获得频繁反馈

  “这不是你的过错,问题出在我们的客户——那些麻烦的最终客户和用户身上。他们不停地更改需求,导致我们严重地延期。他们一次就应该想清楚所有想要的东西,然后把这些需求给我们,这样我们才能开发出令他们满意的系统。这才是正确的工作方式。”

  [正解]

  清晰可见的开发。在开发的时候,要保持应用可见(而且客户心中也要了解)。每隔一周或者两周,邀请所有的客户,给他们演示最新完成的功能,积极获得他们的反馈。

  17、使用短迭代,增量发布

  “我们为后面的3年制定了漂亮的项目计划,列出了所有的任务和可交付的时间表。只要我们那时候发布了产品,就可以占领市场。”

  [正解]

  增量开发。发布带有最小却可用功能块的产品。每个增量开发中,使用1~4周左右迭代周期。

  短迭代让人感觉非常专注且具效率。你能看到一个实际并且确切的目标。严格的最终期限迫使你做出一些艰难的决策,没有遗留下长期悬而未决的问题。

  18、固定的价格就意味着背叛承诺

  “对这个项目,我们必须要有固定的报价。虽然我们还不清楚项目的具体情况,但仍要有一个报价。到星期一,我需要整个团队的评估,并且我们必须要在年末交付整个项目。”

  [正解]

  基于真实工作的评估。让团队和客户一起,真正地在当前项目中工作,做具体实际的评估。由客户控制他们要的功能和预算。

  (1) 主动提议先构建系统最初的、小的和有用的部分(用建筑来打个比方,就是先做一个车库)。挑选一系列小的功能,这样完成第一次交付应该不多于6~8周。向客户解释,这时候还不是要完成所有的功能,而是要足够一次交付,并能让用户真正使用。

  (2) 第一个迭代结束时客户有两个选择:可以选择一系列新的功能,继续进入下一个迭代;或者可以取消合同,仅需支付第一个迭代的几周费用,他们要么把现在的成果扔掉,要么找其他的团队来完成它。

  (3) 如果他们选择继续前进。那么这时候,应该就能很好地预测下一个迭代工作。在下一个迭代结束的时候,用户仍然有同样的选择机会:要么现在停止,要么继续下一个迭代。对客户来说,这种方式的好处是项目不可能会死亡。他们可以很早地看到工作的进度(或者不足之处)。他们总是可以控制项目,可以随时停止项目,不需要缴纳任何的违约金。他们可以控制先完成哪些功能,并能精确地知道需要花费多少资金。总而言之,客户会承担更低的风险。而你所做的就是在进行迭代和增量开发。

  (4) 如果你对答案不满意,那么看看你是否可以改变问题。

  (5) 如果你是在一个基于计划的非敏捷环境中工作,那么要么考虑一个基于计划且非敏捷的开发方法,要么换一个不同的环境。

  (6) 如果你在完成第一个迭代开发之前,拒绝做任何评估,也许你会失去这个合同,让位于那些提供了评估的人,无论他们做了多么不切实际的承诺。

  (7) 敏捷不是意味着“开始编码,我们最终会知道何时可以完成”。你仍然需要根据当前的知识和猜想,做一个大致的评估,解释如何才能到达这个目标,并给出误差范围。

  (8) 如果你现在别无选择,你不得不提供一个固定的价格,那么你需要学到真正好的评估技巧。

  (9) 也许你会考虑在合同中确定每个迭代的固定价格,但迭代的数量是可以商量的,它可以根据当前的工作状况进行调

  19、守护天使

  “你不必为单元测试花费那么多时间和精力。它只会拖延项目的进度。好歹,你也是一个不错的程序员——单元测试只会浪费时间,我们现在正处于关键时刻。”

  [正解]

  使用自动化的单元测试。好的单元测试能够为你的代码问题提供及时的警报。如果没有到位的单元测试,不要进行任何设计和代码修改。

  你依赖于单元测试。如果代码没有测试,你会觉得很不舒服,就像是在高空作业没有系安全带一样。

  单元测试是优质股,值得投资。但一些简单的属性访问方法或者价值不大的方法,是不值得花费时间进行测试的。

  (1) 人们不编写单元测试的很多借口都是因为代码中的设计缺陷。通常,抗议越强烈,就说明设计越糟糕。

  (2) 单元测试只有在达到一定测试覆盖率的时候,才能真正地发挥作用。你可以使用一些测试覆盖率工具,大致了解自己的单元测试的覆盖情况。

  (3) 不是测试越多质量就会越高,测试必须要有效。如果测试无法发现任何问题,也许它们就是没有测试对路。

  20、先用它再实现它

  “前进,先完成所有的库代码。后面会有大量时间看用户是如何思考的。现在只要把代码扔过墙去就可以了,我保证它没有问题。”

  [正解]

  TDD有机会让你编写代码之前(或者至少在深入到实现之前),可以深思熟虑将如何用它。这会迫使你去思考它的可用性和便利性,并让你的设计更加注重实效。

  TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。

  21、不同环境,就有不同问题

  “只要代码能在你的机器上运行就可以了,谁会去关心它是否可以在其他平台上工作。你又不用其他平台。”

  [正解]

  不同环境,就有不同问题。使用持续集成工具,在每一种支持的平台和环境中运行单元测试。要积极地寻找问题,而不是等问题来找你。

  22、自动验收测试

  “很好,你现在用单元测试来验证代码是否完成了你期望的行为。发给客户吧。我们很快会知道这是否是用户期望的功能。”

  [正解]

  为核心的业务逻辑创建测试。让你的客户单独验证这些测试,要让它们像一般的测试一样可以自动运行。

  关键业务逻辑必须要独立进行严格的测试,并且最后需要通过用户的审批。

  23、度量真实的进度

  “用自己的时间表报告工作进度。我们会用它做项目计划。不用管那些实际的工作时间,每周填满40小时就可以了。”

  [正解]

  度量剩下的工作量。不要用不恰当的度量来欺骗自己或者团队。要评估那些需要完成的待办事项。

  (1) 6分钟作为一个时间单位,它的粒度实在太细了,这不是敏捷的做法。

  (2) 一周或者一个月的时间单元,它的粒度太粗了,这也不是敏捷的做法。

  (3) 关注功能,而不是日程表。

  如果你在一个项目中花费了很多时间来了解你所花费的时间,而没有足够的时间进行工作,那么你在了解你所花费的时间上花费的时间就太多了。听懂了吗?

  (4) 一周工作40个小时,不是说你就有40个小时的编码时间。你需要减去会议、电话、电子邮件以及其他相关活动的时间。

  24、倾听用户的声音

  “用户就是会抱怨。这不是你的过错,是用户太愚蠢了,连使用手册都看不懂。它不是一个bug,只是用户不明白如何使用而已。他们本应该知道更多。”

  [正解]

  不管它是否是产品的bug,还是文档的bug,或者是对用户社区理解的bug,它都是团队的问题,而不是用户的问题。

  (1) 没有愚蠢的用户。

  (2) 只有愚蠢、自大的开发人员。

  (3) “它就是这样的。”这不是一个好的答案。

  (4) 如果代码问题解决不了,也许可以考虑通过修改文档或者培训来弥补。

  (5) 你的用户有可能会阅读所有的文档,记住其中的所有内容。但也可能不会。

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

  “可以工作而且易于理解的代码当然好,但是让人觉得聪明更加重要。别人给你钱是因为你脑子好使,让我们看看你到底有多聪明。”

  [正解]

  PIE原则(PIE=Program Intently and Expressively, 即意图清楚而且表达明确地编程。),代码必须明确说出你的意图,而且必须富有表达力。这样可以让代码更易于被别人阅读和理解。代码不让人迷惑,也就减少了发生潜在错误的可能。一言以蔽之,代码应意图清晰,表达明确。

  要编写清晰的而不是讨巧的代码。向代码阅读者明确表明你的意图。可读性差的代码一点都不聪明。

  26、用代码沟通

  “如果代码太杂乱以至于无法阅读,就应该使用注释来说明。精确地解释代码做了什么,每行代码都要加注释。不用管为什么要这样编码,只要告诉我们到底是怎么做的就好了。”

  [正解]

  注释可用来为读者指定一条正确的代码访问路线图。为代码中的每个类或模块添加一个短小的描述,说明其目的以及是否有任何特别需求。对于类中的每个方法,可能要说明下列信息。

  (1) 目的:为什么需要这个方法?

  (2) 需求(前置条件):方法需要什么样的输入,对象必须处于何种状态,才能让这个方法工作?

  (3) 承诺(后置条件):方法成功执行后,对象现在处于什么状态,有哪些返回值?

  (4) 异常:可能会发生什么样的问题?会抛出什么样的异常?

  注释就像是可以帮助你的好朋友,可以先阅读注释,然后快速浏览代码,从而完全理解它做了什么,以及为什么这样做。

  27、动态评估取舍

  “性能、生产力、优雅、成本以及上市时间,在软件开发过程中都是至关重要的因素。每一项都必须达到最理想状态。”

  [正解]

  动态评估权衡。考虑性能、便利性、生产力、成本和上市时间。如果性能表现足够了,就将注意力放在其他因素上。不要为了感觉上的性能提升或者设计的优雅,而将设计复杂化。

  即使不能面面俱到,你也应该觉得已经得到了最重要的东西——客户认为有价值的特性。

  28、增量式编程

  “真正的程序员写起代码来,一干就是几个小时,根本不停,甚至连头都不抬。不要停下来去编译你的代码,只要一直往下写就好了!”

  [正解]

  在很短的编辑/构建/测试循环中编写代码。这要比花费长时间仅仅做编写代码的工作好得多。可以创建更加清晰、简单、易于维护的代码。

  如果不对自己编写的代码进行测试,保证没有问题,就不要连续几个小时,甚至连续几分钟进行编程。相反,应该采用增量式的编程方式。增量式编程可以精炼并结构化你的代码。代码被复杂化、变成一团乱麻的几率减少了。所开发的代码基于即时的反馈,这些反馈来自以小步幅方式编写代码和测试的过程。

  采取增量式编程和测试,会倾向于创建更小的方法和更具内聚性的类。你不是在埋头盲目地一次性编写一大堆代码。相反,你会经常评估代码质量,并不时地进行许多小调整,而不是一次修改许多东西。

  在很短的编辑/构建/测试循环中编写代码。这要比花费长时间仅仅做编写代码的工作好得多。可以创建更加清晰、简单、易于维护的代码。

  在写了几行代码之后,你会迫切地希望进行一次构建/测试循环。在没有得到反馈时,你不想走得太远。

  29、保持简单

  “软件是很复杂的东西。随便哪个笨蛋都可以编写出简单、优雅的软件。通过编写史上最复杂的程序,你将会得到美誉和认可,更不用提保住你的工作了。”

  [正解]

  开发可以工作的、最简单的解决方案。除非有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西。

  当你觉得所编写的代码中没有一行是多余的,并且仍能交付全部的功能时,这种感觉就对了。这样的代码容易理解和改正。

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

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

  (2) 当然,简单的解决方案必须要满足功能需求。为了简单而在功能上妥协,这就是过分简化了。

  (3) 太过简洁不等于简单,那样无法达到沟通的目的。

  (4) 一个人认为简单的东西,可能对另一个人就意味着复杂。

  30、编写内聚的代码

  “你要编写一些新的代码,首先要决定的就是把这些代码放在什么地方。其实放在什么地方问题不大,你就赶紧开始吧,看看IDE中现在打开的是哪个类,直接加进去就是了。如果所有的代码都在一个类或组件里面,要找起来是很方便的。”

  [正解]

  让类的功能尽量集中,让组件尽量小。要避免创建很大的类或组件,也不要创建无所不包的大杂烩类。

  感觉类和组件的功能都很集中:每个类或组件只做一件事,而且做得很好。bug很容易跟踪,代码也易于修改,因为类和组件的责任都很清晰。

  31、告知,不要询问

  “不要相信其他的对象。毕竟,它们是由别人写的,甚至有可能是你自己上个月头脑发昏的时候写的呢。从别人那里去拿你需要的信息,然后自己处理,自己决策。不要放弃控制别人的机会!”

  [正解]

  “送报男孩和钱包的故事”很好地诠释了这一点。假定送报男孩来到你的门前,要求付给他本周的报酬。你转过身去,让送报男孩从你的后屁股兜里掏出钱包,并且从中拿走两美元(你希望是这么多),再把钱包放回去。然后,送报男孩就会开着他崭新的美洲豹汽车扬长而去了。

  在这个过程中,送报男孩作为“调用者”,应该告诉客户付他两美元。他不能探询客户的财务状况,或是钱包的薄厚,他也不能代替客户做任何决策。这都是客户的责任,而不属于送报男孩。敏捷代码也应该以同样的方式工作。

  告知,不要询问。不要抢别的对象或是组件的工作。告诉它做什么,然后盯着你自己的职责就好了。

  32、根据契约进行替换

  “深层次的继承是很棒的。如果你需要其他类的函数,直接继承它们就好了!不要担心你创建的新类会造成破坏,你的调用者可以改变他们的代码。这是他们的问题,而不是你的问题。”

  [正解]

  保持系统灵活性的关键方式,是当新代码取代原有代码之后,其他已有的代码不会意识到任何差别。

  33、记录问题解决日志

  “在开发过程中是不是经常遇到似曾相识的问题?这没关系。以前解决过的问题,现在还是可以解决掉的。”

  [正解]

  维护一个问题及其解决方案的日志。保留解决方案是修复问题过程的一部分,以后发生相同或类似问题时,就可以很快找到并使用了。

  记录问题的时间不能超过在解决问题上花费的时间。要保持轻量级和简单,不必达到对外发布式的质量。

  (1) 找到以前的解决方法非常关键。使用足够的关键字,可以帮助你在需要的时候发现需要的条目。

  (2) 如果通过搜索Web,发现没人曾经遇到同样的问题,也许搜索的方式有问题。

  (3) 要记录发生问题时应用程序、应用框架或平台的特定版本。同样的问题在不同的平台或版本上可能表现得不同。

  (4) 要记录团队做出一个重要决策的原因。否则,在6~9个月之后,想再重新回顾决策过程的时候,这些细节就很难再记得了,很容易发生互相指责的情形。

  34、警告就是错误

  “编译器的警告信息只不过是给过分小心和过于书呆子气的人看的。它们只是警告而已。如果导致的后果很严重,它们就是错误了,而且会导致无法通过编译。所以干脆忽略它们就是了。”

  [正解]

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

  35、对问题各个击破

  “逐行检查代码库中的代码确实很令人恐惧。但是要调试一个明显的错误,只有去查看整个系统的代码,而且要全部过一遍。毕竟你不知道问题可能发生在什么地方,这样做是找到它的唯一方式。”

  [正解]

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

  可是,很多应用的代码在编写时没有注意到这一点,使得分离变得特别困难。应用的各个构成部分之间会彼此纠结:想把这个部分单独拿出来,其他的会紧随而至。在这些状况下,最好花一些时间把关注的代码提取出来,而且创建一个可让其工作的测试环境。

  36、报告所有的异常

  “不要让程序的调用者看到那些奇怪的异常。处理它们是你的责任。把你调用的一切都包起来,然后发送自己定义的异常——或者干脆自己解决掉。”

  [正解]

  处理或是向上传播所有的异常。不要将它们压制不管,就算是临时这样做也不行。在写代码时要估计到会发生的问题。

  37、提供有用的错误信息

  “不要吓着用户,吓程序员也不行。要提供给他们干净整洁的错误信息。要使用如下这样让人舒服的词句:‘用户错误。替换,然后继续’。”

  [正解]

  展示有用的错误信息。提供更易于查找错误细节的方式。发生问题时,要展示出尽量多的支持细节,不过别让用户陷入其中。

  错误信息有助于问题的解决。当问题发生时,可以详细研究问题的细节描述和发生上下文。

  像“无法找到文件”这样的错误信息,就其本身而言无助于问题的解决。“无法打开/andy/project/main.yaml以供读取”这样的信息更有效。

  (1) 没有必要等待抛出异常来发现问题。在代码关键点使用断言以保证一切正常。当断言失败时,要提供与异常报告同样详细的信息。

  (2) 在提供更多信息的同时,不要泄露安全信息、个人隐私、商业机密,或其他敏感信息(对于基于的应用,这一点尤其重要)。

  (3) 提供给用户的信息可以包含一个主键,以便于在日志文件或是审核记录中定位相关内容。

  38、定期安排会面时间

  “会议安排得越多越好。实际上,我们要安排更多的会议,直到发现为什么工作总是完不成。”

  [正解]

  也许你个人很讨厌开会,但是沟通是项目成功的关键。我们不只要跟客户谈话,还应该与开发人员进行良好的沟通。要知道其他人在做什么——如果Bernie知道如何解决你的问题,你肯定希望早点搞清楚她是怎么做的,不是吗?

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

  (1) 昨天有什么收获?

  (2) 今天计划要做哪些工作?

  (3) 面临着哪些障碍?

  每日立会有诸多好处。

  (1) 让大家尽快投入到一天的工作中来。

  (2) 如果某个开发人员在某一点上有问题,他可以趁此机会将问题公开,并积极寻求帮助。

  (3) 帮助团队带头人或管理层了解哪些领域需要更多的帮助,并重新分配人手。

  (4) 让团队成员知道项目其他部分的进展情况。

  (5) 帮助团队识别是否在某些东西上有重复劳动而耗费了精力,或者是不是某个问题有人已有现成的解决方案。

  (6) 通过促进代码和思路的共享,来提升开发速度。

  (7) 鼓励向前的动力:看到别人报告的进度都在前进,会对彼此形成激励。

  平衡的艺术

  (1) 会议会占用开发时间,所以要尽量保证投入的时间有较大的产出。立会的时间最长不能超出30分钟,10~15分钟比较理想。

  (2) 如果要使用需提前预定的会议室,就把预定的时间设定为一个小时吧。这样就有机会在15分钟的立会结束后,马上召开更小规模的会议。

  (3) 虽然大多数团队需要每天都碰头,但对于小型团队来说,这样做可能有点过头了。不妨两天举行一次,或者一周两次,这对小团队来说足够了。

  (4) 要注意报告的细节。在会议中要给出具体的进度,但是不要陷入细节之中。例如,“我在开发登录页面”就不够详细。“登录页面目前接受guest/guest作为登录用户名和密码,我明天会连接数据库来做登录验证”,这样的详细程度才行。

  (5) 迅速地开始可以保证会议短小。不要浪费时间等着会议开始。

  (6) 如果觉得立会是在浪费时间,那可能是大家还没有形成真正的团队意识。这并不是坏事,有利于针对问题进行改进。

  39、架构师必须写代码

  “我们的专家级架构师Fred会提供设计好的架构,供你编写代码。他经验丰富,拿的薪水很高,所以不要用一些愚蠢的问题或者实现上的难点来浪费他的时间。”

  [正解]

  优秀的设计从积极的程序员那里开始演化。积极的编程可以带来深入的理解。不要使用不愿意编程的架构师——不知道系统的真实情况,是无法展开设计的。

  架构、设计、编码和测试,这些工作给人的感觉就像是同一个活动——开发的不同方面。感觉它们彼此之间应该是不可分割的。

  40、实行代码集体所有制

  “不用担心那个烦人的bug,Joe下周假期结束回来后会把它解决掉的。在此之前先想个权宜之计应付一下吧。”

  [正解]

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

  (1) 不要无意间丧失了团队的专家技能。如果某个开发人员在某个领域中极其精通,不妨让他作为这方面的驻留专家,而且系统的其他部分代码也对他开放,这样对团队和项目都很有帮助。

  (2) 在大型项目中,如果每个人都可以随意改变任何代码,一定会把项目弄得一团糟。代码集体所有制并不意味着可以随心所欲、到处破坏。

  (3) 开发人员不必了解项目每一部分的每个细节,但是也不能因为要处理某个模块的代码而感到惊恐。

  (4) 有些场合是不能采用代码集体所有制的。也许代码需要某些特定的知识、对特定问题域的了解,比如一个高难度的实时控制系统。这些时候,人多了反而容易误事。

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

  41、成为指导者

  “你花费了大量的时间和精力,才达到目前的水平。对别人要有所保留,这样让你看起来更有水平。让队友对你超群的技能感到恐惧吧。”

  [正解]

  如果你用你的蜡烛点燃了我的,我在得到光明的同时,也没有让你的周围变暗。好主意就像火,可以引领这个世界,同时不削弱自己。

  通过详细解释自己知道的东西,可以使自己的理解更深入。当别人提出问题时,也可以发现不同的角度,也许可以发现一些新技巧。

  与别人共事,激励他们变得更出色,同时可以提升团队的整体实力。

  成为指导者。分享自己的知识很有趣——付出的同时便有收获。还可以激励别人获得更好的成果,而且提升了整个团队的实力。

  你会感到给予别人教导,也是提升自己学识的一种方式,并且其他人亦开始相信你可以帮助他们。

  42、允许大家自己想办法

  “你这么聪明,直接把干净利落的解决方案告诉团队其他人就好了。不用浪费时间告诉他们为什么这样做。”

  [正解]

  “授人以鱼,三餐之需;授人以渔,终生之用。”告诉团队成员解决问题的方法,也要让他们知道如何解决问题的思路,这也是成为指导者的一部分。

  这样做有下面几点好处。

  (1) 你在帮助他们学会如何解决问题。

  (2) 除了答案之外,他们可以学到更多东西。

  (3) 他们不会再就类似的问题反复问你。

  (4) 这样做,可以帮助他们在你不能回答问题时自己想办法。

  (5) 他们可能想出你没有考虑到的解决方法或者主意。这是最有趣的——你也可以学到新东西。

  如果有人还是没有任何线索,那就给更多提示吧(或者甚至是答案)。

  43、准备好后再共享代码

  “别管是不是达到代码签入的要求,要尽可能频繁地提交代码,特别是在要下班的时候。”

  [正解]

  准备好后再共享代码。绝不要提交尚未完成的代码。故意签入编译未通过或是没有通过单元测试的代码,对项目来说,应被视作玩忽职守的犯罪行为。

  44、做代码复查

  “用户是最好的测试人员。别担心——如果哪里出错了,他们会告诉我们的。”

  [正解]

  噢,代码复查不只针对初级开发者编写的代码——团队中每个开发人员的代码都应该进行复查,无论其经验丰富与否。

  在代码复查中要看什么呢?

  (1) 代码能否被读懂和理解?

  (2) 是否有任何明显的错误?

  (3) 代码是否会对应用的其他部分产生不良影响?

  (4) 是否存在重复的代码(在复查的这部分代码中,或是在系统的其他部分代码)?

  (5) 是否存在可以改进或重构的部分?

  复查所有的代码。对于提升代码质量和降低错误率来说,代码复查是无价之宝。如果以正确的方式进行,复查可以产生非常实用而高效的成果。要让不同的开发人员在每个任务完成后复查代码。

  不进行思考、类似于橡皮图章一样的代码复查没有任何价值。

  (1) 代码复查需要积极评估代码的设计和清晰程度,而不只是考量变量名和代码格式是否符合组织的标准。

  (2) 同样的功能,不同开发人员的代码实现可能不同。差异并不意味着不好。除非你可以让某段代码明确变得更好,否则不要随意批评别人的代码。

  (3) 如果不及时跟进讨论中给出的建议,代码复查是没有实际价值的。可以安排跟进会议,或者使用代码标记系统,来标识需要完成的工作,跟踪已经处理完的部分。

  (4) 要确保代码复查参与人员得到每次复查活动的反馈。作为结果,要让每个人知道复查完成后所采取的行动。

  45、及时通报进展与问题

  “管理层、项目团队以及业务所有方,都仰仗你来完成任务。如果他们想知道进展状况,会主动找你要的。还是埋头继续做事吧。”

  [正解]

  及时通报进展与问题。发布进展状况、新的想法和目前正在关注的主题。不要等着别人来问项目状态如何。

  (1) 每日立会可以让每个人都能明确了解最新的进展和形势。

  (2) 在展示进度状况时,要照顾到受众关注的细节程度。举例来说,CEO和企业主是不会关心抽象基类设计的具体细节的。

  (3) 别花费太多时间在进展与问题通报上面,还是应该保证开发任务的顺利完成。

  (4) 经常抬头看看四周,而不是只埋头于自己的工作。