敏捷开发就是在一个高度协作的环境中,不断地使用反馈进行自我调整和完善.
态度决定一切
做事, 追求结果:
- 以结果为导向, 一切的工作都围绕”把事情做成”. 有问题解决问题, 不允许相互指责, 批判错误而不批判人
- 如果一个成员一再做伤害团队的事情, 无疑显示了他的不专业, 不专业的人无法帮助团队前进
- 当团队中大部分都不专业, 并且没有工作目标, 及早离开
戒骄戒躁,步步为营
- 改代码之前, 要先理解代码. 同样, 要理解团队的开发方法和开发过程, 遵从统一的开发方式
- 警惕”破窗效应”, 一次的妥协, 在不理解的基础上对代码进行类似+1-1的快速修复, 就一定会有下一次
- 重视单元测试, 好的单元测试, 会是代码极佳的说明文档
对事不对人
- 可以不用直接指出队友方案中的错误或不足, 转而以描述问题场景, 询问解决方法来替代. 可能业务场景有特殊性, 并不见得是错误
- 一致对外, 对内多包容. 每个人都会有好的创新想法, 也会萌生愚蠢的馊主意. 要引导团队变得更开放, 禁止组内有挖苦/挤兑的情况存在
- 没有绝对完美的方案, 兼收并蓄, 努力在当前场景下优点最多缺点最少的方案上让大家达成一致.
排除万难, 勇往直前
- 每当发现代码有问题或者不够简洁, 都需要立马进行重构/优化, 不是自己负责的代码, 也应该大胆提出来. 只要方向是正确的, 勇往直前
- 提出观点, 应当具有理论依据, 否则没有说服力
- 遇到缺乏背景知识的抉择者, 要以对方能听懂的方式去沟通. 目的是为了让论点有说服力
学无止境
跟踪变化
- 迭代和增量式学习
- 高频次
- 最好每次只涉及1个点
- 多看好书(技术/非技术均可)
- 机会总是给有准备的人
对团队投资
- 一个学习型的团队才是好团队
- 让团队中的每个成员分享他们擅长的技能, 带动其他成员赶上
- 能提高其他团队成员的人, 应该得到重用
- 坚持分享, 成就感和关注度能够督促每个成员学习
懂得丢弃
- 既有的习惯与思维应该用来帮助理解与解决问题
- 当学习新知识时, 要有开放心态, 不能生搬硬套
刨根问底
- 在找到真正的原因前, 不要停止问为什么
- 要想清楚提问的理由, 问到点子上
保持开发节奏
- 尽量让自己的代码可以在一天结束时, 执行完测试用例然后提交到仓库. 让自己每天都是新的开始
- 保持固定的迭代周期, 在迭代周期内执行明确且合理的开发任务, 保持节奏
交付符合预期的软件
需求负责人决定
- 把影响系统使用或系统行为的问题上报给负责人, 由负责人决定, 只需提供选项
设计只到战略层面
- 重视战略设计, 战术设计留给开发人员
- 好的设计是正确的, 不是精确的
- 设计只需要到调用关系, 可以使用类图或系统交互图来描述
- 开发过程中, 意识到新问题, 不停地调整设计与代码
合理使用技术
- 警惕”简历驱动设计”
- 技术方案的花费不应该高于解决的问题
- 不需要开发容易下载到的东西, 代码写的越少, 维护的工作就越少
- 每一门技术都有优点和缺点, 使用时要清楚利弊, 根据需要选择技术
保持可以发布
- 代码提交前必须自测通过
- 代码提交前必须合并远端最新代码
持续集成
- 尽早集成, 频繁集成, 才能尽早发现问题, 降低风险
自动化部署
- 尽早使用容器, 实现统一的运行环境
不停演示, 不停接收反馈
- 需求总有不确定性, 越早得到反馈, 越早修正错误
- 有缺陷或不稳定的功能, 不要拿来演示
短迭代, 增量发布
- 迭代开发: 在小且重复的周期内, 完成分析/设计/实现/测试和获得反馈
- 注意迭代周期与任务量的匹配
- 相邻迭代中间可以安排时间做总结/维护性工作
敏捷反馈
代码的保护神
- 单元测试, 用单测验证结果, 验证变量
- 可以保留一些只为单测而写的方法
度量真实的进度
- 舍弃计算工作量完成百分比, 应该评估剩余任务的工作量
- 每次都将实际工作量与评估工作量做对比, 不断修正评估方法, 让评估越来越准确
- 用待办事项排列剩余任务和任务优先级
持续集成
- 区分环境进行持续集成, 避免环境不同导致的问题
- 持续集成需要有失败告警机制
倾听用户的声音
- 用户的抱怨背后隐藏着真正的问题
- 用户是最终的使用者, 从用户出发, 理解用户的行为习惯
敏捷编码
代码要清晰地表达意图
- 代码清晰度优先级高于执行效率
- 想要读简洁易懂的代码, 要先做到自己的代码简洁易懂
- 代码改动流程: 读懂代码->确定改动点->修改并测试
用代码沟通
- 保留类/方法的JavaDoc注释, 尽量避免方法体内的注释
- 写简明扼要的注释
- 让代码能够自解释
- 正确命名变量/方法
- 清晰分离逻辑
- 简洁表达逻辑
动态评估取舍
- 没有完美的解决方案, 只有相对最合适的解决方案
- 评估投入产出比, 不为10%的收益付出90%的努力
- 过早的优化是万恶之源
- 要因地制宜地设计方案, 不可生搬硬套
增量式编程
- 编程过程中不停调整, 持续做细小而有用的事
- 番茄工作法
- 测试代码也需要经常调整或重构
保持简单
- 警惕过分设计
- 开发可以工作的, 最简单的解决方案
- 不要过于追求简洁, 防止矫枉过正
高内聚
- 让类的功能尽量集中, 让组件尽量小
方法区分查询和命令
- 将方法分为命令与查询两种类型
- 查询不应该改变对象的可见状态
- 命令改变对象状态, 可以有返回值
里式替换原则
- 里氏替换原则: 子类可以自由替换父类
- 继承的最佳实践之一:代理模式/装饰模式
- 不能进行里式替换, 就采用依赖/聚合的方式
- 通过替换代码类扩展系统
敏捷调试
工作日志
- 每日工作日志汇总每日问题的解决方法, 学到的知识点
- 每周分别汇总知识点和问题集
高效调试
- 如果依赖的第三方没有准备好, 可以先用mock本地调. 同理, 往小可以引申到代码层级调试; 往大可以引申到多服务调用调试
抛出所有异常
- 注意, 代码层级间如果抛出的是检测异常,则需要处理, 不应向上抛, 增加层级耦合. 如果不能处理, 最好的方式是包装成运行时异常或者当前层级所定义异常抛出
- 影响业务流程的地方才抛出异常
- 抛出的异常要有实际意义, 比如抛出一个NullPointerException其实没有意义
异常信息应准确
- 抛异常应该伴随着日志记录, 最好有主键信息方便问题定位
- 异常的错误信息要有实际意义, 能指出问题直接原因, 不能空泛
敏捷协作
定期安排站会
- 每人2分钟左右, 全程10-15分钟
- 小团队可以每周1~2次
- 上班后半小时~一小时内开始站会
- 会议内容
- 昨天的成果
- 今天的工作计划
- 面临的问题
- 如果是大于1天的工作量, 成果和工作计划必须明确
- 根据会议总结进度, 调整任务, 摊开大饼
- 会上不讨论问题细节, 可以会后再召开小规模会议讨论
- 通过会议, 达到问题集思广益, 激励团队成员前进的目的
- 如果有人觉得站会浪费时间, 那是没有形成真正的团队意识
架构师必须写代码
- 新系统的设计者必须亲自参与实现
- 不理解细节, 就不可能做出好的设计
- 战略层次(总的架构)不允许单独设计, 战术层次(具体问题)如果是单独设计, 最好有评审
- 鼓励程序员参与设计
代码集体所有制
- 实行模块轮换制, 定期开发人员负责不同的模块
- 实行模块owner制度, owner对模块负全部责任
- 所有人都可以往不同的模块提交代码, owner负责评审
- 特殊模块可以让专家驻留, 对其开放其他模块代码
- 如果不能实行轮换制, 那一定是高精尖项目
成为指导者
- 费曼学习法
- 通过别人的提问发现不同的角度. 如果不能回答, 就要继续学习增加
- 形式多样, 可以是讨论问题, 可以是博客分享
- 过程是分享自己的知识/经验和体会, 目的是提高自身与队友的能力, 进而提升团队实力
- 讲得多的主题就记录成笔记, 进而可以据此写出博客, 甚至是书
指导者的工作法则
- 在告知答案前, 鼓励/引导大家思考如何解决问题
- 尝试用问题来回答问题
- 如果过了限定时限, 还是没有进展, 直接告知答案, 再给解释
- 如果一个成员拒绝尝试自己寻找答案, 甚至不想听答案的解释. 那他是拒绝进步的, 这类人不适合留在团队
代码管理
- 合并到公共分支的代码, 必须过编译过单测
- 主干分支的代码合并需要给模块owner review
- 差异不意味着不好, 除非能让代码变好, 否则不要批判别人的代码
及时公布进度
- 不同的受众, 关心的进度粒度不同, 要做好区分
- 每日站会评估进度, 一日一次比较好, 紧急的可以一日两次
- 当工作量/问题的原因导致进度受阻或者需要延期, 要及时处理, 方式有如下:
- 及时寻找资源(人/开源工具)解决, 能解决尽量解决
- 不能解决的问题, 抛给上层, 让上层决策