一、计划
1、当你能够度量你所说的,并且能够用数字去表达它时,就表示你了解了它;若你不能度量它,不能用数字去表达它,
那么说明你的知识就是匮乏的,不能令人满意的。
2、过大或者过小的素材都是难以估算的。开发人员往往会低估那些大的素材而高估那些小的素材。任何过大的素材都
应该被分解成小一点的部分,任何过小素材都应该和其他小的素材合并。
3、迭代计划,项目的周期过程,如下图:
二、 重构
1、软件设计的腐化
当软件出现下面任何一种气味时,就表明软件正在腐化。
(1)僵化性(Rigidity)
僵化性是指难以对软件进行改动,即使是简单的改动。如果单一的改动会导致有依赖关系的模块中的连锁改动,
那么设计就是僵化的。必须要改动的模块越多,设计就越僵化。
(2)脆弱性(Fragility)
脆弱性是指,在进行一个改动时,程序的许多地方就可能出现问题。常常是,出现新问题的地方与改动的地方并没有概念
上的关联。要修正这些问题就又会引出新的问题,从而使软件开发团队就像一只不停追逐自己尾巴的狗一样。
(3)牢固性(Immobility)
牢固性指很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。设计中包含了对其他系统有用的部分,
但是要把这些部分从系统中分离出来需要的努力和风险是巨大的。
(4)粘滞性(Viscosity)
做正确的事情比做错误的事情要困难。当面临一个改动时,开发人员常常会发现会有多种改动的方法。其中,
一些会保持设计;而另外一些会破坏设计(也就是生硬的手法)。当那些可以保持系统设计 的方法比那些
生硬手法更难应用时,就表明设计具有高的粘滞性。
(5)不必要的复杂性(Needless Complexity)
设计中包含有不具任何直接好处的基础结构。如果设计中包含当前没有用的组成部分,它就含有不必要的复杂性。
当开发人员预测需求的变化,并在软件中放置了处理潜在变化的代码时,常常会出现这种情况。
(6)不必要的重复(Needless Repetition)
设计中包含有重复的结构,而该重复的结构本可以使用单一的抽象进行统一。复制(Copy)和粘贴(paste)也许是有用的文本编辑(text-editing)操作,但是它们却是灾难性的代码编辑(code-editing)操作。当系统中有重复代码时,
对系统进行改动会变得困难。在一个重复的代码体中发现的错误必须要在每个重复体中一一修正。不过,由于每个重复体
之间都有细微的差别,所以修正的方式也不总是相同的。
(7)晦涩性(Opacity)
很难阅读、理解,没有很好地表现出意图。晦涩性是指,代码模块难以理解,当开发人员最初编写一个模块时,
代码对于他们来说看起来也许是清晰的。这是由于他们使自己专注于代码的编写,并且他们对 于代码非常熟识。
在熟识减退以后,他们或许会回过头来再去看那个模块,并想知道他们为什么会编写出如此糟糕的代码。
为了防止这种情况发生,开发人员必须要 站在代码阅读者的位置,共同努力对他们的代码进行重构。
2、每一个软件模块都具有三项职责
第一个职责是它运行起来所完成的功能。
第二个职责是它要应对变化,几乎所有的模块在生命周期中都要变化,开发者有责任保证这种改变应该尽可能地简单。
第三个职责是要和阅读它的人进行沟通,对该模块不熟悉的开发人员应该能够比较容易地阅读并理解它。
3、重构就好比用餐后对厨房的清理工作
第一次你没有清理它,你用餐是会快一点。但是由于没有对盘碟和用餐环境进行清洁,第二次做准备工作的时间就
要更长一些。这回再一次促使你放弃清洁工作。的确,如果跳过清洁工作,你今天总是能够很快用完餐,但是脏乱在
一天天的积累。最终,你的花费大量的时间去寻找合适的烹饪器具,凿去盘碟上已经干硬的食物残余,并把它们洗擦
干净以使他们适合于烹饪。饭是天天要吃的。忽略掉清洁工作并不能真正加快做饭速度。
4、重构的目的,是为了每天清洁你的代码
我们不想让脏乱积累,我们不想“凿去并洗擦掉”随着时间积累“干硬的”比特,我们想通过最小的努力就能够对我们的
系统进行扩展和修改。要想具有这种能力,最重要的就是保持代码的清洁。
三、测试
1、编写单元测试是一种验证行为,更是一种设计行为,同样,它更是一种编写文档的行为。编写单元测试避免了相当数量的反馈循环,尤其是功能验证方面的反馈循环。
2、测试驱动开发,测试促使模块之间隔离,在编写产品代码之前,先编写测试常常会暴露程序中应该被解藕合的区域。
3、验收测试,作为验证工具来说,单元测试是必要的,但是不够充分。单元测试用来验证系统的小的组成单元应该按照
所期望的方式工作,但是它们没有验证系统作为一个整体时工作的正确性。单元测试是用来验证系统中个别机制的
白盒测试,验收测试是用来验证系统满足客户需求的黑盒测试。