hello world

stay foolish, stay hungry

设计的臭味—软件腐化的气味

设计不是一组和代码分离的UML图, UML图也许描绘了设计的一部分, 但是它不是设计. 软件项目的设计是一个抽象的概念, 和程序的概括形状(shape)、结构、以及每一个模块、类和方法的详细形状和结构有关, 可以使用不同的媒介去描绘它, 但最终体现为源码, 最后, 源码就是设计.

设计的臭味—软件腐化的气味

项目刚开始甚至首次发布时, 系统设计是清晰的, 随着时间流失, 丑陋的设计和弊病在代码中积累, 使其越来越难以维护, 最后仅仅是最简单的更改也要花费巨大的代价, 以至于开发人员和一线管理人员强烈要求重新设计. 这样的设计很少会成功, 老系统不断发展和变化, 新的设计必须跟上这些变化, 所以新系统第一次发布就积累了很多瑕疵和弊病.

当软件出现下面任何一种坏味道时, 就表明软件正在腐化.

1. 僵化性

很难对软件进行改动, 即便是简单的改动. 如果单一的改动会导致有依赖关系的模块中的连锁改动, 那么这样的设计就是僵化的, 要改动的模块越多, 设计就越僵化

2. 脆弱性

对系统进行改动时, 会导致系统中和改动地方在概念上无关的许多地方出现问题, 要修正这些问题又会引入更多的问题. 随着脆弱性的增加, 改动会越容易引出意想不到的问题. 开发人员知道需要对它们进行重新设计, 但是越修正, 就变得越糟.

3. 牢固性

设计中包含了对其他系统有用的部分, 但是很难解开系统间的纠结, 要把这部分从系统中分离出来需要的努力和风险都是巨大的.

4. 粘滞性

粘滞性有两种表现: 软件的粘滞性和环境的粘滞性

进行系统改动时, 开发人员会有多种改动方式, 其中一些会保持设计, 另外一些会破坏设计. 当那些可以保持系统设计的方法比那些破坏系统设计的方法更难应用时, 就表明系统具有高的粘滞性. 做错误的事情很容易, 而做正确的事情很难. 我们系统在软件设计中可以容易的进行那些保持设计的改动.

当开发环境迟钝、低效时, 就会产生环境粘滞性. 例如, 如果编译花费时间很长, 那么开发人员就会被引诱去做不会导致大规模重新编译的改动, 即使那些改动不再保持设计; 如果源码控制系统check in很困难, 那么开发人员就会被引诱去做那些需要尽可能少check in的改动, 而不管改动是否会保持设计.

无论项目具有哪种粘滞性, 都很难保持项目中的软件设计. 我们希望创建易于保持设计的系统和项目环境.

5. 不必要的复杂性

如果设计中包含当前没用的组成部分, 就含有了不必要的复杂性. 开发人员常常预测需求的变化, 并在软件中放置了处理那些潜在变化的代码. 起初, 看起来像是一件好事, 但过多的可能性准备导致设计中包含绝不会用到的结构, 从而变得混乱. 一些准备可能会带来回报, 但更多的不会有作用. 设计背负这这些不会用到的部分, 是软件变的复杂, 并难以理解

6. 不必要的重复性

复制和粘贴操作常常会导致重复的代码片段, 当同样的代码以稍微不同的形式重复出现时, 就表示开发人员忽略了抽象. 发现所有的重复并通过适当的抽象去消除重复, 会使系统的更加易于理解和维护. 当系统有重复的代码时, 对系统进行改动会变得困难, 在一个重复的代码体中发现的错误总是需要在每个重复体中一一修正, 由于每个重复体之间都有细微的区别, 所以修正的方式也不尽相同.

7. 晦涩性

晦涩性是指模块难以理解。代码可以是清晰、富有表现力的,也可以是晦涩的费解的,代码随着时间往往会变得越来越晦涩,为了是代码晦涩性保持最低,就需要持续的保持代码清晰并富有表现力。开发者最初编写模块时,可能会很熟悉代码,随着时间推移,熟悉减退,再看这个模块,同样会觉得代码很糟糕,为了避免这种情况,开发者需要站在代码阅读者的角度,对他们代码进行重构,这样代码阅读者就可以理解代码。

敏捷团队不允许软件腐化

在非敏捷环境中,需求没有按照初始设计和计划的方式进行变化,从而导致了设计的退化。通常改动痘痕急迫,并且进行改动的开发人员对于原始设计思路可能并不熟悉,因而虽然改动可以工作,但是却以某种方式违反了原始的设计。随着改动的不断进行,这些违反设计的行为不断积累,设计开始出现臭味。

敏捷团队依靠变化来获取活力,团队几乎不进行预先设计,因此不需要一个成熟的设计。他们更愿意保持系统尽可能干净、简单,并使用许多单元测试和验收测试,保持了设计的灵活性和可理解性。