date: 2017-10-13 17:59:11
title: 「修改软件的艺术」 读书笔记
百度脑图 - 修改软件的艺术: http://naotu.baidu.com/file/3300eebf1014c10fd4d1a96ad6cf65ac?token=ff8bec2d896c0c61
图灵社区 - 修改软件的艺术: http://www.ituring.com.cn/book/1749
修改软件的艺术:构建易维护代码的9条最佳实践
将理解具象化
优秀软件是具象化的理解
敏捷 vs 瀑布
遗产 vs 遗留
奏效: 受雇的开发者必须意识到,仅仅言听计从是不够的,他们有义务让交付的软件持续产生价值
开发者有三种状态: 已完成 / 未开始 / 快完事了
评估未知
一个充满外行人的产业
导致低成功率的核心因素: (1) 代码变更 (2) bug修复 (3) 复杂度控制
顺流直下: 瀑布模型是从制造业和建筑行业借鉴而来
需求分析 设计 实现 集成 测试 安装 维护
为什么瀑布模型不管用
虚拟世界并不奏效
让我们建造出来的东西难以改变
开发和测试分离
出错误并非我的工作;创造错误才是
当“流程”变成“体力劳动”
流程无法支配创造力
敏捷: 希望软件能拥有即刻适应需求变化的能力
敏捷 Scrum 极限编程(Extreme Programming,XP)
敏捷流程核心: 通过持续不断地及早交付有价值的软件使客户满意
小即是好
并不是急于求成而是循序渐进
艺术与技能的平衡: 开发软件需要许多的技能和能力,也就是技艺,但是无论学到多少技能都没办法解决所有问题。
追求技术卓越
遵循实践(消毒某一特殊器械的行为)和遵循原则(对所有器械进行消毒的理由)的差别
如果想降低软件持有者的开销,我们必须关注软件的构建过程。
守、破、离
单一职责原则
开闭原则:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
原则帮助我们把某件事情通用化,有助于梳理知识体系。
实践必须: 在多数情况下产生价值; 容易学习且容易传授; 简单易行——简单到无需思考。
原则指导实践
压力对于构建更好的产品毫无帮助
要有一个产品负责人
用户故事: 做什么、为什么做、给谁做
为验收测试设立明确标准 / 自动化验收标准
产品负责人的7个策略:
- 成为特定领域专家
- 在开发过程中探索
- 帮助开发者理解为什么和为了谁
- 描述你想要什么,而不是怎么做
- 及时回答问题
- 消除依赖
- 支持重构
编写出更好用户故事的7个策略:
- 它当作一个占位符
- 关注“什么”
- 把“谁”人格化
- 知道为什么会有一个功能需求
- 开始时简单,日后再加强
- 心系边界情况
- 使用验收标准
小批次构建
工作单元应该可以展现出可度量的结果
大小适中,而不仅仅是“小”而已
做出调整
人类无法度量
关键路径的重要性:“怀孕生子需要九个月,无论有多少妇女参与其中。”
范围、时间、资源(scope,time,resource,STR)
控制发布节奏
越小越好有四个基本原因:更容易理解;更容易预估;更容易实现;更容易测试。
分而治之
之所以会很繁重,是因为两个原因:要么是复杂型的,要么是复合型的。
探索未知事物的时候需要做两件事: 未知变为已知,未知进行封装
更短的反馈回路
提高构建速度
对反馈做出响应
建立待办列表
讨论待办列表的顺序而非优先级
把用户故事拆分为任务
跳出时间盒子思考
Scrum并不是一个“全有或全无”的提议。
要么有风险,要么没有风险。当你有风险的时候,则充满未知。未知即是风险。
范围控制
降低风险的唯一方式是把用户故事进行到底,这意味着我们需要对什么是“完成”有明确的定义。
迭代”真正的目的是让团队消除以发布为单位的构建习惯。
看板。
度量软件开发的7个策略:
- 度量产生价值的时间
- 度量编码时间
- 度量缺陷密度
- 度量发现缺陷的时间
- 度量功能的客户价值
- 度量未交付功能的损失
- 度量反馈回路的效率
分割用户故事的7个策略:
- 把复合的故事拆分为组件
- 复杂的故事分割为已知的和未知的
- 对未知持续迭代直至完全理解
- 根据验收标准分割故事
- 最小化依赖
- 保持目的单一
- 保持故事可测试性
持续集成
处理痛苦的方式有两种:避免痛苦,或者学着承受。
建立项目的心跳
实践持续部署
自动化构建
尽早集成,频繁集成
告诉你的开发者每天至少集成一次。
测试驱动开发(Test Driven Development,TDD)
软件应该从第一天起就具备发布条件
构建敏捷设施的7个策略:
- 用版本库管理一切
- 一次点击全部构建
- 持续集成
- 为任务定义验收标准
- 编写可测试的代码
- 保证必要的测试覆盖率
- 即时修复失败的构建
消除风险的7个策略:
- 持续集成
- 避免分支
- 自动化测试上下功夫
- 识别风险区域
- 征服未知
- 构建可以体现价值的最小部分
- 频繁验证
协作
极限编程
开放性的思想
沟通与协作
结对编程
伙伴编程
穿刺,群战,围攻
在时间盒子中对未知进行调研
定期代码审查和回顾会议
加强学习和知识分享
诲人不倦且不耻下问
结对编程的7个策略:
- 尝试一下,你会喜欢的
- 驾驶员和领航员都要参与其中
- 频繁交换角色
- 充实工作一天
- 尝试各种配置
- 让团队决定细节
- 跟踪进度
高效回顾会议的7个策略:
- 找寻小的改进
- 责怪流程而不是人
- 5个为什么
- 解决根源问题
- 倾听每个人的声音
- 给予支持
- 度量进度
编写整洁的代码
CLEAN: Cohesive 内聚 / Loosely Coupled 松散耦合 / Encapsulated 封装 / Assertive 自主 / Nonredundant 没有冗余
高质量的代码是内聚的
单一的职责。
高质量的代码是封装良好的
由外而内编程 vs 由内而外编程
只暴露解决问题所必需的
高质量的代码是自主的
高质量的代码是没有冗余的
DRY Don't Repeat Yourself
提高代码质量的7个策略:
- 明确代码质量的定义
- 对基本的实践达成一致
- 放弃完美主义
- 理解取舍
- 用“什么”来隐藏“怎么”
- 良好的命名
- 保持代码的可测试性
编写可维护代码的7个策略:
- 确立代码的集体所有权
- 积极重构
- 坚持结对编程
- 频繁的代码审查
- 学习其他开发者的风格
- 不断学习软件开发
- 读代码,写代码,练习编码
测试先行
测试是标准,测试定义行为。
验收测试 = 客户测试
单元测试 = 开发者测试
其他测试 = 质量保证测试
质量保证(Quality Assurance,QA):
- “组件测试”体现各个组成单元之间的配合情况。
- “功能测试”体现所有组成单元在一起完成整个端到端的行为。
- “场景测试”体现用户和系统的交互行为。
- “性能测试”验证这些情形:“这个系统能承受很大的负载吗?我们进行过独立测试,但是如果百万级用户进行并发请求会怎么样?”
- “安全测试”验证代码的脆弱程度。
以行为作为单元
TDD可以提供迅速的反馈
TDD可以为重构提供支持
编写可测试的代码
进行优质验收测试的7个策略:
- 明确构建目标所产出的价值
- 理解为谁而做以及他们为什么需要
- 将验收测试自动化
- 定义边界用例、异常、次要路径
- 用实例来充实细节和展示不一致
- 用验收标准来拆分行为
- 保持每个测试的唯一性
进行优秀单元测试的7个策略:
- 从调用者的角度出发
- 用测试定义行为
- 仅仅编写能体现区别的测试
- 仅仅编写可以让测试通过的代码
- 用测试来构建行为
- 对代码进行重构
- 对测试进行重构
用测试描述行为
测试就是标准
测试需要完整
bug是缺失的测试
工作流测试用所谓的模拟对象(mock)进行测试
使用测试作为标准的7个策略:
- 将测试仪表化
- 使用见名知意helper方法
- 突出重点
- 测试行为,而不是实现
- 用模拟对象测试工作流
- 避免过度描述
- 利用真实的例子
修复bug的7个策略:
- 一开始就避免写出bug
- 尽早发现bug
- 通过设计让bug更容易找到
- 问对问题
- 把bug当作失败的测试
- 利用发现的缺陷修正流程
- 从错误中学习
最后实现设计
可变性的阻碍
缺乏封装
滥用继承
僵化的实现
内联代码
依赖
可持续性开发
删除死代码
保持名称更新
集中决策
抽象
对类进行组织
编码与清理
软件被阅读的次数比编写次数多
意图导向编程
降低圈复杂度
演化式设计
进行演化式设计的7个策略:
- 理解面向对象设计
- 理解设计模式
- 理解测试驱动开发
- 理解重构
- 关注代码质量
- 要冷酷无情
- 培养优秀的开发习惯
清理代码的7个策略:
- 让代码自我表达
- 为添加测试创造间隙
- 让方法更内聚
- 让类更内聚
- 集中决策
- 引入多态
- 封装构建过程
重构遗留代码
重构能降低以下四个方面的成本:
- 日后对代码的理解
- 添加单元测试
- 容纳新功能
- 日后的重构
技术债和财务债一样:利息会把你拖垮
通过重构糟糕代码来培养良好习惯
推迟那些不可避免的
图钉测试
依赖注入
系统扼杀
抽象分支
以支持修改为目的重构
以开闭原则为目的重构
以提高可修改性为目的重构
第二次做好
助你正确重构代码的7个策略:
- 从已有系统中学习
- 循序渐进
- 遗留代码中添加测试
- 始终进行重构
- 有更好的理解后对一个实现进行重新设计
- 继续其他工作前进行清理
- 重构以避免误入歧途
决定何时进行重构的7个策略:
- 关键代码维护不善的时候
- 当唯一理解代码的人没空的时候
- 有信息可以揭示更好的设计的时候
- 修复bug的时候
- 需要添加新功能的时候
- 当需要为遗留代码写文档的时候
- 当重构比重写容易的时候
在不需要的事情上花钱
我们是软件开发者,利用现有工具尽我们所能开发最好的软件