《高效程序员的45个习惯 - 敏捷开发修炼之道》之读书笔记
多年前阅读此书时,如醍醐灌顶,从那之后,这些书里面的核心思想,慢慢渗透到我的开发生涯之中,受益良多,把内容分享出来,时时阅读。
- 金句子
- 所有学习上的成功,都只靠两件事: 策略和坚持,而坚持本身就应该是最重要的策略之一
- 只有明白”为什么做“,才能解决”如何做“的问题
- 敏捷就是管理变化的
- 程序员在拒绝设计的同时,也就放弃了思考
- 敏捷并不止是针对代码开发,它存在于软件工程的所有环节
- 先解决困难的问题,简单的问题留到最后
- 敏捷依赖人,而不是依赖于项目的甘特图和里程表
- 如果你没有犯任何错误,说明你可能没有努力去工作
- 很多开发者由于脏乱代码和看不懂的逻辑而秃顶
- 每个敏捷开发的"时间盒"必须是短期的
- 好的设计应该是正确的,而不应该是精确的
- 敏捷的一大特点就是持续开发,持续保证可开发,持续保证可发布
- 敏捷使用短迭代
- 给我一份详细的长期计划,我就会给你一个注定完蛋的项目
- 在小且重复的周期中,增量完成各种开发任务: 分析、设计、实现、测试和获得反馈
- 敏捷开发给我的感觉
- 专注且效率
- 能看到一个实际并且确切的目标
- 不会遗留长期悬而未决的问题
- 硬件成本比开发人员的时间便宜
- 开发人员应该为能够创造出来一个简单并且可用的设计而骄傲,而不是以程序的复杂性为荣
- 序
- 什么是敏捷
- 对敏捷的错误理解
- 越快越敏捷
- 只写代码不写文档
- 需要重构而无需设计
- 敏捷迭代就是尽量做到最小
- 敏捷只有天才程序员才能用
- 本意: lightweight processed(轻量型软件开发过程)
- 概括 -> 敏捷开发是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善
- 对敏捷的错误理解
- 敏捷不是目的,而是手段
- 敏捷开发宣言
- 个体和交互胜过过程和工具
- 可工作的软件胜过面面俱到的文档
- 客户协作胜过合同谈判
- 响应变化胜过遵循几乎
- 敏捷精神
- 要求团队中的每个人都有专业的工作态度
- 并非是所有人都是有经验的专业人员
- 每个人都希望尽最大可能做好自己的工作
- 持续推进系统前进和完善
- 需求采集
- 开发
- 技术技能的学习
- 产品部署
- 用户培训
- 要求团队中的每个人都有专业的工作态度
- 如何操作
- 防微杜渐
- 把问题解决在萌芽状态
- 可行性先行
- 探索未知领域,在大量成本投入之前先确定其可行性
- 持续优化团队协作
- 往往是小型团队
- 共享代码和任务
- 大部分时间能在一起工作
- 使用自动化工具构建、测试和集成
- 持续重构
- 编码永远没有真正意义的结束
- 以小步迭代的方式工作
- 尽可能的频繁给客户演示迭代的最新的系统
- 防微杜渐
- 什么是敏捷
- 态度决定一切
- 做事
- 出了问题,最高优先级是解决问题,而不是找到解决掉制造问题的人
- 一再伤害团队的成员需要让他离开
- 如果大部分成员(尤其是领导者)不职业,那么你就应该主动从团队离开,没必要跟随"死亡之旅"
- 欲速则不达
- 出现bug,不要快速修复,而是要真正从根源修复
- 提升代码的清晰度,让代码变得易读
- 要理解团队开发方法,不要孤立地编码
- 使用单元测试
- 对事不对人
- 公正的去讨论
- 不要把对方案设计和实现的讨论,失控成为情绪化的指责
- 每个人都能有一些极好的创新想法,同样也会萌生很蠢的想法
- 负面的评论会扼杀创新
- 不要把对方案设计和实现的讨论,失控成为情绪化的指责
- 尽最大可能放大方案的优缺点
- 设立仲裁人
- 防止开会时明星员工操纵会议,并及时打断务虚发言
- 支持已经做出的决定
- 一旦方案被确定,就必须通力合作
- 公正的去讨论
- 做事
- 学无止境
- 只有变化是不变的,要拥抱变化
- 迭代和增量式学习
- 每段时间给制定一个新技术的学习目标
- 实操
- 要明白为什么需要这项新技术
- 它可以解决什么问题,用在什么地方
- 避免为了学习新技术而直接将应用切换到新技术。必须全面评估造成的影响
- 要明白为什么需要这项新技术
- 对团队投资
- 找出团队中高手擅长的领域,帮助其他成员迎头赶上
- 坚持有计划地举行分享
- 懂得丢弃
- 丢弃旧的不好的习惯和思维定式
- 不停地问"为什么"
- 深入挖掘背后的原因,单点突破,由点方可及面
- 交付用户想要的软件
- 真正的敌人,是变化
- 变化的需求
- 变化的市场
- 成功的软件开发方法,取决于你识别和适应变化的能力
- 保持项目随时可以发布
- 提早实现自动化部署
- 在开发之前就要进行全面自动化部署,而不是等到上线之前
- 能运行在开发环境,也能运行在生产环境
- 最大程度避免手工操作,且应该简单、可靠及可重复
- 提早实现自动化部署
- 提早集成,频繁集成
- 集成的周期越长,成功的风险就越高,代价就越大
- 避免大范围的修改代码
- 将持续集成作为编码的日常部分
- 明确客户/开发人员职责
- 方案设计时,必须有开发参与
- 业务方面的决定,要让客户来做
- 实操
- 记录客户做出的决定,并注明原因,PS: 使用方便的工具,便于同步
- 从开发角度,给客户提出好的业务建议
- 设计和编码都在变化
- 一旦开始,最初的设计和实际编码都处于不断变化中
- 需合理性的更新维护设计文档
- 好的设计应该是正确的,而不应该是精确的
- 战略级别的设计不应说明程序方法、参数、字段等,详细战术设计文档需包含这些。
- 不要在前期做大量的设计
- 一旦开始,最初的设计和实际编码都处于不断变化中
- 合理地使用新技术
- 避免"新技术-简历驱动设计"
- 避免出现不可控的"新技术大杂烩"
- 新技术真的能解决问题吗
- 新技术维护成本多大
- 新技术的引入,必读多问挑剔性的问题
- 如果还没有足够的经验,不要急于决定用什么技术
- 不要开发哪些你容易下载到的东西
- 用户侧
- 统一好用户软件安装所需要的各个版本、数据库、操作系统等
- 在没有征得用户同意前,绝不能删除用户的数据
- 软件需保证可以完整的正确安装,卸载,并升级(如果有的话)
- 尤其是在质量保证人员的电脑上
- 保证考虑了用户侧的设备,网络和权限
- 尽量降低维护安装脚本,把这一切做的最简化
- 频繁给客户演示
- 使用演示获得频繁的反馈
- 减少与客户的理解的需求偏差,最大程度接近真实需求
- 提早发现环境或者功能的bug
- 跟踪问题
- 反馈类型
- 修正
- 建议
- 变更需求
- 功能增强
- bug修复
- ...
- 需保持对反馈的记录
- 反馈类型
- 演示周期根据需求和用户的反馈,动态调整演示周期
- 使用演示获得频繁的反馈
- 需维护一份项目术语表,统一跟用户的术语认知
- 如何报价
- 使用迭代来报价
- 每个迭代周期,提供部分功能,从而判断出一个相对合理的报价
- 避免为整体项目直接报价
- 当然也需要具体针对项目整体报价的能力,毕竟市场如此...
- 使用迭代来报价
- 真正的敌人,是变化
- 敏捷反馈
- 测试
- 清楚要测试的内容
- 确保测试是可重复的
- 测试你的边界条件
- 不要放过任何一个失败的测试
- 一定要有本地单元测试,一旦单元测试到位,方便回归测试和重构代码
- 要使用自动化的单元测试
- 搭建机器,不断获取最新版本代码,然后编译代码,并运行单元测试
- 清楚要测试的内容
- 单元测试
- 及时提供反馈
- 针对修改或者重写的逻辑,测试用例会检查你是否破坏了已有的功能,可以得到快速反馈
- 让代码更加健壮
- 帮你练习正面、反面以及异常情况
- 是有用的设计工具
- 有助于实现简单的、注重实效的设计
- 单元测试会天然强制代码分层
- 是你自信的根本
- 减少盲区,提供稳定性
- 是可信的文档
- 是学习工具
- 通过测试新技术的API,加深理解
- 单元测试需达到一定的测试覆盖率的时候,才能真正发挥作用
- 可使用一些测试覆盖率工具来了解
- 及时提供反馈
- 不同环境,就有不同问题
- 使用持续集成工具,在每一种支持的平台和环境中运行单元测试,持续保证每个环境下软件的可用性
- 错误的反馈最好统一到一个地方,而不是因为一个错误而收到5次通知轰炸
- 度量真实的进度
- 不要用不恰当的度量来欺骗自己和团队
- 要诚实
- 要找到更加合适的方式
- 使用TO-DO来评估还需要多少小时
- 不要用不恰当的度量来欺骗自己和团队
- 倾听用户的声音
- 每一个抱怨的背后都隐藏了真正的问题,即时这个抱怨很low,很愚蠢
- 举办项目复盘会
- 总结本次项目的所有问题,在以后的项目中逐个避免
- 测试
- 敏捷编码
- 代码要清晰的表达意图
- 保持代码的简单
- 注重可读性,而不是只图自己方便和炫技
- 代码清晰程度的优先级甚至应该排在执行效率之前
- 无需对设计模式执着
- 除非有不可辩驳的原因,否则不要使用模式、原则和高难度技术之类的东西
- 为简单的设计而骄傲
- 相比一个过分复杂,拙劣的解决方案,简单的方案通常更加难以获得
- 代码阅读的次数要远远超过编写的次数
- 保持代码的简单
- 用代码沟通
- 好的编码规范可以让代码变得更加容易理解
- 逻辑分离清晰
- 变量名准确
- 表达式简介
- ...
- 清楚的注释
- 大量节省阅读代码的时间
- 可以沟通代码以外的问题
- 可能要说明以下信息
- 为什么需要这个方法
- 需要什么样的输入
- 会更改哪些状态,有哪些返回值
- 可能会发生什么异常
- 在代码可以传递意图的地方,不要使用注释
- 好的编码规范可以让代码变得更加容易理解
- 动态评估取舍
- 没有最佳方案,只有最合适的方案
- 影响因素,要做到平衡
- 性能
- 生产力
- 优雅
- 成本
- 上市时间
- 增量式编程
- 在很短的构建/测试循环中编写代码
- 确保增量过程稳定且易于维护
- 时常保持对代码的精炼
- 编写高内聚的代码
- 单一职责原则
- 内聚性指一个组件(包、模块等)成员的功能相关性,注意好隔离和分类
- 具有高内聚的代码的变化,不会导致别的太多的变化,因此更加稳定
- 低内聚的代码,一旦发生变化,容易引起"涟漪效应",导致无可预估的维护的成本
- 让类的功能尽量集中,让组件尽量小
- 避免创建很大的类和组件,也不要创造"大杂烩"类
- 编码的时候考虑变化及扩展性以及他们造成的影响范围
- 代码要清晰的表达意图
- 敏捷调试
- 所有项目,都有bug,缺陷
- 记录解决问题的日志
- 问题简述
- 解决方案详细描述
- 引用文章及网址,跟多细节信息
- 将解决方案的日志保存为可供搜索的方式 - Wiki
- 警告就是错误!
- 将其配置到持续集成中,并解决掉这些警告
- 应该报告所有的异常!
- 处理掉当前异常,或是向上传播所有的异常,不要将其忽略
- 提供有用的错误信息
- 提供出优雅的错误信息
- 记录错误日志
- 最起码应该是以文本文件的形式维护
- 日志要清晰
- 要易于理解
- 做好日志类型划分的细节,方便日后阅读和索引
- 禁止记录敏感信息
- 对问题各个击破
- 隔离出发生问题的模块,更容易修复。而不必过多关注整个负责的大型系统
- 使用断言来提供与异常报告同样的信息,而不是等待系统出错来发现问题
- 敏捷协作
- 靠单打独斗在车库里面开发出一个完整产品的日子早已不在
- 定期安排会面时间
- 合理动态安排会议周期和时长
- 每天/每N天(视情况而定)的例会
- 昨天做了什么
- 今天计划做什么
- 有什么障碍
- 公开问题,并积极寻求帮助
- 动态分配任务和人手
- 让大家知道项目的进展情况
- 防止多人开发重复的解决方案
- 促进代码和思路的共享,提升效率和质量
- 看到别人的前进,从而形成正向的激励
- 保证会议短小且不跑题
- 例会解决不了的其他问题,可通过专题会议拉上相关人员解决
- 一般10-15分钟较为合适
- 注意报告的具体程度
- 不可太粗略
- 不可太详细
- 架构师必须写代码
- 架构师不应该只是画一些很漂亮的设计图,说一些"黑话",使用一大堆设计模式
- 有太多"PPT"架构师了
- 高度概括的。粗略的设计图无法很好地理解系统
- 通过持续编码来实际了解系统,丰富和改进设计
- 不存在所谓的最终决策,要根据实际和反馈做出改变
- 要鼓励主力程序员参与设计,担任架构师的角色
- 程序员在拒绝设计的同时,也就放弃了思考
- 优秀的设计,从积极的程序员那里开始演化
- 积极的编程可以带来更加深入的理解
- 不要使用不愿意编程的架构师 - 不知道系统的真实情况,是无法展开设计的
- 指导开发团队,提升水平,以解决更为复杂的问题
- 架构师不应该只是画一些很漂亮的设计图,说一些"黑话",使用一大堆设计模式
- 实行代码集体所有制
- 任何成员缺席都不会对项目造成影响
- 保留技术专家对于其他业务代码的权限
- 开发人员要向团队分享设计和代码,以便做人员热备
- 成为指导者
- 相互分享会得到更多的知识
- 不必局限于自己的团队所用的技术
- 开设博客进行技术分享
- 通过指导而加深自己的结构化知识
- 提升团队的整体实力,提升效率和质量
- 允许大家自己想办法
- 合理给出提示即可
- 激励大家,给大家解决问题的机会
- 不要用填鸭式的方式给予别人帮助
- 合理利用版本控制系统
- 控制每次提交的意义
- 控制提交节奏
- 在保证提交意义的同时,尽可能频繁的提交
- 不要向代码库提交正在开发的代码
- 要保证在提交代码之前,所有的单元测试都是通过的
- 使用持续集成是保证源代码控制系统没有问题的良好方式
- 坚持做CodeReview
- 是任何已知形式测试的效果的两倍
- 能移除80%的代码缺陷
- 产出质量极高且稳定的代码
- 每个人都需要进行代码复查
- 基本的检查列表
- 代码能否被读懂和理解
- 是否有明显的错误
- 是否对应用的其他部分产生不良的影响
- 是否存在重复的代码或者重复的开发逻辑
- 是否存在需要重构的部分
- 所有的异常处理程序不允许为空
- 所有的数据库调用都要在包的事务中进行
- 需要积极评估代码的设计和清晰程度
- 不要随意批评别人的代码,每个人的code风格毕竟不一致,要多鼓励,用开放的心态
- 及时跟进代码复查的执行结果
- 及时通报进展及问题
- 出现不同于计划的情况,要及时向上,向大家通报
- 根据不同的汇报对象,给出不同的汇报细节
- 走向敏捷
- 改变不好的习惯,并持续优化这些习惯
- 向大家说明,敏捷开发是让大家的工作变得更加轻松
- 入门习惯
- 版本控制
- 单元测试
- 自动构建