《程序员》推荐三味书斋——OO篇
来自《程序员》2002年第10期
创建人: 《程序员》
安安注:以下人物介绍的时间是文章出版时期。
主持人:熊节(透明):《程序员》杂志社技术编辑,C-View成员。
嘉 宾:孟岩(梦魇):联想公司掌上设备事业部应用开发处任职,C-View成员。与侯捷先生合译了《C++ Standard Library》一书。
王昕(痴人),C-View成员,《The C++ Standard Template Library》译者。
透明:对于面向对象,UML应该是第一要素。自然语言有着极大的不精确性,维特根斯坦认为这种不精确性是一切哲学问题的根源。如果要用自然语言来描述一个软件系统,这种不精确性也会给软件工程师之间的交流带来巨大的麻烦。UML的价值就在于:它比较精确,并且比较形象直观,对于促进开发者之间的交流是很有好处的。
梦魇:我目前还没有系统地学习过UML。在目前的OO领域,UML确实具有标准语言的地位,虽然这并不意味着它就没有缺点和错误,但是有一种标准语言,总比大家自说自话,老死不相往来要强得多。不过在我看来,它最重要的意义也就在于它是公认的标准,大家以它为共同语言进行交流。这并不等同于说UML就是OO,或者不懂UML便不懂OO。
UML是不是OO的核心或者第一要素,我持怀疑态度。我也很怀疑,那些只会画UML图,并自命为“架构师”的人,究竟能否真正设计出精致的系统。
痴人:其实我对于UML现在已经没有什么感觉了,说到底,UML只是一种工具,所谓的OO还是只能存在于开发人员自己的脑袋中。只是为了沟通上的需要,有UML这么一个标准的工具会方便很多。从其他方面来说,只要大家都愿意并且可以很好的交流,直接用代码来沟通也不是一个很坏的主意。
透明:其实我从来都没有认真学过UML,只看过一本《UML参考手册》,是汪颖翻译的电子版。在做项目、写文章、译书的时候,对UML有什么不懂的,就到那本参考手册里面去查查,慢慢也就熟悉了。不过这种学习方式的缺点就是:自己不太用的feature就总也掌握不好。比如用例,我到现在都不太明白。如果是想认真学UML,机械工业出版社的三本书《UML参考手册》、《UML用户指南》和《UML和模式应用》就足够了。《UML和模式应用》这本书,其实应该叫《UML实例分析》比较合适,很适合面向对象和UML的初学者练手用。
前一阵网上吵架,有人捧UML也有人骂UML,其实UML就是一种语言而已,它对于软件开发者的意义基本上就等于黑板和粉笔对于教师的意义。无论用UML做出了好的系统还是坏的系统,难道跟UML有关系吗?我向面向对象的初学者建议学UML,仅仅因为它是最流行的建模语言,不掌握它就无法和别人沟通。
梦魇:我对于UML的书没有太多了解,虽然也买了几本,但是看上去总觉得索然无味。我曾经怀疑我天生不喜欢用图形来表达设计思想,因为相比代码而言,那些图形似乎总显得不够具体生动,形象模糊。我总是担心一个设计方案蒙着面纱的时候像是绝色的美女,除掉面纱却是千疮百孔。有些早期的介绍性书籍甚至给我造成很大的误导。比如我在相当长的时间里,一直以为用例跟用例图是一回事,因此非常怀疑那些简单的图形究竟能在需求分析中发挥什么了不起的作用?直到不久之前才知道,真正的用例是要写的。
说起来,是Craig Larman的Applying UML and Patterns使我对UML第一次有了亲切感,也在一定程度上认可了UML的价值。不过我现在还没有开始运用它,所以不想、也没这个能力就这个问题多说什么。
痴人:国内出的几本UML的书籍我也买了,但基本都没有看完。我的UML知识是用了一周从Rational的CD tutorial中学到的(可在Rational Suite的CD2中找到),另外就是我问Rational要到的Inside UML的CD-ROM。通过那些图文并茂的tutorial,我觉得学习的效果还是不错的。
对于OO,我曾经从china-pub上面拍卖到一本小书,叫Object Technology:A Manager's Guide,觉得里面的叙述算是比较清楚的。薄薄的一本书(含index两百多页),内容涵盖了对象技术的基本思想、对象技术的重要概念、面向对象数据库、对象技术在企业中的实施等等方面。作为帮助初学者的入门手册、开发者的速查手册都不错。如果有机会,希望国内的出版社可以考虑引进该书。
透明:我非常同意孟岩的说法。这让我想起维特根斯坦在《逻辑哲学论》里举的一个例子:我们可以在几何图象中描绘出不符合空间规律的情景,但无法在空间图象中描绘不符合空间规律的情景。或者换句话说:UML能画的,OO语言未必能实现,实现了也未必就很好。因为UML和C++、Java,毕竟是完全不同的语言。
并且,我一直认为自己是个程序员,所以我更关心“程序员的面向对象”,或者叫面向对象程序设计。当你要用C++或者Java来实现面向对象的时候,那跟用UML画图还是大不一样的。我记得以前看过机械工业出版社的一本《 软件工程-Java语言实现(英文版,第4版) 》,觉得是很好的教科书。而且Java天生就适合用来做面向对象的教学语言,它的语义是smalltalk那一派的,描述从smalltalk发展来的“传统面向对象”得心应手。
痴人:在我看来,OO只是一种程序开发中的抽象方式,不过它恰好是现阶段我们所能接受并认为是最好的一种抽象方式罢了。为了开发中的需要,才会有从基本的OO中整理出来的Refactorings、Patterns等。但我们应该认识到:这都不是本质,只有程序的抽象程度、弹性、可维护性等特性才是我们应该关注的。
为此,我对OOSC(Object-Oriented Software Construction, 2nd Edition,清华大学出版社1999年影印版)一直都赞美有加,不是因为它在OO书籍中的Bible地位(说实话,它太厚了,以至于我每次都没有信心把它看完——事实上我也没有看完它),而是它第一章就讲了Software Quality,让我对于程序的本质有了更多的了解。
对于Design Pattern,我觉得它们不能代表OO的本质,只是OO中的一个分支,用于改善程序中的OO状态而已,没有必要把它们等同于OO。
另外,也有人喜欢把OO分为OOA/OOD/OOP,对于Analysis,由于以前所做项目的因素,我不是很熟悉,不好乱说。但OOD并不能等同于某些所谓的“架构师”用Rose、Together、Visio等工具画出来的UML图形。有时候,一些在图形中看起来很好的设计,在转化为代码时往往会碰到麻烦,所以我一般都喜欢用代码辅助图形来进行我的设计。
至于OOP,我觉得它应该是和OOD结合的非常紧密的一个步骤,没有很多好说的(毕竟程序和设计绝对是一个硬币的两面,我们无法把它们很好地区分开来)。
梦魇:提到OOSC的地位,我举双手赞成王昕的观点。
我认为Bertrand Meyer以及他所代表的Eiffel流派对对象技术理解是最深刻的。十几年来,他们在整个OO技术界一直处于支流,这不能不说是一件令人遗憾的事情。我认为,如果Eiffel及其所倡导的Design By Contract理念一开始就被人重视,那么整个90年代软件工程的发展格局可能都会不一样。另外,从语言本身来说,Eiffel也是非常出色的,我觉得无论将来想不想用这种语言开发项目,认真的学习一次是大有意义的。
OOSC我正在看,里面有不少令人耳目一新的观点,初读起来觉得诧异,细细想来却觉得本该如此。比如把command和query区别对待的观点,所谓访问形式一致性原则(Unified Access Principle),等等,都令人有拨云见日的感觉。
Eiffel的立足点是可扩展性、可复用性和可靠性。我记得前不久我们在一起讨论,这几个目标正是令我们困扰的东西。真的能编写可复用的组件吗?测试难道是保证软件质量的唯一手段吗?是不是面向对象发展到今天,都一直达不到这几个目标,最后只能给所谓的“面向组件”技术当垫脚石呢?读了OOSC,很多疑惑豁然开朗,信心又回来了。
痴人:刚才说过,对于OOSC,我最prefer的还是第一章“Software quality”。
我们一直讲“软件质量”,但是对于“软件质量究竟是什么”这个问题,甚至很少正式解决过。在这一章里面,对影响软件质量的外部因素(例如正确性、坚固性、可扩展性、兼容性、效率等等)和内部因素(模块化、代码可读性等等)提出了明确的定义。我觉得,这一章说出了软件质量的本质。这些东西,是“如何提高软件质量”的先决条件。
透明:不知道你们有没有看到裘宗燕教授翻译的一本叫做《从规范出发的程序设计》?王昕恐怕应该好好读一读这本书。中信出版社的。
痴人:这是怎样的一本书?
透明:第一次看到Design by Contract,是在网上的一篇文章,觉不出有多大的价值;第二次看是在OOSC,觉得的确有价值,对于解决所谓“软件危机”大有帮助。我刚翻译的《最后期限》里面就有一句比较经典的话:软件模块很不容易出错,即使出错也会被程序员发现;软件的错误总是在模块与模块之间的交流上。而Design by Contract很大地帮助了程序员之间、模块之间的交流。
然后就看到裘教授那本《从规范出发的程序设计》。看完以后,只有一个想法:为什么Design by Contract会一直没有受到重视?我甚至觉得Design by Contract应该是天经地义的,我们使用的OO语言才是一种非常冒险的做法。
按照裘教授那本书的理论,程序设计是一个规范逐步精化的过程。你首先必须确定一个规范是可行的,然后确定对这个规范的精化的过程是可行的,这样才能得到合法的程序。而在我们使用的OO语言(例如C++、Java)中,并没有证明一个规范是否合法,换句话说,我们并没有保证client以合法的方式来调用我们的模块、使用我们的返回值。我们只把这些要求写在文档里,天知道client会不会按照文档来做?恶魔前几天问我“如何证明面向对象的科学性”,我想他的迷惑也有这个原因。
痴人:那么,裘教授这本书给出了规范合法性和精化过程合法性的形式化证明吗?如果是这样,那么这本书就定义了一种严格的、不依赖于任何特定语言的程序开发方法,对于软件开发的理论倒是很有价值的。
透明:正是这样。不过,这本书里面几乎全是逻辑代数,读起来非常吃力。裘教授译书的态度、治学的态度都极其认真,这本书的质量是非常高的。
梦魇:我想从更一般的意义上来谈谈我对于Contract在软件系统中重要性的认识。
首先问一个问题,我们为什么要使用对象技术?大家都会回答说,因为系统规模大到一定程度,随着需求变化的振荡性影响越来越大,结构化的方法已经不能适应需求。我想问一句,为什么结构化的方法就行不通了呢?我们用结构化的方法做了很多事情,现今大部分机器和工业产品是用自顶向下的分析思想构造的。象三峡大坝那样的工程,难道它的复杂程度不高、规模不大吗?为什么结构化方法运用于软件,就不行了呢?
痴人:你是想说“依赖倒置原则”吧?结构化系统中,底层模块依赖于上层模块。Robert Martin在Designing Object-Oriented C++ Applications中提到过。
梦魇:差不多是这个意思。我看到的每本软件工程的书,都试图解答这个问题,有的说是因为软件太容易抽象了,有的说是人们对软件重要性的重视不够,各种观点都有。但是我认为,那些都是次要的,最重要的原因是,自顶向下的软件设计方法真正蕴藏的是一种集权的思想。
按面向对象的行话来说,在结构化程序中有那么一个god object,掌控一切,从你这个模块的生死大权,到你的生存行为模式,你的内部组织形式,这个god object无不了如指掌,它统揽一切,随时可以以至高无上的身份干涉各个模块的行为。也正因为如此,它承担了沉重的职责。
软件作为一种工业产品,其质量的要求迫使这个god object必须完美地管理它的臣民,更重要的是,它必须对底层模块的变化作出正确的反应,也就是说,这个god object必须是一个真正“好”的统治者,一个真正的公仆,要对底层模块作出反应,也要对它的客户负责。它不能高高在上,作威作福,而必须事必躬亲,兢兢业业。我们看到了,在规模相对较小的系统里,这个工作是可以达成的,而且可以达成的很好——只要我们有良好的、甚至是天才的设计,即便我们粗暴地限制了下层模块的自由,一样可以让他们运作地井井有条。
透明:哈耶克在《通往奴役之路》里面可是批判了这种集权的。不过,人类社会是个非线性系统,集权导致失控的可能性比较大。而图灵机是线性系统,其中会出现混沌效应吗?
梦魇:虽然我对于非线性系统一无所知,但是我怀疑,软件系统实际上也存在着所谓的混沌效应,毕竟软件是由人开发的。也就是说,可能在这个模块里有一只蝴蝶扇了一下翅膀,而在另一个模块里就会引起一场风暴。
因此,当软件系统的规模大到一定程度,这个god object就不堪重负了。在这种情况下,就像社会学家们所说的,不管某个设计者自己是否有能力来统揽一切,为别的模块计划和指导一切,单单认为自己有这个能力和权力,这种自负就已经是足够危险和荒谬的了。
痴人:没错,结构化程序的问题就在这里。正是因为这个原因,软件业中才会有所谓“软件蓝领”的说法。也正是因为这个原因,结构化方法才屡屡遭到失败。尤其是在需求变化比较快的时候。
梦魇:所以,软件工程界提出来decentralize的思想,取消这个虽然忠于职守,但已经无法支撑的god object,让各个模块变成各自独立的、有有限自主权和自由的对象。把树状的、自上而下、阶级森严的结构形式捣毁,改制为图化的、模块化的、平等的、友好的、协作的联盟或联邦式对象结构形式。让整个软件系统的对象之间彼此互相合作,完成工作。
谁都无法否认,这一进步在思想上是非常伟大的。可是存在一个问题,谁来保证各个模块以合法的、合理的秩序进行协作?没有了god object,谁来做这件事?自由不是绝对的,自由的个体需要契约来维系协作的有效性。即使你能够通过有效的职责分配把一个系统的复杂程度从不受控的非线性转化为稳定的线性系统,个别不守规矩的对象仍然可以导致整个系统的失败。
透明:对了,你们是否还记得以前我转贴过几篇文章,叫“OO,OO以后,及其极限”?在那篇文章里,作者从维特根斯坦的哲学推测:“面向对象(OO)之后是面向事实(FO)”。所谓“面向事实”,我还无法想象到。但维特根斯坦说过:“……事实,就是诸事态的存在。事态是对象的结合。”Design by Contract为我们提供了一种可行的结合对象的方式,应该说是在OO之上的一大进步。
梦魇:你说得对。未来人们怎么解决这个问题,我不知道。但是今天,最理智的答案就是Design By Contract。因此,跟你一样,我现在认为,DbC不是面向对象的可选属性,而是必备属性。是契约把这个自由协作对象群体区别于无政府主义的混乱对象群体。不管你用C++、Java还是别的任何面向对象语言进行开发,契约都是存在的。只不过Eiffel把它显现出来,并且把它放在系统构造的核心位置上。这同样具有伟大的意义。
正文
《程序员》推荐三味书斋——OO篇2006-03-23 12:32:00
【评论】 【打印】 【字体:大 中 小】 本文链接:http://blog.pfan.cn/xiangyu/11303.html
阅读(4345) | 评论(0)
版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!
评论