中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 软件工程 > 综合文章
【转载】Keeping Software Soft (Martin Fowler)
作者:未知 时间:2005-09-13 19:43 出处:ChinaUnix.net 责编:chinaitpower
              摘要:【转载】Keeping Software Soft (Martin Fowler)

本文的一些观点可能会让我们很惊奇,但这些确实是崇尚 极限编程 的开发人员所想的和所做的事情。
一种设计理念的变革。

英文原文:
http://martinfowler.com/distributedComputing/soft.pdf

中文翻译:
http://www.dotspace.twmail.net/softwaredevelopment/Keeping%20Software%20Soft(S).htm


Keeping Software Soft
Martin Fowler

翻译:刘焱 
2002年7月4日星期四

还记得你第一次写程序吗?我可记得:我敲入一些语句(用一些有点笨的语言写的),做一点 debug,我的机器就会给我回应。那时侯,可以很容易地让计算机做点事情,而且改改程序,让计算机做别的事情也很容易,那不过就是稍微改一改程序,做一点 debugging 而已。别忘了,总起来说软件就是要软。

当然,软件的绝对可变性是一种幻想。许多时候,一个软件开发者和一个正常人的区别,就在于:软件开发者知道改变软件有多难。其实,真正难的不是改变软件有多难,而是在改变的同时又不让它崩溃。

这个问题做软件的人也很早就意识到了,这也就是为什么临时设计(ad hoc design)——当程序写到这里了才去设计——不适合于大型系统的原因。

为了解决这个问题,软件开发者们从其它工程学科中获得灵感。在这些学科中,把设计过程和建造过程明确的区分开来。设计者和建造者的沟通是通过设计图,要建造什么东西、怎样去建造都在这些图里面。

大部分的软件开发方法学,是以这种思想为基础的。不再是临时设计了,我们有了一种新的方法,我把它叫做预先设计(up-front design)。就是说,在写程序以前先设计,一旦设计完成了,开始写程序时,就不应该再有重大设计上的改变。当然,改变是在所难免的,但是预先设计流程明确的目的,就是要尽量减少这种改变。

困难的是:要让这些设计尽可能的完备,以避免以后发生重大的改变,而重大改变往往会把设计弄糟。这里就存在一个实际的问题——让设计从一开始就正确是很难的。

需求变更的现实 有一个最根本的问题。有时,我不得不去调查,一些搞得一团糟的项目,看看有什么办法可以让他们脱离苦海。每当,在这种情况下,我去和这些项目的开发者们谈话,我得到的,似乎总是一些恸哭流泣的抱怨:「客户在不停地改需求」。这总是让我感到很奇怪,我所奇怪的是,所有的人都对需求变更感到惊讶。我从来没有遇到过一个真正的项目,它的需求从不改变。即使你让用户在需求文件上用血来签字,不管他们是什么血型,最终还是会改变。

用户改变他们的想法有下面几个原因。一个原因是:一个要开发的系统,将会是个什么样子,要具体形象地表示出来是很困难的。只有当它摆在你面前,你去用它做实际工作了,你才会发现什么功能是真正有用的,什么功能是没用的。另一个原因是业务变更,六个月以前还是一个很真实很重要的需求,因为业务变更,现在就可能成为一个次要的需求。更另人恼火的是,有的用户自己也写过一些小程序:这里用 VB 写过一点,那里用 Excel 宏(macro)写过一点,所以他们就认为软件修改很容易(而他们从来也没处理过一个有许多问题,互相依赖的真正系统,但职业程序员必须处理)。

对许多人来说,这是需求工程必须面对的问题。我们需要更善于在事先把需求搞清楚,把更多的时间花在弄清需求上,而且要跟上新技术的发展。我也曾经这样相信过,但是现在我得出的结论是:这是不可能达到的,至少在一段时间内。

还有另一个关键的问题,这里需要取得一个平衡,你想要什么,你准备花多少钱。如果你买一台汽车,汽车销售人员跟你说:「你要汽车顶棚吗?」,那么你要问的第一个问题可能是:「多少钱?」,如果是 20 块钱,那么给我一个好了,如果是 20,000 块,那我宁肯不要。所以,除非我们给出一个较为精确估价,否则客户是不可能把需求固定下来的。不幸的是,我们在估价方面表现的很糟糕。我并不认为,这是由于软件开发人员都很笨的缘故,问题是我们用的基础材料在不停地变化。如果混凝土的特性每年也都会『升级』地话,土木工程师们,亦会发现他们的估价也很困难。

那么有其它选择吗?我想有一种选择,它可以归结为:期待需求变化,采用一种欢迎变化的开发流程。这种做法,与预先设计的核心思想格格不入。如果需求可以在没有任何警告的情况下改变,那么,让我们怎么来做一个稳定的预先设计呢?

让改变更容易 解决办法是使建造的软件在面对始料不及的变化时,更能应付自如。(我们可以在设计的时候,让它能够处理一些可预料的变化,但问题是那些不可预料的变化,跟在你的屁股后面咬你。)对象技术是这里的一个关键。利用对象封装性(encapsulation)和多态性(polymorphic)的接口,我们可以提高软件的组装特性,从而减少相互之间的依赖性,使改变也更容易。

动态开发环境也很有帮助,例如:对象浏览器,快速的找到交叉引用的特性,让你能探查你的代码的除错器和监视器,很短的编译/连接周期。对于许多职业开发者来说,这些工具还很新,但任何一个 smalltalk(译注:一种动态语言)程序员都知道:一个是在 debug 时,可以更改代码而且立刻生效,一个是让编译/连接来打断你的注意力,这两者是多么不同。

Refactoring(译注:重整,不知道这个译法是否正确,它是指这样一种程序更改:代码更改的目的不是为了增加功能,也不是为了提高效率,而是为了程序结构更合理,代码更清晰,可读性更高,更易扩展。作为一个黑箱来说,程序没有任何改变,作为一个白箱来说,程序的确改变了)在这里也扮演了一个很重要的角色。Refactoring 是这样一套技术,它可以有效地改变你的软件设计,却不会引入新的 bugs。有了 Refactoring,如果一开始设计有错误,以后你去改掉它,就不需要花很大的代价。

动态设计 所有这些技术(译注:上面提到的对象、动态开发环境、Refactoring)一起导致了我们设计方法的转变,这种转变的方向,我把它叫做动态设计。在动态设计中,你用不着非得一开始就要设计得完全正确。这并不是说让你放弃预先设计,你仍旧需要做预先设计,但这时,你设计的目的不是找到最佳解决方案,而是找到一个合理的解决方案即可。你知道,当你开始建造你的软件时,随着理解的一步步深入,你将意识到最佳的解决方案,与你最初的设想是不一样的。有了 Refactoring、对象和动态开发环境,这将不是一个问题,因为改变已经不再昂贵。

需要强调的是,这种转变的重要结果,是导致了一场简单设计(译注:简单设计基于这样一种思想:往一个简单的东西上面加东西,要比从一个复杂的东西上面减东西,容易得多。这也是 XP 的价值观之一)的运动。在我用动态设计以前,我总是在寻找灵活(flexible)的解决方案。对于任何需求,我总是想知道在系统被应用的生命周期中,需求会有怎样的改变。因为更改设计很昂贵,所以我试图让我的设计,可以容许我能预见到的改变。

构建灵活方案的问题是灵活的代价。灵活方案要比简单方案复杂,通常来说,由灵活方案建造的软件也更难维护,当然,如果恰好在我预见的方面需要灵活,那改变会更容易。所以,你需要懂得怎样去让设计具有灵活性。如果只有一两个部分,那没什么,但如果整个系统都会改变,那可就麻烦了。让整个系统在所有地方都很灵活,会使系统更复杂,维护的代价更高。

当然,更另人泄气的是,所有的这些灵活性,或许根本就是不需要的。也可能有一些是需要的,但让你去预见到底哪一些是需要的,几乎是不可能。所以要得到你需要的灵活性,你必须加进一些你根本不需要的灵活性。

用了动态设计,再去处理这些变更的风险,就大不相同了。你仍旧需要考虑潜在的变更,你仍旧需要考虑灵活方案,但在决定采用灵活方案以前,你要问一问你自己,「把一个简单方案,变成一个我需要的灵活方案有多难?」,如果答案是「小意思,很容易」(大多数都是这个答案),那么,你就采用一个简单的方案去吧。

所以动态设计会导致简单设计,却不会损失灵活性。这也使得设计过程更简单,压力更小。一旦你理解了这些东西,就会很容易的去重整(Refactor),你甚至不再去考虑灵活方案。如果需要改变,你有信心去重整(Refactor)。就像 Kent Beck(译注:《Extreme Programming Explained》和《Planning Extreme Programming》的作者)所建议的那样,建造一个最简单的东西,只要它能工作。为了灵活而做的复杂设计,在大多数情况下,是不需要的。

这真是设计流程的一个大变革,而且对于我这样一个设计者,也需要一个很大的转变。但它有几个前提条件:你需要很好的测试,你需要对象技术,你需要懂得Refactoring。不过它的回报也很丰厚,你再也不用害怕需求更改了,还有你可以响应你客户的要求,而不必牺牲你的设计,甚至你的前途。

 无双 回复于:2003-06-25 16:47:05
看了
认真想想先

首先觉得好的设计比简单设计更花时间
所以想写好代码和写快的代码是两回事

其次再补充

 无双 回复于:2003-06-25 16:52:33
本文提倡XP方法
这是解决中小软件开发中由于需求过份变化后引走代码的混乱的一个好方法

就是所做的系统只要能满足当前需求就可以了
简单就是最好是XP设计的精髓

如果需求改变,并且需要重构的话
就进行重构,  而不是修补原有的系统

这样新系统可以保持简洁的特色

但是重构本身需要时间与精力,这点是使用XP时需要考虑的
如果软件比较大的话那么重构是不可能的

继续想

 cinc 回复于:2003-06-25 17:14:20
[quote:d8e25f0de5="无双"]但是重构本身需要时间与精力,这点是使用XP时需要考虑的 
如果软件比较大的话那么重构是不可能的 [/quote:d8e25f0de5]     

本文提出简单为主是基于:
1。需求是变化的,人无法改变这个现实
2。人的认识得有个过程,对系统的认识是在开发系统的过程中不断完善的
   不可能一开始就有很好的设计。
3。修改软件的设计并不是很难的事情,重构在这个过程起到很大的作用。

最后一个观点,需要几个先决条件:
1。系统有完备的测试,以保证重构前后系统功能不变(Martin 曾在他的论文里提过曾经为一个大系统写了 2000 个的 unit test)
2。良好的设计(宜于修改的设计),如果设计太差,再好的重构技术也白搭
3。需要开发人员有很好的 重构的知识,就是何时,如何,怎么重构

有了这几个, xper 才有信心大声的说:“简单为主”     


大的系统不适合重构,这句话不怎么对
系统不是一天构建成的,重构也不是最后在做的,重构贯穿与软件开发的全过程
一般来说,重构的时机在:当你要往软件里新增一个功能,却发现现在的软件框
架不适合,就要先进行重构,然后在继续往系统加新功能。

重构的目的在于使系统更容易理解,更不怕将来的变化。

 无双 回复于:2003-06-25 18:05:40
因为面向对象的语言中都提供了封装等机制
所以重构时可以重用以前的类

如果需求变化很大
以致整个系统都要重写时
那么事实是是开始一个新项目了

所以重构只是重组织以前的对象
让他们更合理
或是对一小部分编写得不合理的对象重写
而不应该是全盘推倒重来

大系统中对象的关联很多
重构时必须考虑其它对象的影响
所以我认为重构并不适合大系统
你可以进行局部的修改,或是模块内的修改
但是对整个系统的全局修改那要问问经理是不是同意了

另外重构需要花时间与人员
所以只是不得已时而为之

每个项目都有自己的预算与经费
经常重构, 系统的开发成本会更高
因此开始时应该尽量掌握客户需求而不是想等到后面客户提出需求时再重构

 cinc 回复于:2003-06-26 09:25:07
>如果需求变化很大 
>以致整个系统都要重写时 
>那么事实是是开始一个新项目了 
Refactoring 也不是万能的,这种情况得比较一下 Refactoring 和重写的成本
如果 Refactoring 的成本更高,就重写吧。



>所以重构只是重组织以前的对象 
>让他们更合理 
>或是对一小部分编写得不合理的对象重写 
>而不应该是全盘推倒重来 
说得对,每次的重构只是对系统的一部分进行的。


>大系统中对象的关联很多 
>重构时必须考虑其它对象的影响 
>所以我认为重构并不适合大系统 
>你可以进行局部的修改,或是模块内的修改 
>但是对整个系统的全局修改那要问问经理是不是同意了 
良好的设计应该做到:如果增加一个新的功能,系统需要改动的地方应该最少
这可以由两个方法做到:
  早期的设计考虑到了将来的变化
  早起的设计没有考虑到这个变化,但可以用重构使系统的结构适合这点


>另外重构需要花时间与人员 
>所以只是不得已时而为之 
不同意。
重构的结果是:程序更容易理解,更容易面对变化,每次加入新的功能都只需要改动很少数的地方,
这样可以减少理解系统,增加新功能的时间,使项目能以恒定的速度加入新的功能

而不是象以前的项目,开发越来越慢,最后加入一个新功能会导致系统的太多地方的改变而不得不
减慢开发速度,甚至完全重新系统

>每个项目都有自己的预算与经费 
>经常重构, 系统的开发成本会更高 
>因此开始时应该尽量掌握客户需求而不是想等到后面客户提出需求时再重构
不同意。
重构不会引起开发成本的提高,反而会降低开发成本

正如文章里所说的,正是由于以往的开发(up-front design)害怕将来的需求改变
所以才出现你说的这种情况:
“希望开始时应该尽量掌握客户需求而不是想等到后面客户提出需求时再重构”

但是,开发人员和客户都是在系统开发的过程中对系统有不断深入的认识的
所以不可能指望一开始就掌握完整的需求,必须承认这点:需求永远使变化的。

究其根本,文中说道,是一个“want 和 cost 的问题”,是因为后期的需求改变
所带来的成本的增加太多了,你的推断是基于这个前提。

但是由于有了 Refactoring,有了完备的测试,有了良好的设计,使 want 和 cost
的关系发生了很大的变化,后期需求的改变并不会引起太多的成本增加。

这就是 xp 里所说的勇气:有了测试,refactoring,频繁的发布,我们需要做的只是
努力做好今天的事情,我们并不害怕将来的需求的变化。

Martin Fowler 为 Refactoring 专门写了一本书:
Refactoring: Improving the Design of Existing Code

在中国刚出影印版:
http://www.china-pub.com/computers/common/info.asp?id=12301

可以去看看。
:)

 无双 回复于:2003-06-26 10:03:53
如果开始需求明确
那么设计就会比较完善

这样写时不需要多少重构

重构是一种方法
但不是说什么都可以通过重构来解决
夸大重构的作用

因为 重构后要对系统徕进行编码 测试  修改关联部分
成本很高

所以开始的需求分析与设计是很重要的
而不是说等到后面再通过重构解决问题

所以就是要知道
重构是一种解决问题的方法 可以让系统代码更简洁 可扩展性更好 
而不是什么都要通过重构来解决

 cinc 回复于:2003-06-26 10:10:52
说的对,呵呵。

对于已经很明确的需求,当然一开始就要用良好的设计开始

只是对于将来无法预测的需求的改变,可以使用重构的方法来解决

:)

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有