目录
[7.1: 软件出了什么错](#7.1: 软件出了什么错)
[7.2: 设计的臭味--腐化软件的气味](#7.2: 设计的臭味--腐化软件的气味)
[7.2.1: 什么激化了软件的腐化](#7.2.1: 什么激化了软件的腐化)
[7.2.2: 敏捷团体不允许软件腐化](#7.2.2: 敏捷团体不允许软件腐化)
[7.3: "copy"程序](#7.3: “copy”程序)
[1: 初始设计](#1: 初始设计)
[2: 需求在变化](#2: 需求在变化)
[3: 得寸进尺](#3: 得寸进尺)
[4: 期望变化](#4: 期望变化)
[7.3.1: "copy"程序的敏捷设计](#7.3.1: “copy”程序的敏捷设计)
[7.3.2: 敏捷开发人员如何知道要做什么](#7.3.2: 敏捷开发人员如何知道要做什么)
[7.4: 保持尽可能好的设计](#7.4: 保持尽可能好的设计)
[7.5: 结论](#7.5: 结论)
1:PDF上传链接
"在按照我的理解方式审查了软件开发的生命周期后,我得出一个结论:实际上满足工程设计标准的唯一软件文档,就是源代码清单。"
--Jack Reeves
7.1: 软件出了什么错
项目开始的时候,软件设计就会存在脑中,有了初步的设计与规划。
接着,在后续的项目进行中,使得它越来越难维护,最后即使进行简单的更改,也要需要花费巨大的努力,以至于管理人员强烈要求进行重新设计。
这样的重新设计很少会成功,虽然设计人员开始时出于好意,但是他们发现自己正照一个移动的目标射击。老系统不断地发展,变化而新的设计必现跟上这些变化。这样甚至在第一次发布前,新的设计中就累积了很多的瑕疵和弊病。
7.2: 设计的臭味--腐化软件的气味
当软件出现下面任何一种气味时,就表明软件正在腐化。
僵化性:很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其他改动。
脆弱性:对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。
牢固性:很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。
粘滞性:做正确的事比做错误的事情要困难。
不必要的复杂性:设计中包含有不具任何直接好处的基础结构。
不必要的重复:设计中包含有重复的结构,而该重复的结构体可以使用单一的抽象进行统一。
晦涩性:很难阅读、理解。没有很好地表现意图。
7.2.1: 什么激化了软件的腐化
在非敏捷环境中,由于需求没有按照初始设计遇见的方式进行变化,从而导致设计的退化。通常的修改都是急迫的,在还不是很了解开发者最开的设计思路进行修改,修改的时候会违反原始的设计,随着改动的不断进行,这些违反渐渐地积累,设计开始出现臭味。
我们必须要设法找到一种方法,使得设得对于这种变化具有弹性,并且应用一些实践来防止设计腐化。
7.2.2: 敏捷团体不允许软件腐化
敏捷团队依靠变化来获取活力。团队利用灵活性,持续的改进设计,以便于每次迭代结束所生成的系统都具有最适合于那次迭代中的需求的设计。
7.3: "copy"程序
观看一个设计的腐化过程会有助于阐述上述的观点。比如老板要求写一个从键盘输入字符并输出到打印机的程序。经过考虑后,判断代码不会超过10行,时间不会超过1个小时。但是考虑到交叉会议、质量教育会议,日常小组会议以及当前正在处理的难题,要完成这个程序要花费大约一个星期的时间---如果你下班后仍坚持工作的话。不过你总是把估值乘以3
"需要3周时间",你告诉老板,老板哼着走开了,把任务留给你了。
1: 初始设计
图7.3.1.1
2: 需求在变化
几个月后,老板说希望copy程序能从纸带读入机中读入信息。你咬咬牙翻着白眼,你想知道为何人民总是改变需求。你的程序不是为了纸带读入机设计的。
开始修改方案,在copy的函数中添加一个boolean变量,如果变量为true就从纸带读入机中读取信息,否则就像之前一个从键盘从读取信息。槽糕的是很多人程序都在使用copy程序,你不能改变copy程序的接口。改变接口会导致长时间的重新编译和重新测试,但但是系统测试工程师就会痛恨你更别提配置控住组的7个家伙了。并且过程控制部门会专门的一天时间来对所调用了copy的模块进行各种各样的代码评审。
不能改变接口使用C语言的操作符;
图7.3.2.1
3: 得寸进尺
几周后,老板又提了新的需求,客户希望copy程序可以输出到纸带穿孔机上。
你告诉老板不断地变更会对设计的优雅性造成极度的负面影响,你警告的说这样继续变更,那么年底前,软件会变得难以维护。老板心照不宣的点点头,然后说就是要改。
图7.3.3.1
4: 期望变化
请读着自行判断上述说的有多少是夸大之词,上面主要说明在变化面前,程序的设计退化的速度是多么的快。copy程序的原始设计师简单并且优雅的。但是经过两次变更它就会出现僵化性、脆弱性、牢固性、不必要的复杂性、不必要的重复及晦涩性的病症。这种趋向继续下去,程序将会变得混乱不堪。
我们可以坐下来去指责变化,可以抱怨程序对于最初的要求是设计良好的,是因为后来对要求的改变导致了设计的退化。然而就是忽略了这个变化的重要原因:需求总是在变化。
记住,在大多数项目中最不稳定的东西就是需求。需求处于在一个持续变动的状态中。这个是我们作为开发人员必须得接受的事实!我们生存在一个需求不断变化的实际中,我们的工作是要保证我们的软件能够经受得住那些变化。如果我们软件的设计由于需求的变化而退化,那么我们就不是敏捷的。
7.3.1: "copy"程序的敏捷设计
图7.3.1.1
团队遵循了开发-封闭原则(简称OPC)我们将在第九章学习它。这个原则指导我们设计出无需修改即可扩展的模块,这个正式团队已经完成的,无需修改copy程序就可以使用老板要求的每种新的输入设备。
有人认为他们仅仅完成了一半的工作,他们在使自己免于不同的输入设备带来的麻烦时,本可以也使自己免于不同的输出设备带来的麻烦。然而,团队实在不知道输出设备是否会变化,现在就添加而外的保护没有任务实现意义。很明显,如果需要这种保护时,以后可以非常容易的添加。因此,实在没有现在就添加的理由。
7.3.2: 敏捷开发人员如何知道要做什么
在上面的例子中,敏捷开发人员构建了一个抽象类,来使他们免于输入设备的变化带来的麻烦,他们如何知道要那样做呢?这和面对对象设计的基本原则中的一个有关。
程序在设计的时候,我们知道copy模块依赖键盘和打印机的底层细节。因而当底层细节变化的时候,上层的应用模块会受到影响。
一旦暴露出了这个不灵活性,敏捷开发人员应该知道从copy模块到输入设备的依赖关系需要被倒置,这样copy模块就不再依赖输入设备。于是他们就应用STRATEGY模式创建了想要的倒置关系。
因此,简而言之,敏捷开发人员知道要做什么,是因为:
(1)遵循敏捷实践去发现问题;
(2)应用设计原则去诊断问题;
(3)应用适当的设计模式去解决问题;
7.4: 保持尽可能好的设计
敏捷开发人员致力于保持设计的干净。每时每刻都在遵守这个原则,不会让腐化出现。
设计必须要保持干净、简单,并且由于源代码是设计最重要的表示,所有它同样保存干净。职业特性要求我们,作为软件开发人员,不能忍受代码腐化。
7.5: 结论
那么,什么是敏捷设计呢?敏捷设计就是一个过程,不是一个事件。它是一个持续的应用原则、模式以及实践来改进软件的结构和可读性的过程。它致力于保持系统设计在任何时间都尽可能得到简单、干净以及富有表现力。