频道直达 - 专题 - 新闻 - 基础 - 高级 - 安装 - 技巧 - 数据库 - 手册 - PHP - Linux - Java - MySQL - Apache - 麻辣堂 - 狼盟 - Rails社群 - 搜索 - 下载 - 开源 - 论坛
PHP开发资源网 主页>>高级应用>> 收藏此文 | 收藏本站 | 设为首页

面对对象的思考

来源:www.phpres.com 作者:Angelover 出处:www.phpres.com 2007-7-25 20:47:21 进入讨论组
关 键 词: 思考 对象 面对 方法 抽象 问题 实现 复用 继承 一个

如今,面对对象方法几乎成为了成功、先进、效率的代名词。使用面对对象的方法设计和实现一个软件几乎成为了开发者们的默认选择。但是,这种方法是否已经真正取得了成功了呢?真的达到了在他产生时候宣称的优势呢?很显然对于这样的问题大多数人是迷惑,不能作出肯定的回答。面对对象的方法在软件分析和设计方面仍然遇到了困难,这些困难主要有这些表现:
1、抽象现实问题的方法不容易被开发者真正掌握。分解问题域中对象一般的思考方式有以下两种,一种是抽象对象的性质,这种方法实际上就是对象继承,第二种就是对象组合的方法。在经典的理论中认为对象的继承是面对对象方法的实质,但是不符合大多数人的思维习惯。对于一个轮胎而言,人们更愿把它看成轮箍、外胎、内胎等等结构的组合体,而不是抽象成这样的层次关系,橡胶-〉含有金属的橡胶-含有金属的圆形橡胶-〉轮胎。
2、分析到设计仍然不能平滑的过渡,在分析阶段产生对象,往往有很多现实的名词,这影响了设计者的思考,使他们不能关注对象在问题域中的关系,往往受到这些名词其他含义影响。假定普通的企业管理系统中,分析作了人-〉公司职员-〉高级职员-〉经理的抽象,设计人员往往会被人、经理、高级职员这些名词的影响,不能把这样的现实对象很好的映射到程序结构中去,甚至会去定义人的姓名、年龄这些属性,然而这些属性在问题域中是不关心的,实际上在程序结构中人这个对象会和真正的人概念完全不一样,之所以抽象这些对象实际上为了提取问题域中的静态关系和动态关系,现实的名词干扰了设计者。
3、面对对象方法产生的软件没有完全实现宣称的软件复用和简化维护的目标。在没有完全采用抽象对象性质的方法的时候,实际上完全采用也是很困难的,大多数人习惯于把复杂的事物分解成一组组合的对象,把简单的事物进行抽象,在这种情况下产生的软件结构是复杂的,对象组合之间必然充满了复杂的消息,要进行重复使用和维护当然是不容易的。
4、缺乏评价一个面对对象设计的标准,一个设计,或者说怎样做出一个能够实现软件复用、降低软件复杂性的设计,没有很好的理论支持。这本身就是由于对象抽象的灵活性造成的,不同的人对同样的问题完全会有不同的抽象方法,面对对象的方法不限制人们抽象的方法,或者说根本没有一套抽象的方法。我说的是抽象,和对象组合对应。缺乏标准,也必然造成软件复用困难。
为了解决这些问题,很多人进行了回归,我要说一些大逆不道的话了。第一个概念把继承分解为接口继承和实现继承,认为对象实际上是实现和宣称的方法集组成的,在现实的设计活动中,他们找到了复用的好办法,因为他们把接口和实现分离,这样在通过同样的接口就可以操纵不同的对象,而不用关心背后对象的细节,这样降低了对象之间的关联程度。第二个概念,尽量使用对象组合而不是继承,在把继承分解以后,就会很自然的发现,纯虚的基类实际上成为了对象的接口,而且为了复用的方便,几乎完全不要实现继承,因为复用是对象本身,而不是用它的基类,所以定义一个良好的组合成为了关键,而且继承也会为这种复用带来麻烦。我把这种解决方法称为回归,这是面对对象向结构化的回归,或者说结构化方法的延伸。在对象进行复用的时候,一般不使用已经成型的对象,而是使用基类,复用的是基类已经实现的方法,当然这样做,需要深刻理解原作者的意图。一个只有一个纯虚基类的对象和一个模块有什么差别呢?这是模块的复用。复用的只是接口,也就是一组定义,要实现支持同样接口的不同对象,需要完全重新设计,实际上并没有代码复用。他把实现的复杂性推给了后面的设计者。如果仅仅把接口复用当成分析,在实现这个借口对象的时候仍然坚持实现继承,也就是实现的时候仍然分层,那么这当然是可取的,但是我看不出需要接口继承的意义。在这种方法下,设计者更倾向于进行问题的功能分解,举个例子,设计企业的管理系统,设计者很可能在这种思考方式的主导下,划分成财务部,人事部,业务部。这完全背离了面对对象方法的初衷。
大多数问题是复杂的,习惯总是明智的,把一个大的问题分解成小问题,在解决小问题的时候使用抽象的方法,可以说是一个很好的折衷,也是很有效率的。但是不能把整个问题都细化,或者说完全取消实现继承,如果那样我看不出这还是面对对象。我更愿意看到结构化方法和面对对象方法的融合,而不是盗用了面对对象的概念行结构化的做法。在对于评价分层抽象,或者说分层抽象指导原则、模式,几乎没有,这不能说是完整的。就像气宗和剑宗构成了华山派一样,独孤九剑好像是绝种的剑宗武功,虽然难炼,但是杀了岳不群。

 

在比较老一些的讨论面对对象方法的书籍中,都把继承看成了最为关键的部分。一般认为,面对对象的方法中最为核心的部分就是继承,因为从继承的角度思考问题,是和结构化设计最为明显的区别。如果,对象都没有继承,那么对象和传统的模块的概念没有太多的差别。我并不是要把这两种方法对立起来,我只是认为面对对象的方法背后的思想是应该和传统结构化的方法有所区别的。
 在结构化的方法中,我们首先需要考虑的是整个软件系统的功能,然后按照一些基本的模块划分的原则,比如高内聚,松耦合,还有模块的扇入扇出数等等,把整个软件的功能分解为各个模块的子功能。当然,模块一般认为是黑箱的。在设计阶段需要定义的是各个模块的调用规则,我不想说是接口,接口我想用在下面另外一个地方。在完成了所有的模块的设计后,拼装好,就应该能够实现整个软件的功能了。当然这属于自顶向下的设计。这种思考的方式应该说是很自然的,就像搭积木一样,也和我们平时的思维习惯相一致,他不是探究为什么会有这样的功能,而是思考我如何实现这样的功能,当然我们的目标就是如何实现,但是他的思考方式是很直接的。这种方式有很大的局限性,一是需求分析总不是很明确,也永远不可能很明确,这就需要经常的变化原来的软件功能构想,这带来了麻烦,因为需要修改各个模块的设计,有时候甚至是致命的,会造成原来的设计被完全推翻。这需要一个很有经验的设计师,他必须了解这个软件适用行业的业务,必须了解未来的软件发展趋势,并且要能够预测用户可能的需求变化,这种要求是相当高的,一个设计师的水平就往往决定了一个软件的生存时间,就算他有一个很好的团队,他的拙劣设计仍然会使这个软件成为昙花一现。二是结构化设计带来的漂亮的文档,仍然不能为以后的维护工作带来相当的好处,大多数的维护工作都是由于用户的需求发生变化引起的,漂亮清晰的文档虽然能给后来的维护者很大的帮助,却仍然不能减少他们的工作量,维护者在改动的时候仍然需要全面准确的理解原来设计者的意图,否则就算有好的文档,维护工作仍然会带来大量的错误,特别是在用户需求发生大的变化的时候。在最近有了一些变化,我会在后面讨论。
 面对对象的方法在开始的时候,第一个工作就是识别对象,识别在问题域出现的对象,最经典方式是寻找需求说明书中出现的名词,这是有道理的,语言是思维的外壳,这些名词在我们头脑中的概念决定了他们之间的联系,这种方式是偷懒的也是最自然的方式。第二步是寻找这些已经确定了的对象之间的共性,当然我们寻找的对象集应该是能够涵盖整个问题的了。寻找共性就是确定它们的共同祖先,在这个过程中设计师能够对问题有进一步的清晰的了解。第三步就是确定问题中各个对象之间的关系,也就是它们之间的消息传递,这不是指Windows中窗口的消息,呵呵。这个过程是苦难的,因为要确定各个对象之间的关系,也就是要更加精确的描述原来的问题,但是也是灵活的,就算理解出现了偏差,仍然是可以愉快的加以改正,因为我们是在理解对象,而不是分解功能,注意,我强调的是理解,而不是设计。这时候我们就可以提交我们的初步成果给客户使用了,有问题的时候加以修改,这种修改不会很困难,因为我们不是基于功能分解,而是基于理解问题域中的对象概念。我们不太会把所有的对象都理解错误,理解错的只是一个或者很少的一部分对象。我认为面对对象方法的实质在于迫使设计师从为什么的角度来设计软件,而不是很直接的怎么做,在这种理解过程中,很自然的形成了我们的设计方案。在这个机制中,能够起到关键性作用正是继承,他是连接为什么到怎么做的桥梁,他自然和不自觉的就把设计师对问题的理解变成了解决问题的方案。之所以会这样,那是因为,在现实世界中我们早就形成了解决这个问题的方法,我们需要的只是把这个解决方案转换成计算机的描述。我们在头脑中的各种概念就是我们解决现实世界的各种问题留下的痕迹,他为我们解决类似的问题提供了参考,请注意到一个事实,科学研究就是想知道是什么和为什么,而不是要干什么,但是我们知道了是什么和为什么以后,我们就会知道要干什么。举一个不恰当的例子,有一个工人很不满他的工资待遇,于是有一个人跑来跟他说,你这么少的工资待遇是因为我们国家还很困难,社会还在转形,不可避免的要有一部分人作出牺牲,于是这个工人就很满意了。为什么这个工人会满意?他原来要寻找的是解决他不满工资待遇的途径。其实,国家的概念在他的脑子中是神圣的,换一句话说,就是一种难以抗拒的力量,这是他的成长道路上教训形成的,当他不尊重国家的时候,老师会罚站,然后那个人的话,就演变成,你现在无法抗拒国家的力量,你现在这种状况是国家的意志,呵呵,这个工人知道怎么做了,就是安于现状。当然他不这样认为,他的概念是我是崇高的。这有点像宗教哦,有点跑题了。不过的确,理解一个问题,实际上就是寻找解决问题的途径。
 在最近的一些日子里,传统的结构化的方法发生了变化,他开始吸收面对对象的概念,用于解决他的传统问题,就是修改模块困难的问题。一方面,他形成一些经典的设计模式,帮助提高设计师在设计同类问题时的能力,如同建筑中的经典设计结构,不过,这种帮助是有限的,我们很少见到一样的建筑物吧!另一方面,它使用接口的概念,意图就是,使模块的实现和描述进一步的分离,这种好处在于,可以在一开始就设计灵活性很高的接口,使用模块是通过接口,这样做实际上把总体设计的负担进一步减轻,他把责任推给了接口实现者,因为在结构化的方法中灵活和精确始终是矛盾的。很多人把这种变化看成是面对对象方法的延伸,而我始终坚持认为:面对对象的方法是寻找是什么和为什么的过程,结构化的方法永远是寻找做什么和怎么做的过程。

欢迎进入PHP开发资源论坛讨论。
收藏此文】【 】【打印】【关闭
相关文章
图文推荐
论 坛 资 源
PHP开发资源网奋斗目标
阅读排行:
热门技术文档
最新图文档
本站编辑推荐:(本站开通Delphi4PHP专区,欢迎进入论坛交流!)
编缉最近更新文章
网站赞助商
搜索您感兴趣的内容
 
   网站首页 -  网站地图 -  网站合作 -  手册中心 -  通用网址 -  网站论坛 -  网站投稿 -  友情链接 -  帮助中心
版权所有:PHP开发资源网 © 2003-2008 通用网址:PHP资源网 合作媒体: 赛迪网IT技术
互联网违法和不良信息举报中心 | 不良信息举报信箱