本文主要内容来自 SpriCoder的博客,更换了更清晰的图片并对原文的疏漏做了补充和修正。
部分名词解释
- 测试驱动开发:测试驱动开发要求程序员在编写一段代码之前,优先完成该段代码的测试代码。并在编程中重复执行测试代码,以验证程序的正确性。
- 结对编程:两个程序员挨着坐在一起,共同协作进行软件构造活动。
什么是软件构造?
SWEBOK2004
- 通过编码、验证、单元测试、集成测试和调试等工作的集合,生产可工作的、有意义的软件的详细创建过程。
McConnell2004
- 软件构造除了核心的编程任务之外,还涉及详细设计(数据结构与算法设计)、单元测试、集成与集成测试、以及其他活动。
Reeves 1992:软件构造是设计的延续
- 设计是规划软件构造方法的过程,实现是依据规划的软件构造方案建造真正产品的过程
- 源程序是软件构建方案的最后一个规划,不是产品本身,真正的产品是运行于计算机上的由二进制代码组成的可执行程序。
- 源程序的生产过程-编程,属于设计活动,编译器完成的编译和链接才是依据规划建造软件产品的实现活动。
- 编程不是一个简单的活动,核心是编码的设计。
软件构造活动重要
包含详细设计、编程、测试、调试、代码评审、集成与构建、构造与管理。
详细设计
- 有些项目会将主要的详细设计工作分配在软件构造阶段完成。
- 无论是哪种项目,在软件构造阶段都不可避免的会设计到详细设计的调整工作。因为编程语言是软件设计的一个重要约束,随着编程工作的进行和约束,人们可能会发现与预想不一致的情况和更多的约束,这个时候就需要在软件构造阶段修改详细设计方案。
- 软件构造阶段详细设计使用的方法与技术与软件设计阶段是一样的,只是应用在更小的规模上。
- 详细设计已经包含实际的代码实现了,不同编程语言的代码行数不同。
编程
程序代码的典型质量
- 易读性:让软件更容易开发,尤其是易于调试;可以使的程序更加容易维护,减少理解代码的难度和成本:降低交流的成本,自己写完之后要修正代码使其易读。
- 易维护性:
- 要求代码易读、易修改,增量开发。
- 关键业务流程应该是易于扩展的。
- 可靠性:执行正确,并能妥善处理故障。
- 性能:高性能,包括时间性能和空间性能,需要设计数据结构和算法设计。
- 快排在实际上应用的更多。
- 如果利用多核的操作。
- 安全性:不留系统漏洞,不出现重要信息的泄露(内存数据区泄露),别的程序可以嗅探到。
- 上面的五个要求,是有顺序的,做好前面才可以去做下面的。
编程的主要技术
- 什么才是好的代码?
- for 循环带来运行代价(谨慎使用控制结构):串行代码无法并行
- Java 的异常处理:try...catch 的使用
- 代码级的安全泄露:C 和 C++中会出现
- 进程线程和数据库锁:互斥机制会带来性能消耗
- 代码文档:进行一些 DOC 和注释
测试
- 保证写的程序是正确的
- 写完一次就进行一次单元测试
- 写的时候就要进行单元测试进行检测
- 集成测试是在单元测试之后才进行的操作。
调试
- 测试发现了问题之后我们要进行调试,通过重现和调试来完成。
重现问题的方法
- 控制输入:缺陷和控制相关等
- 控制环境:和具体的机器、操作系统、数据库管理系统等,关机重启,内存问题减少。(和队友看看)
寻找和定位缺陷的方法
- 路径 debug,检查刚刚写了的部分的代码
常见错误
- Java 对象如果用不到了就重置为 NULL,然后把对象交给 GC 处理
- 降低控制的复杂程度
- 多线程的错误(同步的问题)
- 多线程的定时问题
- 存储错误(磁盘已经满了)
- 字符集编码问题
- 版本缺陷,对以前不兼容。
修复缺陷的注意点
代码评审
- 重新回到软件构造的过程中去
- 让别人发现你的问题,更多使用轻量级的代码评审
实践经验
CheckList
课本 287 页
集成与构建
构造管理
- 独狼和配置管理的详细描述见课本 288 页
实践方法
重构、测试驱动开发和结对编程
重构
- 保留业务功能,避免出现问题
代码的坏味道
- 太长的方法:一个方法里面有太多的行为。
- 太大的类:一个类不是单一职责的
- 上图中(课本 17-3):name 和 point 不要分开
- 使用 PO 来传递参数,而不是通过过多的参数。
注意事项
- 详见课本 290 页。
- 重构是基于已有代码的设计改进,不是开发新代码的方法。
- 重构要防止副作用。
- 重构的重点是改进详细设计结构。
测试驱动开发
测试驱动开发的过程
- 常见的过程
测试启动开发示例
- 详见课本 292 页
结对编程概念
- 两位程序员并排工作,在相同的设计,算法,代码或测试上进行协作
- 一个程序员(驱动程序)可以控制键盘/鼠标并主动执行程序
- 另一个程序员(观察员)不断观察驾驶员的工作,以发现战术上的(语法上的,拼写的等)缺陷,并从战略上考虑工作的方向
- 根据需要,两位程序员可以集思广益解决任何难题
- 两位程序员定期切换角色,他们平等地合作开发软件
为什么结对编程有效?
- 双压力:彼此保持专注并专注于任务
- 配对思考:为任务带来不同的先前经验
- 配对中继:每个人依次为自己的知识和能力做出最大贡献,然后坐下来思考,而他们的伴侣继续奋斗
- 配对审查
- 持续的设计和代码审查
- 极高的缺陷去除效率
- 消除程序员对评论的厌恶
- 在所有(单独)程序员中,有 80% 都不定期或根本不这样做
- 预防缺陷总是比消除缺陷更有效
- 配对调试:成对谈论问题可能会导致解决方案变得显而易见
- 配对学习:持续审核->向合作伙伴学习技术,语言知识,领域等。
工作区域层
配对选择
- 简化员工培训和过渡
- 知识管理/降低产品风险
- 加强团队建设
有建设性的想法
- 十年的软件建设进展
- 现代软件建设的十个实践
- 1990 年代和 2000 年代最糟糕的建筑思想
十年的软件建设进展
设计已提高到一个水平
- 编程通过创建更大的代码聚合而变得先进
- 语句
- 过程
- 类
- 包
- OO 的真正意义可能是更大的聚合
每日构建和冒烟测试
- 将增量集成制度化
- 最小化以前很常见的严重集成问题
- 还有很多其他好处
- 冒烟测试:将比较重要的部分进行测试,大规模的如果每次都测试问题太大
标准库
- 优秀的程序员一直使用库
- 现在提供了语言(Java,C ++ 、. NET)
Visual Basic
- 视觉编程创新
- 第一个广泛使用 COTS 组件的开发环境
- 唯一可以学习 Ada 语法课程的语言(case 语句,control 语句等)
- 高度集成的环境
- 集成大量的商业组件。
开源软件
- 在开发过程中对程序员的极大帮助
- 减少提供代码的障碍
- 从可用代码中学习的机会
- 提高了读取代码的能力
- 好的程序员“社区”
- 开源不等于免费,鲲鹏社区,Github 上 Star 比较高的项目
网络,用于研究
- FAQs
- 讨论小组
- 一般的可搜索性
增量开发的广泛应用
- 概念在 1990 年代众所周知
- 实践在 2000 年代已确立
测试优先开发
- 缩短缺陷检测时间
- 增加个人纪律
- 补充日常构建和烟雾测试
重构为学科
- 提供进行变更的纪律
- 不如整体设计策略
- 增量主义的好例子
更快的计算机
- 优化的意义
- 对编程语言的影响
- 对发展的影响
现代软件建设的十个现实
-1-“构造”是正当的话题
- 软件“构造” -现在看起来像这样
-2-个人差异很大
- 变化在哪里存在?
- 研究人员发现以下方面的变化范围是 10 倍至 28 倍:
- 编码速度
- 调试速度
- 发现缺陷的速度
- 发现缺陷的百分比
- 发现缺陷的百分比...
- 设计品质
- 设计生成的代码量
-3-个人纪律事项
- 为什么个人纪律很重要
- 在预测未来时要现实
- 纪律很重要的领域
- 重构
- 原型制作
- 优化
- 最小复杂度的设计
- 一般管理复杂性
- 端点—纪律和勇气
- 汉弗莱(PSP)
- 贝克谈极限编程
-4-专注于简单比专注于复杂性更好
- 专注于读取时间的方便,而不是写入时间的方便
- 让别人更加任意的理解
-5-缺陷成本增长依然有效
- 指数增长的修复代价
-6-设计的重要性
- “无设计” —“所有设计”连续体上有很多有效的观点
- 要点:极端情况通常没有生产力
- 全部预先设计与没有预先设计
- 完全计划与完全即兴(迭代/增量)
- 纯迭代与直序列
- 所有结构与所有创意
- 记录一切,什么都不记录
-7-技术浪潮影响施工实践
- 技术浪潮对施工的影响
- “技术浪潮”的定义
- 初潮特征
- 成熟波特征
- 后波特性
- 施工受技术的影响-比我想象的要多(哦!)
- 可以根据一般原则解决技术
- “技术浪潮”的定义
-8 增量方法效果最佳
- 增量主义观点
- 纯瀑布模型完全不是增量模型或迭代模型,这就是为什么它不能很好地工作的原因
- 螺旋发展具有高度的增量性和迭代性,这就是其运作良好的部分原因
- 所有项目在某个时候都会经历迭代
- 想一想在项目中何时何地获得增量主义—便宜还是昂贵?
-9-工具箱的隐喻继续发亮
- 工具箱隐喻
- 什么才好敏捷? XP? Scrum? CMM?
- 工具箱说明没有一项适合每一项工作的工具
- 不同的行业部门将具有不同的工具,甚至会有不同的工具箱
- 软件工程工具箱中有什么?
- 最佳实践
- 生命周期模型
- 模板,清单,模式,示例
- 软件工具
-10-软件的基本张力
- 多年来,软件的主要矛盾一直没有改变:
- 刚性计划与即兴创作
- 规划与算命
- 创意与结构
- 纪律与灵活性
- 定量与定性
- 工艺与产品
- 优化与满意
- 平衡摇杆,但基本张力是恒定的