《高效程序员的45个习惯》敏捷开发修炼之道——Subramaniam,Hunt

敏捷开发指的是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善。

一般误认为,敏捷就是快,越快就是越敏捷,岂不知它本来要以 “lightweight process”(轻量级过程)命名,只不过有些参会者不喜欢被看作是在舞台上跳来跳去的轻量级拳手,所以才用了 “敏捷” 这个词。敏捷不是目的,只是手段。只要某个手段适合某个场景,有助于提升质量,提高交付能力,提高开发者水平……一切有利于团队建设、提高生产力的时间都应该频繁且持续做(比如回顾、测试、重构)然后日积月累就养成了习惯。习惯改变行为,行为决定命运。

本书注重于培养软件开发者的态度、原则、操守、价值观。

只有明白了 “为什么做”,才能够解决 “如何做” 的问题。为什么要做这件事情?它所带来的好处是什么?如果不做它又会有哪些坏处?

迭代开发,价值优先

分解任务,真实进度

站立会议,交流畅通

用户参与,调整方向

结对编程,代码质量

测试驱动,安全可靠

持续集成,尽早反馈

自动部署,一键安装

定期回顾,持续改进

不断学习,提高能力

第1章 敏捷——高效软件开发之道

“不管路走了多远,错了就要重新返回。”——土耳其谚语

敏捷:只关注真正重要的事情,少关注那些占用大量时间而无甚裨益的不重要的事情。

敏捷开发:一种把以人为本、团队合作、快速响应变化和可工作的软件作为宗旨的开发方法。

敏捷的重点:贯穿项目的整个生命周期,持续开发、持续反馈。

开发要持续不断,切勿时续时新 = Continuous development, not episodic

持续注入能量 = Inject energy

科普:

重构:在功能不变的情况下,重新设计部分代码,改善代码的质量。

Wiki:Wiki 是一个网站,用户通过浏览器,就可以编辑网页内容并创建链接到一个新的内容页面。Wiki 是一种很好的支持协作的工具,因为团队中的每一个人都可以根据需要动态地新增和重新组织网页中的内容,实现知识共享。

版本控制:项目开发中所有的产物(全部的源代码、文档、图标、构建脚本等)都需要放入版本控制系统中,由版本控制系统来统一管理。

单元测试:用代码来检查代码,这是开发者获得反馈的主要来源。

自动构建:不管是在自己的本地机器上实现构建,还是为整个团队实现构建,都是全自动化并可重复。因为这些构建一直运行,所以又称为持续集成。和单元测试一样,有大量的免费开源产品和商业产品为你提供支持。

第 2 章 态度决定一切

“选定了要走的路,就是选定了它通往的目的地。”——Harry Emerson Fosidick(美国基督教现代主义神学家)

1.做事

2.欲速则不达

3.对事不对人

4.排除万难,奋勇前进

最高优先级应该是解决问题。为了解决或缓解这个问题,我能够做些什么。专业的态度是着眼于项目和团队的积极结果,关注个人和团队的成长,围绕最后的成功开展工作。集中注意力,你是为做事而工作的。

千里之堤,溃于蚁穴,大灾难是逐步演化来的。一次又一次的快速修复,每一次都不探究问题的根源,久而久之就形成了一个危险的沼泽地,最终会吞噬整个项目的生命。只要我们继续进行快速修复,代码的清晰度就不断降低。一旦问题累积到一定程度,清晰的代码就不复存在,只剩下一篇混沌。不要坠入快速的简单修复之中。要投入时间和精力保持代码的整洁、敞亮。拙劣的代码工人会这样不假思索地改完代码,然后快速转向下一个问题。优秀的程序员会挖掘更深一层,尽力去理解为什么这里必须要加1,更重要的是,他会想明白会产生什么其他影响。

好的软件开发作品和好的软件设计,都需要大量的创造力和洞察力。分享并融合各种不同的想法和观点,远远胜于单个想法为项目带来的价值。在一个需要紧密合作的开发团队中,如果能稍加注意礼貌对待他人,将会有益于整个团队关注真正有价值的问题,而不是勾心斗角,误入歧途。

指责不能修复bug = Blame doesn’t fix bugs

防微杜渐 = Beware of land mines

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

使用单元测试 = Use unit tests

消极扼杀创新 = Negativity kills innovation

你不需要很出色才能起步,但是你必须起步才能变得很出色。——Les Brown(全球领军励志演讲家和作家)

绝妙的计划会因为勇气不足而最终失败。你必须有勇气向前冲锋,做你认为对的事情。

有效的特殊技术:

- 设定最终期限。没有最好的答案,只有更合适的方案。

- 逆向思维。先是积极地看到它的正面,然后在努力地从反面去认识它。

- 设立仲裁人。仲裁人的责任就是确保每个人都有发言的机会,并维持会议的正常进行。

- 支持已经做出的决定。我们的目标是让项目成功满足用户需求。

第 3 章 学无止境

“即使你已经在正确的轨道上,但如果只是停止不前,也仍然会被淘汰出局。”——Will Rogers(美国著名演员)

5、跟踪变化

6、对团队投资

7、懂得丢弃

8、打破砂锅问到底

9、把握开发节奏

敏捷的根本之一就是拥抱变化。“唯有变化是永恒的。”——赫拉克利特

你不需要精通所有的技术,但需要清楚知道行业的动向,从而规划你的项目和职业生涯。如何才能跟上技术变化的步伐?

- 迭代和增量式的学习。每天计划用一段时间来学习新技术

- 了解最新行情。

- 参加本地的用户组活动。

- 参加研讨会议。

- 如饥似渴地阅读。

午餐会议可以增进每个人的知识和技能,并帮助大家聚集在一起进行沟通交流。唤起人们对技术和技巧的激情,将会对项目大有裨益。

根深蒂固的习惯不可能轻易地就丢弃掉 = Expensive mental models aren’t discarded lightly.

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

许多的敏捷技巧来源于时间盒——设定一个短时的期限,为任务设定不能延长的最终期限。你可以选择放弃其他方面的任务,但是最终期限是不变的。每个时间盒必须是短期的、有效的,并且要完成具体的目标。当你遇到艰难抉择的时候,固定的时间期限会促使你做决定。

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

“没有任何计划在遇敌后还能继续执行。”——Helmuth von Moltke(德国陆军元帅)

10、让客户做决定

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

12、合理地使用技术

13、保持可以发布

14、提早集成,频繁集成

15、提早实现自动化部署

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

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

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

开发者(及项目经理)能做的一个最重要的决定就是:判断哪些事自己决定不了的,应该让企业主做决定。开发者、经理或者业务分析师不应该做业务方面的决定。用业务负责人能够理解的语言,向他们详细解释遇到的问题,并让他们做决定。(决定什么不该决定 = Decide what you shouldn’t decide)

任何设计仅是一个起跑点:它就像你的代码一样,在项目的生命周期中,会不停地进一步发展和提炼。(战略设计与战术设计 = Strategic versus tactical design)好的设计应该是正确的,指引你向正确的方向前进,而不是精确的,它不应该标识具体的路线。也就是说,它描述的一切必须是正确的,不应该设计不确定或者可能会发生变化的细节。它是目标,不是具体的处方。(设计满足实现即可,不必过于详细 = Design should be only as detailed as needed to implement)好的设计十分重要。画关键工作图(例如,用UML)是必不可少的,因为要使用类及其交互关系来描绘系统是如何组织的。在做设计的时候,你需要花时间去思考(讨论)各种不同选择的缺陷和益处,以及如何做权衡。

根据需求选择技术。首先决定什么是你需要的,接着为这些具体的问题评估使用技术。对任何要使用的技术,多问一些挑剔的问题,并真实地作出回答。(盲目地为项目选择技术框架,就好比是为了少交税而生孩子 = Blindly picking a framework is like having kids to save taxes)不要开发你能下载到的东西 = Don’t build what you can download 虽然有时需要从最基础开发所有你需要的东西,但那是相当危险和昂贵的。

任何时候只要你没有准备好,那就是敌人进攻你的最佳时机。保持你的项目时刻可以发布,你的系统随时可以编译、运行、测试并立即部署。(已提交的代码应该随时可以行动 = Checked-in code is always ready for action)防止提交破坏系统的代码工作流程:在本地运行测试—>检出最新的代码—>提交代码。

代码集成是主要的风险来源。要想规避这个风险,只有提早集成,持续而有规律地进行集成。(绝不要做大爆炸式的集成 = Never accept big-bang integration)

一开始就进行全面部署,而不是等到项目的后期。使用部署系统安装你的应用,在不同的机器上用不同的配置文件测试依赖的问题。系统的安装或者部署应该简单、可靠及可重复。(质量保证人员应该测试部署过程 = QA should test deployment)

在开发的时候,要保持应用可见(而且客户心中也要了解)。每隔一周或者两周,邀请所有的客户,给他们演示最新完成的功能,积极获得他们的反馈。演示是用来让客户提出反馈的,有助于驾驭项目的方向。(需求就像是流动着的油墨 = Requirements are as fluid as ink)

短迭代让人感觉非常专注且具效率。你能看到一个实际并且确切的目标。发布带有最小却可用功能块的产品。每个增量开发中,使用 1~4 周左右迭代周期。(给我一份详细的长期计划,我就会给你一个注定完蛋的项目 = Show me a detailed long-term plan, and I’ll show you a project that’s doomed)

基于真实工作的评估。让团队和客户一起,真正地在当前项目中工作,做具体实际的评估。由客户控制他们要的功能和预算。(固定的价格就是保证要背叛承诺 = A fixed price guarantees a broken promise)

第 5 章 敏捷反馈

“一步行动,胜过千万专家的意见。”——Bill Nye,The Science Guy科普节目主持人

19、守护天使

20、先用它再实现它

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

22、自动验收测试

23、度量真实的进度

24、倾听用户的声音

好的单元测试能够为你的代码问题提供及时的警报。如果没有到位的单元测试,不要进行任何设计和代码修改。(编写能产生反馈的代码 = Coding feedback)

将 TDD 作为设计工具,它会为你带来更简单更有实效的设计(编码之前,先写测试 = Write tests before writing code)好的设计并不意味着需要更多的类 = Good design doesn’t mean more classes

使用持续集成工具,在每一种支持的平台和环境中运行单元测试。要积极地寻找问题,而不是等问题来找你。(使用自动化会节省时间 = Automate to save time)

不要用不恰当的度量来欺骗自己或者团队。要评估那些需要完成的待办事项(backlog)(专注于你的方向 = Focus on where you’re going)

第 6 章 敏捷编码

“任何一个笨蛋都能够让事情变得越来越笨重、越来越复杂、越来越极端。需要天才的指点以及许多的勇气,才能让事情向相反的方向发展。”——John Dryden

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

26、用代码沟通

27、动态评估取舍

28、增量式编程

29、保持简单

30、编写内聚的代码

31、告知,不要询问

32、根据契约进行替换

开发代码时,应该更注重可读性,而不是只图自己方便。例如,如果默认参数或可选参数会影响代码可读性,使其更难以理解和调试,那最好明确地指明参数,而不是在以后让人觉得迷惑。

源代码可以被读懂,不是因为其中的注释,而应该是由于它本身优雅而清晰——变量名运用正确(i 表示循环索引变量。s 常被用来表示一个字符串)、空格使用得当、逻辑分离清晰,以及表达式非常简洁。使用细心选择的、有意义的命名。用注释描述代码意图和约束。代码能够自解释,而不用依赖注释,注释不能替代优秀的代码。(不要用注释来包装你的代码 = Don’t comment to cover up)

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

增量式编程可以提炼并结构化你的代码。敏捷的方式在于持续做一些细小而有用的事情,而不是做一段长时间的编程和重构。

优雅是易于理解和辨识的,但是要想创造出来就困难得多了(简单不是简陋 =  Simple is not simplistic)。

如果一个类的方法和属性共同完成了一个功能(或者一系列紧密相关的功能),这个类就是内聚的。要避免创建很大的类或组件,也不要创建无所不包的大杂烩类。

面向过程的代码取得信息,然后做出决策。面向对象的代码让别的对象去做事情。作为某段代码的调用者,开发人员绝对不应该基于被调用对象的状态来做出任何决策,更不能去改变该对象的状态。这样的逻辑应该是被调用对象的责任,而不是你的。(将命令与查询分离开来 = Keep commands separate from queries)

任何继承后得到的派生类对象,必须可以替换任何被使用的基类对象,而且使用者不必知道任何差异。换句话说,某段代码如果使用了基类中的方法,就必须能够使用派生类的对象,并且自己不必进行任何修改。

第 7 章 敏捷调试

“你也许会对木匠那毫无差错的工作印象深刻。但我向你保证,事实不是这样的。真正的高手只是知道如何亡羊补牢。”——Jeff Miller,家具制造者、作家

33、记录解决问题的日志

34、警告就是错误

35、对问题各个击破

36、报告所有的异常

37、提供有用的错误信息

保留解决方案是修复问题过程的一部分,以后发生相同或类似问题时,就可以很快找到并使用了。每日日志daylog(不要在同一处跌倒两次 = Don’t get burned twice)

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

识别复杂问题的第一步,是将它们分离出来。(用原型进行分离 = Prototype to isolate)

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

在开发过程中,如果定位和修复问题让人被受挫则,就考虑使用更加积极主动的错误报告方式。展示有用的错误信息(错误类型:程序缺陷、环境问题、用户错误。)。提供更易于查找错误细节的方式。发生问题时,要展示出尽量多的支持细节,不过别让用户陷入其中。

第 8 章 敏捷写作

“我不仅发挥了自己的全部能力,还将我所仰仗的人的能力发挥到极致。”——伍德罗·威尔逊,美国第 28 任总统

38、定期安排会面时间

39、架构师必须写代码

40、实际代码集成所有制

41、成为指导者

42、允许大家自己想办法

43、准备好后再共享代码

44、做代码复查

45、及时通报进展与问题

沟通是项目成功的关键(昨天有什么收获?今天计划要做哪些工作?面临着哪些障碍?)使用立会。立会可以让团队达成共识。保证会议短小精悍不跑题。

优秀的设计从积极的程序员那里开始演化。积极的编程可以带来深入的理解。不要使用不愿意编程的架构师。(不可能在 PowerPoint 幻灯片中进行编程 = You can’t code in PowerPoint)没有哪个决策做出之后就是板上钉钉的。

让开发人员轮换完成系统不同领域中不同模块的不同任务。

分享自己的知识很有趣——付出的同时便有收获。还可以激励别人获得更好的成果,而且提升了整个团队的实力。(教学相长 = Knowledge grows when given)

给别人解决问题的机会。指给他们正确的方向,而不是直接提供解决方案。每个人都能从中学到不少东西。能欣赏自己并不接受的想法,表明你的头脑足够有学识。——亚里士多德

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

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

及时通报进展与问题,有情况发生时,就不会让别人感到突然,而且他们也很愿意了解目前的进展状况。他们会知道何时应提供帮助,而且你也获得了他们的信任。

第 9 章 尾声:走向敏捷

“一灯能除千年暗,一智能灭万年愚。”——慧能,中国禅宗第 6 代祖师

读后感:习惯改变行为,行为决定命运。养成好的习惯真的很重要,虽然这里写的是高效程序员的45个习惯,但对于不是程序员的人来说,也是很有指导意义的。我们的人生也是需要不断的通过复盘来回归正道,一个大项目就像一个成人,有着精密的自我调试能力,如果一直积累一些不好的习惯,最后这个项目就会 bug 层出不穷,在解 bug 的过程中常常牵一发而动全身,解决了一个又出现了两个,唯有养成好的习惯,不断的迭代、回顾、总结才能走到最后。

你可能感兴趣的:(《高效程序员的45个习惯》敏捷开发修炼之道——Subramaniam,Hunt)