`

对面向对象的一些思考

阅读更多

原文地址:http://blog.codingnow.com/2008/06/object_oriented.html

 

面向对象方法被人谈论了二十多年了。我接触它比较晚,直到九十年代中期才开始学习使用它。若说对这个方法做些评价,那还真是大言不惭了。不过这么些年来,也周期性的对面向对象做些思考。或对或错,我想都值得总结一下。一家之言,来看的同学不必太当真。

首先我们要区分一下“基于对象”和“面向对象”的区别。

基于对象,通常指的是对数据的封装,以及提供一组方法对封装过的数据操作。比如 C 的 IO 库中的 FILE * 就可以看成是基于对象的。

面向对象,则在基于对象的基础上增加了多态性。所谓多态,就是可以用统一的方法对不同的对象进行同样的操作。当然,这些对象不能完全不同,而需要有一些共性,只有存在了这些共性才可能用同样的方法去操作它们。我们从 C++ 通常的实现方法的角度来看,A 和 B 在继承关系上都有共同的祖先 R ,那么我们就可以把 A 和 B 都用对待 R 的控制方法去控制它们。

为什么需要这样做?

回到一个古老的话题:程序是什么?

程序 = 算法 + 数据结构

在计算机的世界里,数据就是一个个比特的组合;代码的执行流程就是顺序、分支、循环的程序结构的组合。用计算机解决问题,就是用程序结构的组合去重新排列数据的组合,得到结果。为了从庞大的输入数据(从 bit 的角度上看,任何输入数据都可能非常的庞大),通过代码映射到结果数据。我们就必须用合理的数据结构把这些比特数据组合起来,形成数量更少的单元。

这些单元,就是对象。对象同时也包括了对它进行操作的方法。这样,我们完成了一次封装,就变成了:

程序 = 基于对象操作的算法 + 以对象为最小单位的数据结构

封装总是为了减少操作粒度,数据结构上的封装导致了数据数据的减少,自然减少了问题求解的复杂度;对代码的封装使得代码得以复用,减少了代码的体积,同样使问题简化。

接下来来看 基于对象操作的算法。这种算法必须将操作对象看成是同样的东西。在没有对象的层次上,算法操作的都是字节,是同类。但是到了对象的层次,就不一定相同了。这个时候,算法操作的是一个抽象概念的集合。

在面向对象的程序设计中,我们便少不了容器。容器就用来存放一类有共同抽象概念的东西。这里说有共同概念的东西,而没有说对象。是因为对于算法作用于的集合,里面放的并不是对象实体,而是一个对实体的引用。这个引用表达的是,算法可以对引用的那一头的东西做些什么,而并不要求那一头是什么。

比如,我实现一个 GUI 系统(或是一个 3d 世界)。需要实现一个功能——判断鼠标点选到了什么物件。这里,每个物件提供了一个方法,可以判断当前鼠标的位置有没有捕获(点到)它。

这时最简单的时候方法是:把所有可以被点选的物件都放在一个容器中,每次遍历这个容器,查看是哪一个物件捕获了鼠标。

我们并不需要可被点选的物件都是同类,只需要要求从容器中可以以统一方法访问每个元素的是否捕获住鼠标的这个判定方法。

也就是说,把对象置入容器时,只需要让置入的东西有这一个判定方法即可。了解 COM 的同学应该明白我要说什么了。对,这就是 QueryInterface 的用途。com 的 query interface 就是说,从一个对象里取到一个特定可以做某件事情的接口。通常接下来的代码会把它放在一个容器里,方便别处的代码可以干这些事情。

面向对象的本质就是让对象有多态性,把不同对象以同一特性来归组,统一处理。至于所谓继承、虚表、等等概念,只是实现的细节。

说到这里,再说一下 COM 。COM 允许 接口继承 ,但不允许接口多继承。这一点是从二进制一致性上来考虑的。

为什么没提 实现继承 的事情?因为实现继承不属于面向对象的必要因素。而且,现在来看,实现继承对软件质量来说,是有负面影响的。因为如果你改写基类的虚方法,就意味着有可能破坏基类的行为(继承角度看,基类对象是你这个对象的一部分)。往往基类的实现早于派生类,并不能了解到派生类的需求变化。这样,在不了解基类设计的前提下,冒然的实现继承都是有风险的。这不利于软件的模块化分离和组件复用。

但是接口继承又有什么意义呢?以我愚见,绝大多数情况下,同样对设计没有意义。但具体到 COM 设计本身,让每个接口都继承于 IUnknown 却是有意义的。这个意义来至于基础设施的缺乏。我指的是 GC 。在没有 GC 的环境中,AddRef 和 Release 相当于让每个对象自己来实现 RC (引用计数)的自动化管理。对于非虚拟机的原生代码,考虑到 COM 不依赖具体语言,这几乎是唯一的手段。另外 COM 还支持 apartment 的概念,甚至允许 COM 对象处于不同的机器间,这也使得 GC 实现困难。

QueryInterface 存在于每个 COM 接口中却有那么一点格格不入。它之所以存在,是因为 COM 接口指针承担了双重责任,既指出了一个抽象概念,又引用了对象的实体。但从一个具体算法来看,它只需要对一组相同的抽象概念做操作即可。但它做完操作后,很可能(但不是必须)需要把对象放入另一个不同的集合中,供其它算法操作。这个时候,就需要 QueryInterface 将其转换为另外一个接口。

但是,从概念上讲,让两个不相关的接口相互转换是不合逻辑的。本质上,其实在不相关的接口间转换做的事情等价于:从一个接口中取得对对象的引用,然后调用这个对象的方法,取到新的接口。

如果去掉了 AddRef Release (依赖 GC )以及 QueryInterface (只在需要时增加一个接口获得对象的引用),IUnknown 就什么都不剩了。那么接口继承也完全不必存在。


回头再来看程序语言。

C++ 提供了对面向对象的支持,但 C++ 所用的方法(虚表、继承、多重继承、虚继承、等等)只是一种在 C 已有的模型上,追加的一种高效的实现方式而已。它不一定是最高效的方式(虽然很少能做到更高效),也不是最灵活的方式(可以考察 Ruby )。我想,只用 C++ 写程序的人最容易犯的错误就是认为 C++ 对面向对象的支持的实现本身就是面向对象的本质。如果真的理解了面向对象,在特定需求下可以做出特定的结构来实现它。语言就已经是次要的东西了。

了解你的需求,区分我需要什么和我可以做到什么,对于设计是很重要的。好的设计在于减无可减。

你需要面向对象吗?你需要 GC 吗?你需要所有的类都有一个共同的基类吗?你需要接口可以继承吗?你为什么需要这些?

TRACKBACK

如果你想引用这篇文章,请复制下面的链接发送引用通告(GBK)
http://linode.codingnow.com/cgi-bin/mt/mt-tb.cgi/390

COMMENTS

太赞了。看完文章和评论,受益匪浅。

看东西的层次问题。
面向对象是帮助人来理解代码的方式。
就象我看见灯 
我只需要知道:我一拉它就亮。

我不关心他是什么样的灯 在客观世界就是有各种的标签 这些标签形成了我们的认知。

不明何谓“减无可减”。
代码量?
数据量?
还是接口规模?
--
只知3NF,5NF等早已对某些东西有所指明。

唉,我们这些浅薄的程序员,也不过是讨口饭吃,也许是我意志薄弱,曾经想成为高手的想法已经不知道藏哪里去了

所谓的设计模式,n多类其实在直接和OS打交道的领域里,都是垃圾

@ghost

这样看来我和你的看法又没什么大的出入。只是我说得没你那么详细而已。
曾经也在改别人的错误,也曾自己获过错误,后来是被逼着去重复错误,接着是辞职,呵呵。不过这样的公司还真不少:(
那现状如此,除了一气走人,坚持走自己的路,我们于大环境又能改变什么呢?
或许真的没那些有着花哨名词的新技术,会多几个潜心修行的开发者。

看ghost的发言,让我有一种泄愤的快感:)

但是,从概念上讲,让两个不相关的接口相互转换是不合逻辑的。本质上,其实在不相关的接口间转换做的事情等价于:从一个接口中取得对对象的引用,然后调用这个对象的方法,取到新的接口。


有趣的是,对于COM来说,不光“本质上”类型转换等价于方法调用,“实际实现”也是如此。

好的设计?
那么什么才算是好的设计呢?
高效?简洁?扩展性?维护性?
评价的标准似乎很多。但是那似乎也只是理论而已。
设计人对项目的理解和把握,曾经的项目经验,甚至学习经验。项目本身的要求?

“正因为设计如此重要,所以必须禁止外行染指这个领域。”
“禁止”是人为的壁垒,而不是知识壁垒。

回 zen_yue朋友:

1、设计是最最重要的。没有好的架构设计,万字就要画一万横。
正因为设计如此重要,所以必须禁止外行染指这个领域。
这不是什么行业壁垒,而是知识壁垒。

20个线程读磁盘,真正懂得计算机、真正动手做过东西的一定会感到可笑,进而担心这个项目的命运。

不仅仅是数据结构和算法,UML、面向对象还有设计模式都是必要的好东西——飞机也是好东西;但绝不应让拉登等心智还不健全的原教旨主义分子接触。

 

2、如果你觉得Linus Torvalds居然像个小P孩般去争论语言的优劣,那么你也把他看得太低了些。

仔细品品他话里的味道吧。

明确点说,就是:C++和UML一样,是一种威力强大的好东西。但正因为它的强大,仅仅学会“用VB编计算器”的家伙就多了起来。

由于缺少对计算机真正深刻的理解,这些C++语言专家就觉得一切也不过如此,按照对象发现方法论把类啊模式啊往上一套,一切就都有了;甚至于有了相关知识后,他们还是脱离不了那些可笑的固定套路——这就是所谓的心智包袱。

必须明白:没有任何一种方法论可以告诉你“不能用20个线程读同时读写磁盘”以及诸如此类的其他东西。

如果法律执行严格,这些浪费了纳税人数千万的不称职的家伙,处境相当危险。

但显然,这些人的自我感觉还是非常良好的。从他们自称“白领”并且想用机器替代“蓝领”便可见一斑。
他们不知道,自己的一只脚就在牢门里放着。

能把一个好好的人整成这样,你说C++以及UML、设计模式算什么?

 


3、正因为人才难找,这才彰显能干活的软件“蓝领”的重要。

追加投入100亿,给他们100年,你觉得我说的那帮子“白领”能把东西做出来吗?

给你100万,但必须承担项目失败的后果;你愿意以“不修改高层设计”的前提接下那个“以O(N^2)效率存储用户信息、数据库存储程序状态却又让其他模块无限制访问、20线程玩磁盘、5000并发用户连接用5000个进程实现且5000个进程无任何锁自由访问(包括添加和删除!)同一块共享内存里的session、并且认为单核CPU根本就不可能出现并行因而不管多少线程访问同一块内存都不需要锁”的“白领”项目烂摊子吗?


一个破网上超市项目而已,不考虑用户界面,内部逻辑在云风这里可能就是一两个月;而且做出的一定还是通用内核(连我都觉得这是个半年单人干的活!)。

但那帮家伙楞是做了好几年,花了数千万!


没有人说方案不可以折中,不可以靠牺牲某些东西以绕开技术难点——相反,能够做到这个的,才配叫技术人才。

是的。企业不需要天才,他们只需要开发人员能把任务完成。

问题是:你用哪只眼睛看到,只要会画画UML、像“学用VB编计算器”一样玩玩对象发现,就能“完成而且低成本高效率的完成任务”?

那些在监狱门外徘徊的白领们的教训,还不够深刻么?


现在根本的问题不是什么“开发/设计人员的实力”,而是把草包剔除。

当这些草包滚蛋之后——只要有类似云风这样懂技术的主心骨在,把核心做了,剩下的直接上lua或其他脚本即可:这时候,对开发人员的素质要求才可能真正降下来。


——相反,当初在草包的手下,我们几个会干活的那可是名符其实的“救火队”:从数据库性能不足需调查原因、到莫名其妙的偶发crash(被我查出原因是线程退出次序紊乱)、再到“由于一点点设计疏漏,我们要帮另一个模块更新数据库状态”、继而“由于对方数据库负荷过重,那个更新导致我们的服务失去响应”(为这个,我不得不写了个自动管理线程及相关资源的小调度模块,以保证主逻辑里可以像函数调用一样完成数据库异步更新工作——并且这个模块的健壮性必须达到7×24小时级别;由于这个200多行代码写的模块太干净利落了点,导致另一个想当“白领”的家伙对我产生了警惕,从此时时处处给我下绊子!)……

这份“蓝领”的工作看起来如何?您拿得下吗?

 

人贵有自知之明。
对初学者来说,千万要明白画UML、玩面向对象、看设计模式等等花活和真正的项目设计之间的区别。
在工程师的世界里,一个算法可能都值得很多人研究一辈子;甚至他们的后人还要接着研究;或者,他会知道关于软硬件的一切,然后小心翼翼地引领团队绕开一个个陷阱:而为了这个,他需要懂得一切,甚至包括生物学(比如遗传算法、神经网络以及人眼人耳的物理原理及特性等等等等)——这些都和管理者的“浅薄(无贬义)”的世界在根本上是不同的。

不打算在engineer的世界里投入一辈子的,可能是好的engineer吗?

我是个新人,读了ghost的回复,觉得说的没错,但有些地方难以理解,接受不了。对一个软件难道设计不重要吗?除去说什么对象与模式的,至少也要设计个数据结构与算法吧。
对于我,虽然有用起来不喜欢的语言,但没有觉得什么是垃圾的语言。存在就有它的道理,或许只是你不需要而已。
人才是难找的,你不可能要求每个开发人员都有天才般的开发实力,但项目必须完成,有些东西就是折衷的方案。企业要的不是一个天才的团队,而是一个能完成项目,同时低成本,高效率(依靠某些工具或方法)的团队。一般都以设计做主导,如果设计出问题,无疑项目会一团糟,但假设设计没有问题,那项目就有可能接近理想。
所说的管理者与工程师的问题,哎,管理者不该涉及系统设计与程序的。项目经理应该只负责调度,当然如果他是个牛人,能说善听,精力旺盛,程序写得顶呱呱,兼个架构师的职位也没什么不可以。
发现是看的方向不太相同,似乎也没什么好讨论的:(
还是那句话,存在有它的道理。发现这个道理就知道该用在哪里。没发现前也用用吧,不用又怎么会明白其中的道理呢。用完,记得深思,审视。
嗯,看完,也提醒自己再审视一些东西。

Q1:你需要面向对象吗?
A1:需要,在设计时会使我的思路更加清晰,可扩展性可读性上都得到很大的提升。
Q2:你需要 GC 吗?
A2:需要。使我写代码时比较安心一些。
Q3:你需要所有的类都有一个共同的基类吗?
A3:通常时候会用大部分类继承于某一基类,原因如A1,良好的抽象的设计能很大程度上方便之后的工作。
Q4:你需要接口可以继承吗?
A4:是的。有接口,容易扩展,并且为若干时间后的补充提供一套规范。
Q5:你为什么需要这些?
A5:综上。
OO并没有错,是好东西。语言之争实在没意思的很,就象砍木头,愿意用锯还是愿意用斧头有什么区别。关键是使用工具的人怎么想。

说实话,感觉这篇文章,有点怪。对于“基于对象”“面象对象”这种咬字眼的东西实在不感冒。

你的心智,到能够继承它们的时候了吗?

好文共赏!受教了!

呵呵,我倒觉得,现在颇有些人以为拿ROSE画UML就是“面向对象软件设计”了。

事实上,所谓的“对象发现”、用例设计等等东西,和“跟我学用VB编写计算器”,在水平层次上毫无差异。

其实,虽然宣传起来吹得很大,rose还是相当清楚自己的定位的:一个专业程序员和普通用户间的交流工具。

用一位外国朋友的话来说就是:这东西是manager's world用来沟通user's world和engineer's world的。

 

用户基本没有关于计算机知识;他只能说出他的工作是什么;manager善于沟通,但对程序设计并不精通;engineer虽然精于程序设计,但往往并不善于与人打交道。

借助UML和用例以及对象发现,manager可以做出一个虽不比“用VB学编计算器”更高明、但至少不能算是外行的初步框架——这是对engineer来说的。
而对于用户来说,UML避免了engineer随口说出的术语,给出了一个虽然样式有点怪异、但毕竟不算难懂的模型。

于是,三方皆大欢喜,这事就这样成了。


但是,倘若manager学了个“VB写计算器”的方法,便以为engineer们的时代过去了,一切有他和机器足矣;那么大家就应该知道,是该给什么医院打个电话的时候了。

 

比如,我之前提的那个“每天50G以上日志;单个日志文件小于2M;每天定时分析此日志;消耗时间尽可能少”的需求,你拿UML+用例+对象发现 能捣鼓出什么?!

manager只要能确定如上需求,他就已经非常优秀了;但适可而止吧,再多走一步就是犯罪(现实是:数千万已经这样打了水漂了;而且显然还要继续投入更多的钱打水漂!)

相反,这东西在我们engineer手里,又怎么样呢?
我们马上就会想起,一次拖10个1G的文件到另一个硬盘可能需要10分钟;但一次拖一个文件,让10个拷贝操作同时运行,可能就要几个小时。
由我们的专业知识,很容易知道这是因为乱序访问磁盘,导致出现大量磁头寻道操作所致。
于是,正确的方案就摆在面前了。
(相反,那些玩过界的manager们搞了20个线程同时到磁盘上瞎玩——想想情况会有多可怕吧)


国外对这些区分的是非常清楚的。
所谓manager,他只是资源的管理者——资源当然包括人力资源在内。
但必须强调,他只是被赋予权力调度各种资源以尽可能高的效率完成工作,并不是engineer的上司:双方根本就不是同一个世界的人。

在国外,从engineer世界转到manager世界的人,往往是会被真正的engineer鄙视的。因为这说明他根本就不喜欢或做不了engineer的工作,在engineer的世界里没有发展前途。

(事实上,manager不过是个管家类型的人才;engineer才是真正可以被称作“学者”的。双方的社会声誉是相差极大的。不管做管理的做到什么程度,做技术的都能以一句“just a manager”噎得他喘不过气。)

 

说这些,我的意思当然不是说做管理的都是些没文化的家伙。
沟通是门艺术;在下就极不善于口头沟通,对嘴皮子厉害的人,当然是相当仰慕的。
——但艺术毕竟不是学术。

要说水深,再没有比学术淹死的人更多的了。

 

国内的情况大家都很了解,不多说了。

但有一个极其严重的问题必须再提一提:由于官本位思想作祟,我们的manager太具侵略性了。
这些家伙,和那个学会一横是“一”、两横是“二”、三横是“三”,便敢宣称“儿得矣”的小屁孩是一路货。

小屁孩揽下个写“万”的任务,险些把自己累死。
同样,我们刚学会“用VB编计算器”的manager也能搞20个线程把磁盘累死;搞个O(N^2)的算法处理千万级别的数据把数据库服务器累死;搞个大蜘蛛网把自己也累死——最后,倘若法律能更完善,被他们葬送的数千万恐怕已足以将此等人送上刑场;起码也得好几年牢坐。

但没关系。这里是中国。这里是软件“白领”们正要用机器替代软件“蓝领”的中国。

 

受这些脸皮足以挡子弹的家伙影响,准备先做几天技术然后转管理的家伙越来越多——原因嘛,管理人员早已远远过剩,能做技术的却是千百人中都挑不出一个(这是实话,没有半点夸张)。

所以,即使学个半吊子,也能混上个技术工作;干上两年——我们很多公司根本就没给做技术的准备升职路线——自然就升职做管理了。

另一方面,为避免其他做技术的抢到自己的位置,他们自然要大力宣传“蓝领”论,拼命打压真正做技术的。

 

在这种浮躁的气氛下,大量涌现只会写一二三的小屁孩,也就不足为奇了。

毕竟,死记硬背几条C++特性,要比彻底理解计算机软硬件原理、理解算法原理以及相关的数学甚至物理知识,要容易太多太多了。

PS:Linus Torvalds骂的不是C++,而是学了几条C++基础知识就不知道天高地厚的小屁孩;是那些学会“用VB写计算器”就自以为是软件白领的人:

C++是一种糟糕的(horrible)语言。而且因为有大量不够标准的程序员在使用而使情况更糟,以至于极容易产生彻头彻尾的垃圾(total and utter crap)。老实说,选择C就是为了把C++程序员踢出去。……我有这样的结论,任何喜欢用C++而不是C开发项目的程序员可能都是我希望踢出去的人,免得他们来搞乱我参与的项目。C++会导致非常非常糟糕的设计选择。你们这些C++程序员总是一上来就用语言的那些‘漂亮的’库特性比如STL、Boost和其他彻头彻尾的垃圾,这可能对你们的程序有所‘帮助’,但是却会导致:

“——当库无法工作时无穷无尽的折磨(别跟我说什么STL尤其是Boost很稳定而且可移植性很好,那全是屁话,而且一点都不可笑)

"——低效的抽象编程模型,可能在两年之后你会注意到有些抽象效果不怎么样,但是所有代码已经依赖于围绕它设计的‘漂亮’对象模型了,如果不重写应用程序,就无法改正。


”也就是说,使用优秀的、高效的、系统级的和可移植的C++的唯一方式,最终还是限于使用C本身具有的所有特性。项目限制只用C,意味着参与的人不会捣乱,也意味着会得到许多真正懂得底层问题,而不会折腾那些白痴‘对象模型’垃圾的程序员。

"所以,我很抱歉,但是对于Git这样效率是主要目标的软件,C++的所谓优点只是巨大的错误。而我们将看不到这一点的人排除在外却成了一个巨大的附加优势。

"如果你想要用C++写的版本控制系统,去玩Monotone吧。他们确实使用了‘真格的数据库’,使用了‘漂亮的面向对象库’、使用了‘漂亮的C++抽象’。可是说老实话,所有这些对某些计算机专业人士而言富于吸引力的设计决定,其最终结果确是一堆可怕、难以维护的垃圾。“


尤其是这些:

唯一真正重要的部分是设计。

"你当然可以用任何语言编写糟糕的代码。但是,有些语言,尤其是带有一些心理(mental)包袱的语言本身就非常糟糕。你这样的新手跑来指出一些绝对无关紧要的补丁特性,用它们作为一种语言优越的论据(这些东西语言原作者都不喜欢),这一事实本身恰恰说明你满脑子都是糊涂概念,应该好好醒悟一下了。

不仅指语言本身,还包括一种必需的心态(mentality)。C最大的优点之一,就是它不会使你认为程序是什么高层的东西。正是后一种心态会使你明显偏向其他语言,但实际上从Git的角度看来,所谓 ' 高层 ' 恰恰是错误的。"

 


其实,不光是C++;面向对象、UML以及新近晋升为祸害的设计模式,不都是这样吗?

举例来说:打开老爸的工具箱,你会发现钳子、扳手、刀子、电锯、机油甚至硫酸、剧毒杀虫剂和极易爆炸的氧炔焊接装置。

你的心智,到能够继承它们的时候了吗?

"我想,只用 C++ 写程序的人最容易犯的错误就是认为 C++ 对面向对象的支持的实现本身就是面向对象的本质。如果真的理解了面向对象,在特定需求下可以做出特定的结构来实现它。语言就已经是次要的东西了。"
===>
我喜欢这句话.

简洁清晰,一般来说我会这样要求自己设计。如果无法一目了然的了解程序在做什么。那么一般我会换一个方式来思考。unix其实设计得很精妙,设计模式说白了在很大程度上是在用面向对象的方式实现unix在几十年前所提出的那些关于软件设计的精神。

为了避免误解,小心翼翼地, 我强调,这是指参与的讨论而言,而不是文章本身

剥离了在应用和工程中创造的无数拗口生僻的名词, 所有的概念基础存在于学校课本里,存在于数学书中,学生应该掌握,

面向对象谈论这么多年, 似乎工程师谈论的都是具体语言措施里的实现, 反复, 没有理论的一个概括.

表面上, 面向对象方法,设计模式, 统称为“方法论”, 奇怪的名词,这些东西看似一半的理论,给人以无数著书立说的可能, 因为讨论方法嘛,没人说对错,

对啊, 面向对象, GC...你为什么需要这些, 工程师们,处于一个缺乏理解的时代,

编程模式越来越纯粹, 相关的理论基础早以存在,却一直没被工程师理解而已, 一切美好的东西, 淹没在工程的复杂性里面

毫无疑问,这种几乎属于玄学的讨论,吸引了最多人的讨论, 因为很难有硬伤:)

有一个问题,你的blog在屏幕上怎么只有那么一点点宽,能不调到0.618那个范围,不然看起来有一点儿不爽,不过blog内容还是有趣的

你需要面向对象吗?
你需要 GC 吗?
你需要所有的类都有一个共同的
你需要接口可以继承吗?
你为什么需要这些?

非得不用,非利不动,非危不>

如果对程序设计而言,能够减少耦合,提高内聚,增加稳定性,减少代码量及资源占用的设计就是好设计。实现这些目标有N种方法,前人不断实践与总结,所以有了函数,结构,面向对象……各有各有好处,各有各的应用范围。最近做些东西,发现在C++中,有些实际情况坚持应用某一方法是不太理想的,或许得看需求,舍弃一些设计上的统一。我比较向往灵活性与安全性,但对资源占用并不很在意,除非项目明确规定,运行在某某平台上。因为软件要向前发展,硬件也是,如何让软件更上硬件发展的脚步,保持原来软件的灵活性很重要。基于这样的考虑,接口应用是一种不错的实现手段。方便,直观。而谈到设计层面来,似乎可以是语言无关的东东,当你设计完你的系统,再根据性能需求选个工具来开发,如果选了C++,再审视一下设计,发现有个GC不错,那么就做个GC吧。其实程序跑起来,硬件也只需知道数据在那,指令在那也就行了。N多方法只为了方便我们的开发与维护。明确目标选工具,而不是拿个工具来套目标。愚见!

我对OO的理解和云风差不多,就是OB+多态,便于以相同方式遍历操作相似的东西。

囧……有个问题……
有多少人调查过到底有没有方形的或者非圆形的下水道盖子?

@Zenberg

GP愚以为并不是OO的补充,范型编程其重中之重是一个“范”字,编程已是其次,“范”明显的代表了抽象的意味,如果在C上去作泛型编程,大概亦只能用void*作接口,但丝毫不影响其实现。现在我比较喜欢用接口这个词,其本身就有一种抽象的意思。诚如贵言:“linux对待不同文件系统的实现的接口设计和collection framework抽象不同行为模式容器的接口设计实在是异曲同工。”,抽象出接口后,C写就的linux kernel和以Java写就的collection framework如何实现已不重要,本人愚见,这就是所谓的泛型编程(GP)。

确实,一种语言会对程序员产生导向。但是作为一个程序员,不是应该把握好各种导向,站在更高层次,构思抽象,充分利用各种语言的特色吗?当然混合各种语言的编程是天方夜谭,但是可以充分利用接口的功用,结合不同的语言,例如C/C++与LUA脚本的结合,愚以为亦是GP的一种表现。

我觉得,作为一个程序员应该去发挥各种语言的特色,而不是去矮化各种语言。

@Cloud

我也不想探讨设计模式,因为我实在没有发言权,我举例不过为了说明抽象的重要性,实现是其次的。

“那么,怎么提取这些共性。”“重要的是理解你的需求,判别哪些是真正的需求,哪些是不必要的需求。”
大概这些就是抽象的工作了,用什么实现这里一点都不重要。

“举例,GP 也是一种抽象的手段,但 GP 不是 OO 。GP 的抽象主要解决的是在不同的地方用相同的算法去处理不同类别的东西。

而 OO 做的是什么呢?OO 做的是把不同的东西归类在一起,在同一地方处理这些东西具有共性的部分。这就是多态。”

按照我的理解,方法和数据都是有“接口”的,因为方法期望合法的数据,所以数据也需要提供访问的接口,在C语言中,你可以提供一个方法的接口或者一个数据的接口,但是在OO中,你可以拥有方法和数据的共同体。两者抽象的本质却是没有分别的。

===================
本人才疏学浅,见笑了,还望指教。

并非任何软件搭建都会强调抽象和封装的,软件危机的原因产生大概就在于此。

OO的好处是强制你去进行抽象和封装,至少会让开发者去在这方面做思考。其实我们尽可以去用Java写Procedure形式的程序,也可以用C去OO,当然这并不是问题的关键。

GP与OO并不矛盾,就如楼主所说,只是不同角度而已,我个人觉得GP是对OO非常好的一个补充。

以本人有限的认识,我觉得以C写就的linux kernel和以Java写就的collection framework都是令人击节的OO实践杰作。

linux对待不同文件系统的实现的接口设计和collection framework抽象不同行为模式容器的接口设计实在是异曲同工。

再,我个人认为你对封装和抽象的理解有问题,并非问题粒度上的事情。

抽象是为了对各类需求进行分门别类的管理。

封装是为了隐藏实现的细节,进而达到抽象的目的。

@joe wulf

我举鼠标选取的例子,不是想探讨设计模式,我认为模式固然有用,但是大多数情况下会让我们忽略本质。这点我跟 ghost 的看法近似。

那么我想说明什么?

在这个例子里,我们的本质需求是:可以需要让不同的对象可以用统一的途径去检查是否捕获住鼠标。只要满足了这个,就可以把这些对象放在一起来处理。这就是 OO 在这个问题上作用。

至于之后怎么办,无非是顺序、分支、循环而已。我们不需要看到什么模式,因为要处理的事务和数据的粒度已经足够粗了,基本的算法就能搞定它们。

那么,怎么提取这些共性。COM 的 QueryInterface 就是描述的这个问题。字面的意义解释的恰到好处。至于如何实现它,用继承只是解决方案之一。当语言提供了某种便捷的语法手段时,我们就倾向于把实现手法偏向于它。所以语言本身就对程序员的思维造成了导向。

margin-top: 10px; margin-bottom:

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics