怪怪 | Nothing, Everything

"有过一个发疯的时刻,有感觉的钢琴以为它是世界上仅有的一架钢琴,宇宙的全部和谐都发生在它身上." - 狄德罗
随笔 - 101, 文章 - 3, 评论 - 1996, 引用 - 42
数据加载中……

一些待解的疑问

想了想, 还真不知道拿什么题目起头。 这样, 从以前的文章开始好了。

为什么OO是有本质缺陷的?


这篇文章中的疑问首先有这么一点: 静态语言中,我们如何能在改变一个系统内部接口的时候(注意, 不是对外发布的, 所以没有不能更改的问题), 只更改一处就解决问题? 比如最简单的, 一个类, 有Name属性, 是string的, 它对应某一个数据文件里的类似于表中一列的信息。 改变数据文件的结构,新添加了一个叫做Description的记录信息, 一个内部实体也增加了这个属性,我如何做到不修改从数据文件中读取, 和写入数据文件的代码呢?

毕竟, 这两个属性对这个数据文件的读写, 是没有什么差别的。举一个对比的例子, 在C++中, 我可以这样:

namespace fields
{
    
struct name;
    
struct age;
    
struct code;
}


typedef map
<fusion::pair<fields::name, std::string>, fusion::pair<fields::age, int>, fusion::pair<fields::code, char> > person;

使用时,我们这样使用:

person a_person;
at_key
<name>(a_person) = s;
at_key
<age>(a_person) = i;
at_key
<code>(a_person) = ch;

事实上, 这是使用fusion,稍微更改一下形式, 就可以变成这样: a_person.p<name>, a_person.p<age>。如果碰见变化, 修改一下typedef即可。 而我操作person的代码,只要其本身的逻辑没有变化,就可以做到一字不改; 因为我可以通过获取map中所包含的类型定义携带的信息, 直接写一个统一化的过程, 进行所有操作。 而如果使用OO, 第一个可以想象的就是, 每一个倒腾数据的逻辑, 无论是从哪儿到哪儿, 我都得加上对该属性的操作。

这个最大的好处是,只要在本质上是相同的过程, 我们只用写一遍。 另一个好处是, 我们同时具有静态语言的全部优势: 比如没有定义和包含description的时候, 无论你是at_key<description>,还是a_person.p<description>,根本就不会通过, 这样在非常大量的这种工作, 比起Dictionary和动态语言, 我们就可以避免大量的失误。

我想, 这个问题不能简单的用“很少有人用”来回答,因为它是结果。 首先它是方便的,而且方法名、属性名这种给人使用的死标记没有的缺陷它也没有。  那么我认为,没人用更多的仅仅是因为, C++和另外那些支持这种非OO范式的静态语言,其它地方太烂,是首先否定了语言上的选择, 所以也就没人在实体上使用这种设计和实现的方式。

当然使用Dictionary就痛快多了, 不过强类型带来的保障没了,这是不是缺陷呢?还可以使用反射完成相同的功能, 然后付出性能, 在我看来,这个性能就是缺陷的证明; 比如: 数据源是数据库, 那么有的ORM就用反射完成类似的工作, 但ORM的存在,反而证明了需求的存在。而且在ORM覆盖范围以外的数据复制和转移呢? 性能问题, 我们可以通过Emit来解决, 但Emit不是适合于所有使用情景; 而且, 我们就必须编写和调试大量的Emit代码, 额外的设施的使用和多付出的工作量, 也是缺陷的证明之一。

毕竟, 这些信息本来就是运行前已知的, 而且他们是有规律的, 也就是可以通过某种形式在运行前处理的, 同时可以通过合理表达自动化的。某人嘴里的“孟老头”对这个事情有他自己的理解, 现在就看某人的啦: 这是不是OO的缺陷?

posted on 2008-07-17 12:16 怪怪 阅读(172) 评论(18)  编辑 收藏

评论

#1楼    回复  引用  查看    

不要怪我抢沙发,我实在不乐意看到你还这么乱搞,差不多就收手吧,犯得上吗?
2008-07-17 12:30 | 丁学      

#2楼    回复  引用  查看    

晕,文章还没出来沙发就被占了...
2008-07-17 12:30 | 狼Robot      

#3楼    回复  引用  查看    

这里会很热闹。稍等...
2008-07-17 12:32 | 迭戈      

#4楼    回复  引用  查看    

午餐时间,我已经给你发消息了,有时间加下我.

不知道1楼说的乱搞是啥意思....
2008-07-17 12:32 | 狼Robot      

#5楼    回复  引用  查看    

@狼Robot
一楼消息已经经过部分加密处理,请勿随便破解,以防CPU爆炸
2008-07-17 12:34 | 丁学      

#6楼    回复  引用  查看    

冲动是魔鬼
2008-07-17 12:42 | 无名的小卒      

#7楼    回复  引用    

怪怪想表达什么呀?
2008-07-17 13:03 | 7支火柴 [未注册用户]

#8楼    回复  引用    

@7支火柴
除了表达自己是个有特立独行思想的人之外什么都说明不了,就这种形而上的玩意,跟大学教授争论个理直气壮倒不错,这种学问跟回字有几种写法有什么本质区别吗?
2008-07-17 13:27 | 纸毛巾 [未注册用户]

#9楼 [楼主]   回复  引用  查看    

@纸毛巾
大哥, 这就是你给我解惑的方式呀...

这个东西用起来很实际的, 我在一些可以选择C++的方案里用过,才产生的感受。根本不是你说的形而上学的东西,也不是为了说明实体有几种设计方法....

我只是说, 一般OO语言和OO设计中, 不包含这种方法, 让人很郁闷。
2008-07-17 13:32 | 怪怪      

#10楼    回复  引用    

@怪怪
你的惑就是不知道你自己所醉心,关注,自以为得的东西都是些完全没用的玩意。如果说别人的博客内容看完让人有长进,你的博客让人看完除了研究针尖能上能站几个天使一类的问题之外,几乎没别的内容。
2008-07-17 13:40 | 纸毛巾 [未注册用户]

#11楼 [楼主]   回复  引用  查看    

@纸毛巾
这个问题我觉得吧, 总得有人关注这些, 否则连OO都不会有。 我不会愚蠢到认为我能创造SmallTalk, 但是如果社区里完全没有做这种讨论的, 就是好事吗?

而且,我只是提出我经历过的, 而且绝对实用的写程序方式。 我也不只一次的说过, 既然主要工作还是用C#, 我也没办法, 但是我至少可以说出我想要的吧。

当然我也会逐渐尝试,就像你说的, 我能力不足, 所以还得不到好的结果来; 但是也许你不想成为框架、语言的发起人, 但是我想; 而我有没有能力做是另外一码事。

哪怕我是光说不练假把式,人总是可以有愿望的,何必打击我呢?
2008-07-17 13:49 | 怪怪      

#12楼    回复  引用    

@怪怪
你美你的,我们说我们的,大家本来不是一路子,也许在考虑这些学术问题上您有思考,您独到您特立独行。但是跟社会上办点事您那点特立独行就别拿出来了,简单的说,您那思想高度和行为模式略微和现在商业社会大环境不合拍,所以您可以跟您自我干良好的领域随便说,但是您在您不擅长的领域说了傻帽的话,就应该允许别人说您傻帽。
2008-07-17 14:08 | 纸毛巾 [未注册用户]

#13楼    回复  引用  查看    

当限定了一面,另一面就肯定会有缺陷。
正因为oo是静态的,才导致它不能获得动态的好处,相反也成立。

举个另外的例子
分层大伙都知道,因为分层限定了它的调用只能是单向的。所以有时候我们需要下层调用上层。这问题就出现了。解决的办法也就是回调,Observer
而MVC提供的好些。
想ms那个petshop挺流行的,但是很显然违反了分层原则,如果不使用反射的话,也不至于那么流行吧。

我觉得没有完美的,就看怎么权衡。
2008-07-17 14:13 | bmrxntfj      

#14楼    回复  引用  查看    

这么说吧,我看到这篇文章之后我至少会:去用C++比划一下,看看这种抽象力来自于何处。并且思考为什么商业型语言C#和Java没有这种抽象性。它在语言层面还是在VM层面。我能不能改变编译器引入这种抽象性。能否用动态语言的特性来代替它以达到相同的目的。

而不是:说楼主研究的东西没用,说LZ傻等等。因为这样做没用,什么也没有创造,什么也没有揭示,真的没用。

怪怪的思考容易缺乏实践的支持,容易在深入之前停止,但他也能经常发现别人忽略的地方。能够受此启发继续研究和思考;和批评其自我感觉良好,或者学术性之类不相关的莫须有缺点,哪个更有意义?
2008-07-17 18:01 | 装配脑袋      

#15楼    回复  引用  查看    

@guaiguai
对于oo,我也就是知道个表面,没有去了解它的历史发展过程,这些我觉得都是值得去研究下。应该跨越几个范型才能看到点门路。@laodai 很想听你说说编译器方面的。
2008-07-17 18:33 | bmrxntfj      

#16楼    回复  引用  查看    

@bmrxntfj
像这么declarative的东西可能已经超出了OO的能力,OO讲究的是将数据和方法封装在一起,以及运行时的多态。而数据实体似乎不能看成是一个孤立的数据,而是广阔数据的一小部分,一旦用OO的做法封装,就限制在OO所定义的封装方式(数据+方法),而不能表达数据之间真正复杂的关系。

我觉得泛型、函数式编程在表达数据之间的关系方面比OO更灵活。而泛型的主要抽象力来源——特化和偏特化其实是模式匹配的语义。这些东西为什么结合起来就有如此威力,他们有什么运用的模式,都是非常值得仔细思考的。在.NET编译器层面无法实现泛型的特化和偏特化,因为泛型是在JIT阶段构造化的。但是Ruby有一套不错的元编程特色,没准是解决这个问题的另一个有参考价值的案例。
2008-07-17 20:29 | 装配脑袋      

#17楼 [楼主]   回复  引用  查看    

@bmrxntfj
呵呵,我能力有限,还无法做到深入浅出, 就像脑袋说的, 这些东西自己试一试, 也许会比我说明白。 面向对象碰到静态强类型, 这缺陷是必然的, 而引入其它的范式是可以配合解决的, 这就是我拿出来说的意义, 而不是一味的鞭笞和哗众取宠。

占了一种好处, 就占不了另一种,这种看法也不是处处成立的。 首先具体到眼前的问题上, 很多人是有实践的。 其次, 这种说法, 其前提条件是很模糊的。 如果一个事情是10分,现在只做到3分, 那还不到说这个取舍的时候。 同时, 还是要看系统是封闭的,还是开放的。

@装配脑袋
你说的对, C++/CLI那种VM外加代码生成, 接口的兼容性就没了。 而且还有另一个方面: C++ Template式的源代码库, 比起动态库, 虽然写程序时灵活了, 在同一个平台上,和DLL相比却缺乏了运行时的灵活性。 所以我在使劲儿想, 到底怎么办好。

Ruby的问题, 就像你几年前跟别人说的, 我现在还认为, 运行前就知道的事情,还是写代码时和编译期就给做了好; 交给运行时, 然后正确性依赖于测试, 这个....
2008-07-18 03:04 | 怪怪      

#18楼 [楼主]   回复  引用  查看    

@装配脑袋
另外, 孟岩那天跟我说, 没几个人会愿意对着T写代码, 真的是这样吗? 我怎么体会不到呢...,不过他对各种程序员应该是有广泛接触的。
2008-07-18 03:11 | 怪怪      

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-07-17 13:40 编辑过


相关链接: