第一章 敏捷-高效软件开发之道

敏捷开发宣言

  1. 个体和交互胜过过程和工具
  2. 可工作的软件胜过面面俱到的文档
  3. 客户协作胜过合同谈判
  4. 响应变化胜过遵循计划

敏捷的精神

  • 一种以人为本、团队合作、快速响应变化和可工作的软件作为总之的开发方法;
  • 快速响应 团队合作
  • 开发需持续不断,切勿时断时续
  • 持续注入能量
  • 危机管理异同:危机管理是指问题累计并恶化,直到问题非常严重,以至于你不得不立即解决,这样会带来负面影响,陷入危机和恐慌的恶性循环中,正是我们要避免的恶性循环;

敏捷的修炼之道

敏捷开发就是在一个相互协作的环境中,不断地使用反馈进行自我调整和完善;

  • 团队,反馈,重构,迭代;
  • 敏捷工具箱: wiki,版本控制,单元测试《单元测试之道java版》,自动构建(持续集成)

第二章 态度决定一切

1 做事

出了问题,第一重要确定元凶,wrong;

  • 指责不能修复bug。矛头对准问题的解决办法,而不是人,这才是正面效应;
  • 用于承认自己不知道答案;团队成员们一起工作,相互帮助,不是指责;
  • 没犯过错,说明没努力工作;
  • 敏捷团队,更多的不是抱怨,不是追究责任,而是解决问题;

2 欲速则不达

不需要真正理解代码,能工作就行了;
不要坠入快速的简单修复中,要投入时间、精力保持代码的整洁;

  • 不深入了解真正的问题,快速修改代码,引发大问题:
  • 防微杜渐
  • 不要孤立的编码;代码复审,确认可读,可理解;
  • 单元测试; 帮助代码分层,也是可执行的文档,看到更小、易于理解的代码;

3 对事不对人

那样会很蠢;
那样很蠢,你忘记考虑它要线程安全;
谢谢,lee先生,但是我想知道,如果两个用户同时登陆会发生什么?

  • 避免情绪化,消极扼杀创新;
  • 紧密合作的团队中,礼貌待人,可以有助于团队关注真正有价值的问题,不是勾心斗角;

集体决策很有效,但是要尊重个别独立的思考人,吸取各方的意见; 另一个是缺乏生气的委员会,每个设计方案要全票通过,小题大做;能容纳自己并不接受的想法,表明你的头脑足够有学识;

  • 有效的特殊技术
  • 设定最终极限;
  • 逆向思维:找出有点最多缺点少的方案;
  • 设立仲裁人;
  • 支持已经做出的决定:设计充满了妥协;
  • 对事不对人,让我们骄傲的应该是解决了问题,而不是比较出谁的主意更好;
  • 脱离实际的反方观点使争论变味,没有最好,只有更好的“最佳实践”,

4 排除万难,奋勇前进

发现别人的代码有问题,心里知道,不伤害,不惹麻烦;
做正确的事,要诚实,有勇气的说出实情;

  • 发现问题,不试图掩盖,要勇气的站起来,意图寻找解决方案;

第三章 学无止境

即使你在正确的轨道上,但如果停滞不前,也会被淘汰出局;

5 跟踪变化

软件技术的变化如此之快,是它的本性,继续使用熟悉的语言做你的老本行,wrong;
跟踪技术变化:你不需要精通所有技术,但需要清除知道行业的动向,从而规划你的项目和职业生涯;

  • 唯有变化是永恒的,技术发展的步伐是如此快速;
  • 迭代和增量式的学习:学习新技术,不熟悉的术语等,记录,研究;
  • 了解最新行情:
  • 参加本地的用户组活动;
  • 参加研讨会议;
  • 阅读

6 对团队投资

不要和别人分享你的知识-自己留着,只要自己聪明就可,不管其他失败者;
每个人都比你厉害吗?恩,那太好了;动力提高自己;

  • 一个学习型的团队才是较好的团队;找出高手擅长的,迎头赶上;
  • 午餐会议:增进每个人的只是和技能,帮助大家聚集在一起进行沟通交流,唤起大家对技术和技巧的激情;会议不是设计会议,关注与应用相关的,具体的设计留到专业会议中;
  • 每周要求团队中一个人主持讲座;
  • 坚持有计划有规律的举行讲座,持续、小步前进才是敏捷;

7 懂得丢弃

那就是你一贯的工作方法,很好为你所用,明显它就是最好的方法,以后不要再改变了。WRONG
学习新的东西,丢弃旧的东西

  • 敏捷的根本之一拥抱变化
  • 根深蒂固的习惯不肯能给你轻易的丢弃掉
  • 打破旧习惯很难
  • 要意识到你正在使用过时的方法
  • 真正的丢弃旧习惯,思维定式很难丢弃

8 打破砂锅问到底

接受别人给你的解释,别人告诉你哪里出问题,就去看什么地方,不需要再浪费时间追根问底;WRONG
不停地问为什么:不能只满足于别人告诉你的表面现象,不停的提问知道你明白问题的根源;

  • 理解一个问题,渐次问5个以上的“为什么”
  • 可能跑题,问“为什么”,要是到问到点子上,要反问自己,为什么问这个问题?

9 把握开发节奏

我们很长时间没有代码复审了,这周复审所有代码,此外,也要做发布计划了,从周二开始,3周时间,做一个发布计划;WRONG
解决任务,在事情变得一团糟之前;保持时间之间稳定重复的间隔,更容易解决常见的重复任务;

  • 很多不成功的项目中,基本随意安排计划,没有任何规律,你根本不知道明天发生什么,敏捷项目会有一个节奏和循环,让开发更轻松;
  • 上帝发明了时间,就是为了防止所有事情同时发生;
  • 时间盒:固定的时间期限促使你做决定,不能再讨论或功能上浪费太多时间,这些时间可以用于具体的工作;
  • 站立会议,迭代时间;
  • 每天结束提交代码,不经常加班,开发节奏过于密集,精疲力尽;
  • 有规律的开发节奏暴露很多问题,让你有更多鼓起勇气的借口;
  • 像减肥一样,一点点的成功也是很大的激励,小而大的目标让每个人全速前进;

第四章 交付用户想要的软件

没有任何计划在遇敌后还能继续执行;
真正的敌人是变化;设计、架构、需求的理解-取决于你识别和适应变化的能力;

10 让客户做决定

开发者兼具创新和智慧,所有关键决定都应开发者定夺,业务人员介入,都会弄得一团糟;WRONG
让你的客户决定;开发者、经理、业务分析师不应该做业务方面的决定;向他们解释遇到的问题,让他们做决定;

  • 开发者能做的一个重要的决定是:判断哪些是自己决定不了的,应该让企业主做决定;
  • 记录客户做出的决定,标明原因;
  • 不用用低阶别和无价值的问题打扰业务人员,但是也不用随意假设低阶别额问题不会影响他们的业务;

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

设计文档应该尽可能详细,这样代码工人敲代码即可,编代码时无论发现什么,决不能偏离设计文档;WROGN
好设计是一张地图,它也会进化;设计指引你向正确的方向前进,不是殖民地,它不应该标识具体的陆续;

  • 设计是必不可少的步骤,帮助你理解系统的谢姐,理解部件和子系统之间的关系,指导你的实现;
  • 敏捷方法建议在开发初期开始编码,但也需要设计,即使有设计文档,也会有意料之外的情况;一些人认为设计尽可能详细,可以简单交付给编码者,认为他们不需要做任何决定。wrong;
  • 设计满足实现即可,不必过于详细;
  • 严格的需求-设计-代码-测试,开发流程是理想和的瀑布式开发防范,导致前面过度的设计,导致项目的生命周期中,更新、维护这些详细设计文档成了主要工作;
  • 设计可分为两层:战略和战术;前期的设计属于战略,只描述总体战略,不应深入到具体的细节;良好的战略设计扮演图的角色,指引你正确方向前进;之后再战术设计,重点集中在单个的方法或数据类型上;
  • 好的设计是正确的,而不是精确的。

12 合理地使用技术

当你开始一个新项目,使用列表中伟大的框架等,让你的新应用具有极高技术含量;WRONG
根据需要选择技术:首先觉得什么是需要的,接着为这些具体的问题评估使用技术,对任何要用的技术,多一些挑剔的问题,真实的做出回答;

  • 盲目地为项目选择技术框架,就好比是为了少变税而生孩子
  • 首先找到真正需要解决的问题:
  • 这个技术框架真能解决这个问题?
  • 你讲被它拴住吗?缺乏可取消性?
  • 维护成本多少?
  • 不用开发你能下载到的东西;
  • 新技术就应该是新工具,可以帮助你更好的工作,它自己不应该成为你的工作。

13 保持可以发布

我们发现一个bug,放下手头的工作,不要经过正规的程序,不用告诉任何人,修复它即可.wrong
保持你的项目时刻可以发布。保证你的系统随时可以编译、运行、测试并立即部署;

  • 已经提交的代码应该随时可以行动;你的项目一直处于可以运行的稳定状态;
  • 简单流程,防止你提交破坏系统的代码;
  • 本地运行测试;
  • 实时拉最新的代码
  • 提交代码;
  • 拥有一个持续集成系统,自动集成并报告集成结果;自动化

14 提早集成,频繁集成

只要没有到开发末尾阶段,不用浪费时间集成代码,到项目的末尾,有充裕的时间来集成;WRONG
提早集成,频繁集成;代码集成是主要的风险来源,要向规避这个风险,就是提交集成,持续而有规律的进行集成;

  • 敏捷一个特点持续开发,尤其几个人开发同一功能要频繁集成代码;
  • 集成和独立是不矛盾的,可以一边进行集成,一边独立开发;
  • 绝不要做大爆炸式的集成;

15 提早实现自动化部署

没问题,可以手工安装产品,尤其是给测试安装,他们都擅长复制需要的文件;WRONG
一开始就实现自动化部署应用;不同的机器用不同的配置文件测试依赖问题;

  • 可重复和可靠的方式,在目标机器上部署你的应用;
  • 质量保证人员应该测试部署过程;
  • 从第一天就开始交付;

16 使用演示获得频繁反馈

这不是你的过错,问题在我们的客户,不停的更改需求,导致项目严重的延期,他们应该清楚想要的东西,然后把需求给我们,才能开发满意的系统;WRONG
清晰课件的开发:在开发的时候,要保持应用课件,每隔一周或两周,邀请所有的客户,给他们演示最新完成的功能,积极获得反馈;

  • 常听到要冻结需求,但实际上需求就是流动着的油墨;
  • 事情总是希望越做越好,缓慢而逐步的方式,给你需求后,不停研究,改善;
  • 给客户演示功能的时间与得到客户需求的时间间隔越长,离最初需求越来越远,应定期与客户会晤,演示已经完成的功能特性;
  • 不一致的术语也是导致需求误解的主要原因,需维护一份项目术语表,确保你与用户真正的沟通;

17 使用短迭代,增量发布

我们为后面三年制定了漂亮的项目计划,列出了所有的任务和可交付的时间表,只要我们那时候发布了产品就可以占领市场WRONG
增量开发:发布带有最小却可用功能块的产品;每个增量开发中,使用1-4周左右迭代周期;

  • 统一过程和敏捷方法使用迭代和增量开发,每一轮的开发基于前一次的功能,为产品增值新的功能;
  • 迭代开发是小且重复的周期里,完成各种开发任务:分析、设计、实现、测试、反馈;迭代的结束就是一个里程碑;
  • 对付大项目,理想的办法就是小步前进;如果打算1两年才交付的项目,应该重新评估和重新计划,因为无法用增量的方式开发的大型系统,应该分解成有用的小系统,在增量开发;
  • 尽快交付产品到用户手里的原因:1 产品有收入,有理由为产品继续投资,获得反馈,理解下一步的功能;2可以让开发者更加专注于自己的工作,如果目标很遥远,很难于专注;

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

对于这个项目,我们必须有固定的报价,需要真个团队的评估,并且必须在年末交付整个项目;WRONG
基于真实工作的评估:让团队和客户一起,真正的在当前项目中工作,做具体实际的评估,让客户控制他们要的功能和预算;

  • 固定价格的合同是hi敏捷团队的难题:客户方如盖楼房,理所应当;软件项目遭遇各种小错误,加上基础需求的变化,不可重复等;提前给出的价格,就几乎不能遵守开发商的承诺;
  • 如果客户一定预先确定项目的报价,需要研究评估的技术:COCOMO模型、功能点分析法;
  • 1:主动提议构建最初、小的、有用部分,让用户使用;
  • 2:迭代一后客户选择:1选择新功能,继续下迭代;2 取消合同,支付费用;
  • 3 继续前进,可以更好的预测下一迭代;
  • 对客户来说,这种好处项目不可能死亡,很早看到进度或不足之处,可以控制项目,随时停止项目;
  • 你所做的就是进行迭代和增量开发;

第五章 敏捷反馈

敏捷项目中,小步前进,不停收集反馈,时刻纠正自己;

19 守护天使

不必为单元测试花费太多的时间和精力,只会浪费时间;WRONG
使用自动化的单元测试;好的单元测试能够为代码问题提供及时的警报,如果无测试,不要进行任何涉及和代码修改;

  • 编写能产生反馈的代码;无意中破坏了什么功能?带上守护天使,确保功能正常工作,需要自动化单元测试;把它看成是一个极好、编写能产生反馈的代码的技术;
  • 确保测试是可重复的,测试边界条件,不要放过任何一个失败的测试;
  • 单元测试能及时提供反馈;让代码更健壮;是解决问题时的探测器;是可信的文档;是学习的工具;
  • 人们不编写测试许多接口是代码的设计缺陷;测试不能太重,要有效;

20 先用它再实现它

前进,先完成所有代码,后面有大量时间看用户是如何思考的;WRONG
先用它再实现它,将TDD作为设计工具,他会为你带来更简单更实效的设计;

  • 编程之前,先写测试;TDD,总是在有一个失败的单元测试后才开始编码;
  • 先写测试,你会站在代码用户的角度思考,不是单纯的实现者;有助于消除过度复杂的设计,让你可以专注于真正需要完成的工作;
  • 好的设计并不意味着需要更多的类;

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

只要代码能在机器运行就可以,谁会关心它是否可以在其他平台工作,你又不用其他平台;WRONG
不同的环境就有不同问题;使用持续集成工具,在每一种支持的平台和环境中运行单元测试,积极寻找问题,而不是等问题来找你;

  • 也许会要求测试团队在支持的平台测试,但手工测试并不是最可靠的测试办法;
  • 使用自动化会节省时间;在多个平台测试,为每个平台设置持续集成系统就行;

22 自动验收测试

很好,你现在用单元测试验证代码是否完成你期望的行为,发给客户吧,很快会知道这是否是用户期望的功能;WRONG
为核心的业务逻辑创建测试;让你的客户单独验证这些测试,要让它们像一般的测试一样可以自动运行;集成测试

  • 关键业务逻辑必须要独立进行严格的测试,并且最后需要通过用户的审批;
  • FIT集成测试框架;客户可以定义带有新功能的使用样本,开发人员编写相应测试代码;

23 度量真实的进度

用自己的时间表报告工作进度,我们会用它做项目计划,不用管那些实际的工作时间,每周填满40小时就可以了;WRONG
度量剩下的工作量;不要用不恰当的度量来欺骗自己或者团队,要评估那些需要完成的待办事项;

  • 时间消逝可以证明:判断工作进度最好是实际花费的时间而不是估计的时间;
  • 专注于你的方向;不应该计算工作量完成的百分比,明确剩下多少工作量没有完成;
  • 清楚知道完成这个任务真正花费的时间;花费的可能比预估的时间长,没有关系,希望这能作为下一次的参考;评估2天,花费6天,系数是3;
  • 能一直让下一步工作可见的,有助于进度度量,使用待办事项;
  • scrum中每个迭代sprint,一般30天,sprint的待办事项列表就是当前迭代任务列表,评估生鲜的工作量;

24 倾听用户的声音

用户就是抱怨,这不是你的过错,是用户太蠢了,连使用手册都看不懂,它不是一个bug,只是用户不明白使用而已;WRONG
每一个抱怨的背后都隐藏了一个事实;得找出真相,修复真正的问题;

  • 这是一个bug;客户需要配置一堆参数,才能运行系统;系统无错误信息,也不崩溃就是黑屏和退出按钮,说明书有一行提到这样的问题,但80%用户都忽略了;当出了错误,首先要尽可能提示;更糟糕的是嘲笑用户愚蠢,而不是真正的解决问题;
  • 不管是产品bug,文档bug,或者是对用户社区理解的bug,都是团队的问题,不是用户的问题;
  • 花费了很大的精力从单元测试之类的代码中获得反馈,缺容易忽略最终用户的反馈;

第6章 敏捷编码

任何一个笨蛋都能够让事情越来越笨重,越复杂,越极端,需要天才的指点及许多的勇气,才能让事情向相反的方向发展;

25 代码要清晰的表达意图

可以工作而且易于理解的代码代码当然好,但是让人觉得聪明更加重要;WRONG?
要编写清晰的而不是讨巧的代码;向代码阅读者明确表达你的意图;可读性查的代码一点都不聪明;

  • 软件设计两种方式:一种设计尽量简单,且明显没有缺陷;二种设计尽量复杂,且没有明显的缺陷;
  • 开发代码应注重可读性,不是图自己方便,代码阅读次数要远远超过编写的次数;代码的清晰程度的优先级应该排在执行效率之前;
  • 改动代码修复bug或添加新功能:首先,理解代码做什么;然后,搞清楚要改变的部分;修改并进行测试;
添加注释//large cup   
注释有事后是为了帮写的不好的代码补漏;
coffeeShop.placeOrder(CoffeeCupSize.large);
  • PIE原则:代码必须明确说出你的意图,而且必须富有表达力;代码意图清晰,表达明确;
  • 不要明日复明日,现在不做的话,以后也不会做的;

26 用代码沟通

如果代码太杂乱无法阅读,就使用注释来说明,每行都加;WRONG
用注释沟通;使用细心选择的、有意义的命名;用注释描述代码意图和约束;注释不能替代优秀的代码;

  • 建立文档两种方式:利用代码本身;利用注释来沟通代码之外的问题;
  • 不要用注释来包裹你的代码;
  • 良好的命名可以传递大量的意图和信息;使用细心挑选的名称和清晰的执行路径,代码几乎不需要注释;
  • 对显而易见的代码增加注释,多此一举;

27 动态评估取舍

性能、生产力、优雅、成本及上市时间,在软件开发过程中都是至关重要的因素,每一项都必须达到最理想状态; WRONG
动态评估权衡:考虑性能、便利性、生产力、成本和上市时间,如果性能表现足够了,就将注意力放在其他因素上,不要为了感觉上的性能提升或者设计的优雅,而将设计复杂化;

  • 任何单个因素独断地强调,而不是考虑它是否是项目成功的必要因素,必然导致灾难的发生;
  • 但是谁来最终判定性能表现已经足够好,或是应用的展现已经足够了;需要客户或是利益相关必须进行评估,并作出相关决定;
  • 没有最佳解决方案;必须对问题评估,并选出最合适的方案,只有明确的评估和权衡,才能得出更好的解决方案;

28 增量式编程

真正的程序员写起代码来,一干就是几小时,根本不停,甚至头不抬。不要停下来编译你的代码,只要一直往下写就好了; WRONG
在很短的编辑/构建/测试循环中编写代码;可以创建更加清晰、简单、易于维护的代码;

  • 增量式编程可以精炼并结构化你的代码,代码被复杂化、一团乱麻的机会减少,会倾向于创建更小的方法和更具内聚的类;也可能改善代码的可读性,拆分成更小的方法,使其易于测试;

29 保持简单

软件是很复杂的东西,随便哪个笨蛋都可以编写出简单、优雅的软件。通过编写史上最复杂的程序,你将会得到美誉和认可,更不同提保住你的工作了。 WRONG
开发可以工作的、最简单的解决方案;除非有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西;

  • 也许你可到一篇文章,得到个设计想法,有个花哨的名称的设计模式,眼前的代码似乎马上用到;但是需要认识到是否真的需要它,不用被迫进行过分设计,不用将代码复杂化;
  • 当别人给解决方案评价说“非常简单易于理解”,可能会让设计者不高兴,他们以程序复杂为荣;但是开发人员应该面带自豪的微笑,以创建简单而可用的设计而骄傲;
  • 简单不是简陋;简单性,像是厨师的收汁调料,从大量材质中得到最浓缩的精华部分;
  • 太过简洁不等于简单,无法达到沟通目的;

30 编写内聚的代码

你要编写新的代码,首先决定放哪,其实放哪问题不大; WRONG
让类的功能尽量集中,让组件尽量小;要避免创建很大的类或组件,也不要创建无所不包的大杂烩类;

  • 内聚型用来评估一个组件中成员功能相关性;内聚程度高,表明各个成员共同完成的一个功能特性,低表示各个成员提供的功能是互不相干,类也要遵循内聚性;
  • 低内聚性的代码造成的后果严重,如果一个类,实现五种不相干的功能,如果这5个发生变化,类必须跟着改,类改变过于频繁,会对这个系统产生涟漪效应,导致更多的维护成本的发生;一个模块应该只有一个发生变化的原因;
  • 内聚会影响一个组件的可重用性;

31 告知,不用询问

不要相信其他对象,毕竟它们是由别人写的,从别人那里去拿需要的信息,然后自己处理,自己决策,不要放弃控制别人的机会;WRONG
告知,不要询问;不要抢别的对象或是组件的工作,告诉它做什么,然后盯着你自己的指责就好了;

  • 面向过程的代码取得信息,然后做出决策;面向对象的代码让别的对象去做事情;
  • 作为调用者,不应该基于被调用对象的状态做任何决策,更不能改变状态,这样的逻辑应该是被调用者对象的责任。
  • 将命令与查询分离开来;命令可能改变对象的状态,而且可能返回一些有用的值;查询仅仅提供给开发人员对象的状态,并不会对其外部的可见状态进行修改;

32 根据契约进行替换

深层次的继承是很棒的,如果你需要其他类的函数,直接继承就好,不用担心你创建的新类会造成破坏,你的调用者可以改变他们的代码,这是他们的问题,不是你的问题;WRONG
通过替换代码来扩展系统;通过替换遵循接口契约的类,来添加并改进功能特性,更多使用委托而不是继承;

  • Liskov替换原则:任何继承后得到的派生类对象,必须可以替换任何被使用的基类对象,而且使用者不必知道任何差异;
  • 当使用继承时,要想想派生类是否可以替换基类,如果不能,想想为什么使用继承?
  • 针对is-a关系使用继承,针对has-a或use-a关系使用委托;聚合是指在类中包含一个对象,并且该对象是其他类的实例,将责任委托给所包含对象来完成;
  • 继承和委托:如果新类可以替换已有的类,继承;新类只是使用已有的类,委托;

第7章 敏捷调试

你也许会对木匠那毫无差错的工作印象深刻,但事实是,真正的高手只是知道如何亡羊补牢;

33 记录问题解决日志

在开发过程中是不是经常遇到似曾相识的问题? 没关系,以前解决过的问题,现在还是可以解决掉的; WRONG
维护一个问题及其解决方案的日志;保留解决方案是修复问题过程的一部分,以后发生相同或类似问题时,就可以很快找到并使用了;

  • 开发人员经常解决问题,当熟悉问题再发生,不记得如何修复;web寻找答案耗时;不如维护一个保存曾遇到问题以及对应解决方案的日志,称每日日志;
  • 不要在同一处跌倒两次;

34 警告就是错误

编译器的警告信息只不过是过分小心了,如果导致后果严重就是错误了,且无法通过编译,现在这些警告,干脆忽略他们就是了;
将警告视为错误;签入带有警告的代码,就跟签入带有错误或者没有通过测试的代码一样,都是极差的做法;签入构建工具中的代码不应该产生任何警告信息;

  • 当程序出现错误时,别无选择,立马修复;出现警告,仍然可以运行程序;但有些警告,可能产生恶劣的影响;if(test=true)产生的警告,就是错误;
  • 有组织忽略类似警告,导致代码行为无法预测,质量直线下降;
  • 让编译器将警告作为错误提示出来,提高警告的报告级别;

35 对问题各个击破

逐行检查代码库中的代码确认恐惧,但要调试一个明显的错误,只有查看整个系统,全部过一遍,毕竟你不知道问题发生在哪里,这是找到它的唯一方式; WRONG;
对问题各个击破;在解决问题时,要将问题域与其周边隔离开,特别是在大型应应用中;

  • 单元测试带来的积极效应之一就是强迫形成代码的分层;这样不但让代码更健壮,且发生问题时,更容易定位来源;
  • 问题发生时,不用试图了解系统素有细节,想认证调试必须将问题与其他模块等分离开,发现问题;
  • 用原型进行分离;识别复杂问题第一步,将问题分离开;对问题各个击破;
  • 二分查找定位问题;也可在问题发起进攻之前,查找问题解决日志;

36 报告所有的异常

不要让程序的调用者看到那些奇怪的异常;处理它们是你的责任,把你调用的一切都包起来,然后发送自己定义的异常或者干脆自己解决掉; WRONG
处理或是向上传播所有的异常;不要将他们压制不管,就算是临时这样做也不行,在写代码时估计到会发生的问题;

  • 调用别人代码,也许会抛异常,试着对其处理,并从失败中恢复;若是可以在用户没有意识情况下继续正常流程最好;但是要是不能恢复,应该让调用代码的用户知道,哪里出了问题;
  • 检查异常让后捕捉异常,并把它传播出去;但是有些开发人员临时方案,捕捉后忽略了异常,让调用者无法明白错误原因,无法处理;
  • 决定谁来处理异常是设计的一部分,不是所有问题都该抛出异常,传播不能处理的异常;

37 提供有用的错误信息

不要吓着用户,吓程序员也不行ing,要提供给他们干净整洁的错误信息。要使用如下这样舒服的词句:“用户错误,替换,然后继续”; WRONG
展示有用的错误信息;提供更易于查找错误细节的方式;发生问题时,要展示出尽量多的支持细节,不过别让用户陷入其中;

  • 当错误发生时,显示通用的信息,告诉用户发生了问题,好过系统崩溃;但是通用的错误消息,无法提供足够的数据定位识别问题;通常方案是记录日志;
  • 记录日志有用,但是不够;对于用户来说,起不到帮助作用,还是一头雾水;不妨在显示给用户的信息中提供更多细节;
  • 首先:提供给用户清晰、易于理解的问题描述和解释;其次,还有提供具备关于错误的详细结束细节给用户,方便开发人员寻找代码中真正问题所在;
  • 开发时可以看到错误信息细节,但进入生产系统,不能把这些底层细节给用户,还是使用错误日志;

第8章 敏捷协作

我不仅发挥了自己的全部能力,还将我所仰仗的人的能力发挥到极致;

38 定期安排会面时间

会议安排的越多越好,实际上,我们要安排更多的会议,直到发现为什么工作总是完不成;WRONG
使用立会;立会可以让团队达成共识;保证会议短小精悍不跑题;

  • 立会让会议快速进行;
  • 昨天有什么收获;
  • 今天计划要做哪些工作?
  • 面临着哪些障碍?
  • 猪与鸡:scrum团队将团队成员比作猪,非团队成员(支持,QA,管理者)是鸡;农场里动物一起开饭店,用熏肉和鸡蛋作为早餐提供;鸡是参与进来;猪可就是放血投入;只有猪才允许参加立会;
  • 好处:
  • 让大家尽快投入到一天的工作;
  • 若有人有问题,可以公开,寻求帮助;
  • 帮助团队带头人了解哪些域需要帮助,重新分配人手;
  • 让团队成员知道项目其他进展;
  • 帮助团队识别是否有重复劳动力,是否有现成方案;
  • 促进代码和思路共享;鼓励向前的动力,彼此形成激励;

39 架构师必须写代码

我们的专家级架构师会提供设计好的架构,供你编写代码,他经验丰富,拿的薪水高,所以不用用一些愚蠢的问题或者实现上的难点来浪费他的时间; WRONG
优秀的设计从积极的程序员那里开始演化;积极的编程可以带来深入的理解;不要使用不愿意编程的架构师-不知道系统的真是情况,是无法展开设计的;

  • 不可能在PTT幻灯片中进行编程;有些架构师项目开始时介入,绘制各种图,然后在代码实现前离开,得不到反馈,他们的架构设计工作不会有很好的收效;
  • 系统的设计者必须亲自投入到实现中去;好的架构师应该指导开发团队,提升他们的水平,以解决更为复杂的问题;通过找到移除软件设计不可逆性的方式,去除所谓架构的概念;
  • 架构、设计、编码和测试,彼此不可分割;

40 实行代码集体所有制

不用担心那个烦人的bug,joe下周假期结束回来欧会把它解决掉的,在此之前先像个权宜之计应付一下把; WRONG
要强调代码的集体所有制; 让开发人员轮换完成系统不同领域中不同模块的不同任务;

  • 任何具备一定规模的应用,都需要多人协作进行开发,不应该申明个人对代码的所有权;多人同时开发时,代码会被频繁地检查、重构及维护;修bug,任何人员都可以完成;也可以让项目的日程安排更容易;
  • 团队中实行任务轮换制,可以让每个成员接触不同部分的代码,提升团队整体的知识和专业技能;同时当知道别人接过自己的代码,也让自己更守规矩;提升代码的整体质量,让其更易于维护和理解,并降低出错率;
  • 不要丧失了团队的专家技能,某个领域精通,可以成为团队的驻留专家,系统的其他部分代码对其开放;

41 成为指导者

你花费了大量的时间和精力,才达到目前的水平,对别人要有所保留,这样让你看起来更有水平,让队友对你超群的技能感到恐惧; WRONG
成为指导者;分享自己的知识很有趣;付出的同时便有收货,还可以激励别人获得更好的成果,而且提升了整个团队的实力;

  • 教学相长;与团队其他人一起共事是很好的学习机会;通过详细解释自己指导的东西,可以使自己的理解更深入;别人提问时,可以发现不同的角度;
  • 与别人共事,激励他们变的更出色,通知可以提升团队的整体实力;
  • 成为指导者,不意味着手把手教团队成员怎么做,或者白板讲座等;多数时候,帮助团队成员提升水平的同时也提高自己;
  • 努力爬到高处,蔑视的眼神轻视他人,似人类本性;切忌无意识情况下,沟通的障碍建立;其他人畏惧或尴尬,不愿提出问题;
  • 结对编程;

42 允许大家自己想办法

你这么聪明,直接把干净利落的解决方案告诉团队其他人就好了;不用浪费时间告诉他们为什么这样做; WRONG
给别人解决问题的机会;指给他们正确的方向;而不是直接提供解决方案;每个人都能从中学到不少东西;

  • 授人以鱼,三餐只需;授人以渔,终生之用;告诉团队成员解决问题的方法;让他们知道如何解决问题的思路;
  • 作为指导者,应该鼓励、引领大家思考如何解决问题;帮助他们学会如何解决问题;除了答案之外,他们可以学到更多东西;他们不会类似的问题反复问你;他们可能相处你没有考虑到的解决方法;

43 准备好后再共享代码

别管是不是达到代码签入的要求,要尽可能频繁的提交代码,特别是在要下班的时候; WRONG
准备好后再共享代码,绝不要提交尚未完成的代码,故意签入编译未通过或是没有通过单元测试的代码,对项目来说应该被视作玩忽职守的犯罪行为;

  • 相对不适用版本控制系统,更坏的是错误使用,方式不对影响生产力、产品稳定性、产品质量、开发日程;
  • 完成任务后应该马上提交代码,让别人集成使用,并开始收集反馈;
  • 任务完成前提交代码,代码坑你有编译错误,或做的某些变化与其他不兼容,影响他人;
  • 通常情况下,应该使用changelog,知道每次修改的地方;
  • 仍然频繁提交代码,不能用“代码尚未完成”作为避免提交代码的借口;

44 做代码复查

用户是最好的测试人员,别担心-如果哪里出错了,他们会告诉我们的; WRONG
复查所有的代码;对于提升代码质量和降低错误率来说,代码复查是无价之宝,如果以正确的方式进行;复查可以产生非常实用而高效的成果;要让不同的开发人员在每个任务完成后复查代码;

  • 管理层担心代码复查耗费时间,开发人员担心别人看到自己代码让自己有受威胁的感觉,影响自尊心;
  • 如何代码复查,基本方式:
  • 通宵复查:每个月进行一次通宵的代码复查之夜;不建议
  • 捡拾游戏:代码写完通过编译测试,准备提交时,其他开发人员捡拾这些代码开始复查;为了消除行为上的惯性;开发人员之间轮换;
  • 结对编程:持续的代码复查活动;
  • 基本的检查列表:
  • 代码能被读懂和理解?
  • 是否有明显错误?
  • 代码是否会对应用其他部分产生不良影响?
  • 是否存在重复代码?
  • 是否有可以改进和重构的部分?
  • 不同人的实现可能不同,差异不意味不好,除非可以让代码更明确更好,否则不要批评别人;

45 及时通报进度与问题

管理层、项目团队及业务所有方,都仰仗你完成任务。如果他们想知道进展状况,会主动找你要的,还是埋头继续做事吧; WRONG
及时通报进展与问题;发布进展状况,新的想法和目前正在关注的主体,不用等着别人来问项目状态如何;

  • 接受一个任务,应为着准时交付;如果等到截止时间发布坏消息,让经理主管失望;他们担心再次失望,开始多次检查工作进度,影响你的生活;
  • 如果你遇到问题,积极通知其他相关各方,等于给机会让他们提前找出解决问题的方案;有情况发生时,就不会让别人感到突然,他们愿意了解目前进展状况,他们会知道何时提供帮助,而且你也获得了他们的信任;

参考《高效程序员的45个习惯:敏捷开发之道》