敏捷开发修炼之道

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

  1. 敏捷开发宣言

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

    • 开发要持续不断,切勿时断时续
    • 持续注入能量
  3. 敏捷的修炼之道

    • 敏捷开发就是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善。
    • 在功能不变的情况下,重新设计部分代码,改善代码质量,这就是所谓的重构
  4. 敏捷工具箱

    • Wiki
    • 版本控制
    • 单元测试
    • 自动构建

2. 态度决定一切

  1. 做事

    • 指责不能修复bug
      把矛头对准解决问题的办法,而不是人。这是真正有用处的正面效应。
    • 切身感受
      勇于承认自己不知道的答案,这会让人感到放心。
  2. 欲速则不达

    • 防微杜渐
    • 不要孤立地编码
      实行代码复查,不仅有助于代码更好理解,而且是发现bug最有效的方法之一。
    • 使用单元测试
      单元测试帮助你很自然地把代码分层,分成很多可管理的小块,这样就会得到设计更好、更清晰地代码。
    • 不要坠入快速的简单修复之中。
      要投入时间和精力保持代码的整洁、敞亮。
  3. 对事不对人

    • 引导性的提出一个疑问,让他们自己意思到问题。
    • 要专业而不是自我。
    • 消极扼杀创新。
    • 能欣赏自己并不接受的想法,表明你的头脑足够有学识。
    • 有效的特殊技术:
      1. 设定最终期限
        没有最好的答案,只有更合适的方案。
      2. 逆向思维
        团队中的每个成员都应该意思到权衡的必要性。
      3. 设定仲裁人
        仲裁人的责任就是确保每个人都有发言的机会,并维持会议的正常进行。
      4. 支持已经做出的决定
        我们的目标是让项目成功满足用户需求。结果最重要。
    • 让我们骄傲的应该是解决了问题,而不是比较出谁的主意更好。
  4. 排除万难,奋勇前行

    • 当发现问题时,不要试图掩盖这些问题。
    • 践行良好习惯。
    • 要诚实,要有勇气去说出实情。有时,这样做很困难,所以我们需要有足够的勇气。
    • 如果受到了缺乏背景知识的决策者的抵制,你需要用他们能够听懂的话语表达。

3. 学无止境

敏捷需要不断的学习和充电

  1. 跟踪变化

    • 迭代和增量式的学习
      每天计划用一段时间来学习新技术,它不需要很长时间,但需要经常进行
    • 了解最新行情
      互联网上有大量关于学习新技术的资源
    • 参加本地的用户组活动
    • 参加研讨会议
      计算机大会在世界各地举行,许多知名的顾问或作者主持研讨会或课程。这些聚会是向专家学习的最直接的好机会
    • 如饥似渴地阅读
    • 你不需要精通所有技术,但需清楚的知道行业的动向,从而规划你的项目和职业生涯。
  2. 对团队投资

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

    • 根深蒂固的习惯不可能轻易地就丢弃掉
    • 学习新的东西,丢弃旧的东西
      在学习一门新技术的时候,要丢弃会阻止你前行的旧习惯。毕竟,汽车要比马车车厢强得多。
  4. 打破砂锅问到底

    • 不停地问为什么
      不能只满足别人告诉你的表面现象。要不停地提问知道你明白问题的根源。
  5. 把握开发节奏

    • 敏捷项目会有一个节奏和循环,让开发更加轻松。
    • 当你遇上艰难抉择的时候,固定的时候期限会促使你做决定。
    • 解决问题,在事情变得一团糟之前
      保持事件之间稳定重复的间隔,更容易解决常见的重复任务
    • 项目开发需要有一致的稳定的节奏

4. 支付用户想要的软件

没有任何计划在遇敌后还能继续执行。

  1. 让客户做决定
    • 在设计方面,做决定的时候必须有开发者参与。
    • 决定什么不该决定
      判断哪些是自己决定不了的,应该让企业主决定
    • 让你的客户做决定
      开发者、经理或者业务分析师不应该做业务方面的决定。用业务负责人能够理解的语言,向他们详细解释遇到的问题,并让他们做决定。
    • 记录客户做出的决定,并注明原因。
    • 不要用过于具体和没有价值的原因打扰繁忙的业务人员。如果问题没有影响,就应该是没有价值的。
  2. 让设计指导而不是操作开发
    • 设计满足实现即可,不必过于详细
    • 设计可以分为两层:
      • 战略
        只描述总体战略,不应深入到具体的细节,扮演的是地图的角色,指引你向正确的方向前进。
      • 战术
        战术设计的重点是集中在单个的方法或数据类型上。这时适合讨论如何设计类的职责。
    • 好设计是一张地图,它也会进化。
      设计指引你向正确的方向前进,它不是殖民地,他不应该标识具体的路线。你不要被设计操纵。
  3. 合理地使用技术

    • 盲目地为项目选择技术框架,就好比是为了少交税而生孩子。
    • 找到了需要解决的问题,接下来需要考虑:
      • 这个技术框架真的能解决这个问题吗?
        如果需要,先做一个小的原型。
      • 你将会被它拴住吗?
        一些技术缺乏可取消性,一旦你使用了它,就会被它套牢,再也不可能回头了。
      • 维护成本是多少?
    • 不要开发你容易下载到的东西
    • 根据需要选择技术
      首先决定什么是你需要的,接着为这些具体的问题评估使用技术。对任何要使用的技术,多问一些挑剔的问题,并真实地作出回答。
  4. 保持可以发布

    • 已提交的代码应该随时可以行动
    • 防止你提交破坏系统代码的简单工作流程:
      • 在本地运行测试
      • 检出最新的代码
      • 提交代码
    • 持续集成系统
      在后台不停地检出、构建和测试代码的应用
    • 保持你的项目时刻可以发布
      保证你的系统随时可以编译、运行、测试并立即部署
  5. 提早集成,频繁集成

    • 集成和独立不是相互矛盾的,你可以一边进行集成,一边进行独立开发。
    • 决不要做大爆炸式的集成
    • 代码集成是主要的风险来源。要想规避这个风险,只有提早集成,持续而有规律地进行集成
  6. 提早实现自动化部署

    • 质量保证人员(QA)应该测试部署过程
    • 一开始就实现自动化部署应用
      使用部署系统安装你的应用,在不同的机器上用不同的配置文件测试依赖的问题。质量保证人员要像测试应用一样测试部署。
  7. 使用演示获得频繁反馈

    • 需求就像是流动着的油墨
    • 清晰可见的开发
      在开发的时候,要保持应用可见(而且客户心中也要了解)。每隔一周或者两周,邀请所有的客户,给他们演示最新完成的功能,积极获得他们的反馈。
  8. 使用短迭代,增量发布

    • 统一过程和敏捷方法都使用迭代和增量开发。
    • 迭代开发: 你在小且重复的周期里完成各种开发任务:分析、设计、实现、测试和获得反馈。
    • 给我一个详细的长期计划,我就会给你一个注定完蛋的项目
    • 增量开发: 发布带有最小却可用功能块的产品。每个增量开发中,使用1~4周左右迭代周期。
  9. 固定的价格就意味着背叛承诺

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

5. 敏捷反馈

  1. 守护天使

    • 编写能产生反馈的代码
    • 自动化单元测试
      • 确保测试是可重复的
      • 测试你的边界条件
      • 不要放过任何一个失败的测试
    • 单元测试能及时提供反馈
    • 单元测试让你的代码更加健壮
    • 单元测试是有用的设计工具
    • 单元测试是让你自信的后台
    • 单元测试是解决问题时的探测器
    • 单元测试是可信的文档
    • 单元测试是学习工具
    • 使用自动化的单元测试
      好的单元测试能够为你的代码问题提供及时的警报。如果没有到位的单元测试,不要进行任何设计和代码修改。
  2. 先用他再实现它

    • 编码之前,先写测试
    • 好的设计并不意味着需要更多的类。
    • 将TDD(Test Driven Development)作为设计工具,它会为你带来更简单更有效用的设计。
  3. 不同环境,就有不同问题

    • 使用自动化会节省时间
    • 使用持续集成工具,在每一种支持的平台和环境中运行单元测试。要积极地寻求问题,而不是等问题来找你。
  4. 自动验收测试

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

    • 专注于你的方向
    • 不要用不恰当的度量来欺骗自己或者团队。要评估那些需要完成的待办事项。
  6. 倾听用户的声音

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

6. 敏捷编码

  1. 代码要清楚的表达意图

    • 设计软件有两种方式。
      一种是设计得尽量简单,并且明显没有缺陷。另外一种方式是设计的尽量复杂,并且没有明显的缺陷。
    • PIE(Program Intently and Expressively)原则
      代码必须明确说明你的意图,而且必须富有表达力。这样可以让代码更易于被别人阅读和理解。代码不让人感到迷惑,也就减少了发生潜在错误的可能。一言以蔽之,代码应意图清晰,表达明确。
    • 要编写清晰的而不是讨巧的代码
      向代码阅读者明确表明你的意图。可读性差的代码一点都不聪明。
  2. 用代码沟通

    • 不要用注释来包裹你的代码
    • 注释可用来为读者指定一条正确的代码访问路线图。为代码中的每个类或模块添加一个短小的描述,说明其目的以及是否有特别的需求。对于类中的每个方法可能要说明以下信息:
      • 目的: 为什么需要这个方法
      • 需求(前置条件): 方法需要什么样的输入,对象必须处于何种状态,才能让这个方法工作
      • 承诺(后置条件) :方法成功执行后,对象处于什么样的状态,有那些返回值。
      • 异常:可能会发生什么样的问题, 会抛出什么样的异常。
    • 用注释沟通
      使用细心选择的、有意义的命名。用注释描述代码意图和约束。注释不能代替优秀代码。
  3. 动态评估取舍

    • 没有最佳解决方案
    • 动态评估权衡
      考虑性能、便利性、生产力、成本和上市时间。如果性能表现足够了,就将注意力方法其他因素上。不要为了感觉上的性能提升或者设计上的优雅,而将设计复杂化。
  4. 增量式编程

    • 关键在于持续做一些细小而有用的事情,而不是做一段长时间的编程或重构。
    • 在很短的编辑/构建/测试循环中编写代码
      这要比花费长时间仅仅做编写代码的工作好得多。可以创建更加清晰、简单、易于维护的代码。
  5. 保持简单

    • 简单不是简陋
    • 开发可以工作的、最简单的解决方案
      除非·有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西。
  6. 编写内聚的代码

    • 内聚性用来评估一个组件(包、模块或配件)中成员的功能相关性。
    • 让类的功能尽量集中,让组件尽量小。
      要避免创建很大的类或组件,也不要创建无所不包的大杂烩类。
  7. 告知, 不要询问

    • 面向过程的代码取得信息,然后做出决策。面向对象的代码让别的对象去做事情。
    • 将命令与查询分离开来
    • 不要抢别的对象或是组件的工作。告诉它做什么,然后盯着你自己的职责就好了。
  8. 根据契约进行替换

    • Liskov替换原则:任何继承后得到的派生类对象,必须可以替换任何被使用的基类对象,而且使用者不必知道任何差异。
    • 针对is-a关系使用继承;针对has-a或uses-a关系使用委托
    • 通过替换代码来扩展系统:通过替换遵循接口契约的类,来添加并改进功能特性。要多使用委托而不是继承。

7. 敏捷调试

  1. 记录解决问题的日志

    • 不要在同一个地方跌倒两次
      每日日志
    • 维护一个问题及其解决方案的日志
      保留解决方案是修复问题过程的一部分,以后发生相同或类似问题时,就可以很快找到并使用了。
    • 要记录团队做出一个重要决策的原因
  2. 警告就是错误

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

    • 用原型进行分离
    • 对问题进行各个击破
      在解决问题时,要将问题域与其周边隔离开,特别是在大型应用中。
  4. 报告所有的异常

    • 处理或是向上传播所有的异常
      不要将它们压制不管,就算是临时的也不行。在写代码时要估计到会发生的问题。
  5. 提供有用的错误信息

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

      • 程序缺陷
      • 环境问题
      • 用户错误
    • 通过跟踪记录报告的错误类型,可以为受众提供更加合适的建议。

8. 敏捷协作

  1. 定期安排会面时间

    • 要保证会议议题不会发散,每个人都应该只回答下述三个问题:
      • 昨天有什么收获?
      • 今天计划要做哪些工作?
      • 面临着哪些障碍?
    • 每日立会有诸多好处:

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

  2. 架构师必须写代码

    • 不可能在PowerPoint幻灯片中进行编程
    • 新系统的设计者必须要亲自投入到实现中去
    • 架构师最主要的任务是通过找到移动软件设计不可逆的方式,从而去除所谓架构的概念
    • 增加可逆性是注重时效的软件实现方式的关键构成部分
    • 优秀的设计从积极的程序员那里开始演化
      积极的编程可以带来深入的理解。不要使用不愿意编程的架构师——不知道系统的真实情况,是无法展开设计的。
  3. 实行代码集体所有制

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

    • 教学相长(knowledge grows when given)
    • 分享自己的知识很有趣——付出的同时便有收获。还可以鼓励别人获得更好的成果,而且提升了整个团队的实力。
    • 结对编程是一种进行高效指导的、很自然的环境
  5. 允许大家自己想办法

    • 能欣赏自己并不接受的想法,表明你的头脑足够有学识
    • 给别人解决问题的机会
      指给他们正确的方向,而不是直接提供解决方案。每个人都能从中学到不少东西
  6. 准备好后再共享代码

    • 代码不执行提交操作的其他安全选择

      • 使用远程访问
      • 随身携带
      • 使用带有底座扩展的笔记本电脑
      • 使用源代码控制系统的特性
    • 绝不要提交尚未完成的代码。故意签入编译未通过或没有经过单元测试的代码,对项目而言,应被视为玩忽职守的犯罪行为

  7. 做代码复查

    • 代码复查和缺陷移除
      要寻找深藏不露的程序bug, 正式的进行代码检查,其效果是任何已知形式测试的两倍,而且是移除80%缺陷的唯一已知方法
    • 对于提升代码质量和降低错误率来说,代码复查是无价之宝。如果以正确的方式进行,复查可以产生非常实用而高效的成果。要让不同的开发人员在每个任务后复查代码
    • 除非你可以让某段代码明确变得更好,否则不要随便批评别人的代码
  8. 及时通报进展与问题

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

9. 尾声: 走向敏捷

  • 一灯能除千年暗,一智能灭万能愚
  • 只要一个新的习惯,就让团队发生了巨大的变化
  • 拯救频临失败的项目
    如果事态没有那么糟糕,可以采取更加全面、整齐的方式来引入敏捷习惯
    • 引入敏捷:管理员指南
    • 引入敏捷:程序员指南

你可能感兴趣的:(软件工程,敏捷开发,软件开发,单元测试)