精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-07-03
代码重用并不是OO设计的目的,而是好的OO设计导致的必然结果,OO设计的目的是为复杂系统建立正确的对象关系模型,其工作包括以合适的粒度将系统分解为合适的对象元素,并为这些对象元素建立合理的关系模型。好的OO设计确实能够达到所宣称的效果,但差的设计则完全是另外一回事。
OO设计并不会使我们的设计工作变得更加简单、更加容易或者让菜鸟更快上手,实际上恰恰相反,OO设计是从来都是复杂的,困难重重的,尤其是大型的系统框架设计,经历过无数次的失败之后你就会很清楚的意识到这一点。但是一旦获得优秀的OO框架设计,其所能产生的效果绝对是达到数量级的影响。我不怀疑庄某的新思路会有出色的地方,但是没必要以批评现有OO理论的某些缺陷来为自己做铺垫。关于OO设计的理论缺陷,庄某的某些批评甚至可以说不够深刻,寥寥几段话光说道理是不够的,一定要摆事实,最好上实例,不要只做纸上谈兵之举。 文章到底是要教导如何避免错误的OO设计呢,还是要否定OO另起XO炉灶?如果是前者的话,不如改成如何正确的进行OO设计会更有吸引力,如果是后者的话也没有必要反反复复的去列举只有菜鸟才不了解的事实,卖关子也不要卖太久了。 |
|
返回顶楼 | |
发表时间:2005-07-03
age0 写道 代码重用并不是OO设计的目的,而是好的OO设计导致的必然结果,OO设计的目的是为复杂系统建立正确的对象关系模型,其工作包括以合适的粒度将系统分解为合适的对象元素,并为这些对象元素建立合理的关系模型。好的OO设计确实能够达到所宣称的效果,但差的设计则完全是另外一回事。
OO设计并不会使我们的设计工作变得更加简单、更加容易或者让菜鸟更快上手,实际上恰恰相反,OO设计是从来都是复杂的,困难重重的,尤其是大型的系统框架设计,经历过无数次的失败之后你就会很清楚的意识到这一点。但是一旦获得优秀的OO框架设计,其所能产生的效果绝对是达到数量级的影响。我不怀疑庄某的新思路会有出色的地方,但是没必要以批评现有OO理论的某些缺陷来为自己做铺垫。关于OO设计的理论缺陷,庄某的某些批评甚至可以说不够深刻,寥寥几段话光说道理是不够的,一定要摆事实,最好上实例,不要只做纸上谈兵之举。 文章到底是要教导如何避免错误的OO设计呢,还是要否定OO另起XO炉灶?如果是前者的话,不如改成如何正确的进行OO设计会更有吸引力,如果是后者的话也没有必要反反复复的去列举只有菜鸟才不了解的事实,卖关子也不要卖太久了。 我恰恰认为,OO的本质,阻碍了代码重用。为了改变这一事实,OO的后续演变才会是那样的一个过程...... 这正好是我明天要写出来的内容。 我也不是要卖关子,至少这样“一种观众体验”,不是我想要的效果。 |
|
返回顶楼 | |
发表时间:2005-07-03
关于“泛型”
http://spaces.msn.com/members/zbw25/Blog/cns!1pA6-3FOo9yNp_4lmEHxdDqA!277.entry |
|
返回顶楼 | |
发表时间:2005-07-03
泛型和子类型多态都是多态的实现形式之一,一般意义上的泛型,是指支持泛化参数的编程范式,它出现的目的主要是解决静态语言中的代码复用问题。
java并不真正支持参数化多态,最主要的问题是没有操作符重载。java在jdk1.4之前,只支持子类型多态。 在静态语言中,参数化多态与子类型多态互有长短,如果参数类型会在运行时发生变化,就只能使用基于动态绑定的子类型多态。 选择参数化多态还是子类型的标准是,参数会不会在运行时发生变化。C++两种方式都支持 |
|
返回顶楼 | |
发表时间:2005-07-04
引用 泛型背后的模板机制是一个很好的技术,但是受到OO的拖累,并没有发挥其应有的功效。
庄老这里最好明确一下所谓的“拖累”,OO不仅仅是Java那样子类等于子类型的OO,还包括子类不等于子类型的OO,这样就牵扯出来所谓的protocol来 ajoo曾经想要使用protocol来完善C++的模版机制来着 推荐庄老去找ajoo研究一下protocol,看看是否还是受拖累 |
|
返回顶楼 | |
发表时间:2005-07-04
age0 写道 代码重用并不是OO设计的目的,而是好的OO设计导致的必然结果
我完全同意age0关于重用的看法,我在前面对<<丧钟>>的观点疑虑中也提出了类似的看法。 庄表伟 写道 假设Class A有两个属性和两个方法:String a1;int i;void f1();void f2();当我们另外写一个Class B去继承Class A的时候,我们可以继续使用某些属性,而覆盖另一些属性,还可以继续使用某些方法,而重写另一些方法。还可以添加一些新的属性,还可以添加一些新的方法。如果在加上各种访问控制符的限定与修正。谁能够告诉我:“这个Class B究竟想干什么?!” 对于OO的继承性,庄子和其他一些人举出了矩形和正方形这个经典的例子来说明OO问题的存在,这个问题的存在对于在形而上学的系统当中的确是有问题的,但是有些研究认为OO中的继承不仅可以表达形而上学继承的模型,而且能够表达达尔文进化论概念中的继承,这种继承就是一种可以完全覆盖父辈方法的继承,一个明显的例子就是人类的行走和其祖辈的行走,都是行走但是我们却采取了完全不同的方式,我们覆盖了我们祖辈的行走方式,而这并不是OO“发明的”,我们为何要将自己局限在形而上学的分类系统当中呢?为什么我们不能认为不满足LSP的继承是OO所具备的对客观世界多样性的一种表述能力呢?。 庄表伟 写道 这就是号称优雅的解决了OO继承问题的Eiffel语言。他所谓的优雅,可以不客气的说,就是把所有的麻烦都明确的告诉你,而不是像C++和Java那样,假装什么事情都没有发生过。但是,麻烦依然在那里,并没有减少,根本的解决方法,是应该不让这样的麻烦出现呀!可是OO确实无法做到这一点 age0 写道 OO设计并不会使我们的设计工作变得更加简单、更加容易或者让菜鸟更快上手,实际上恰恰相反,OO设计是从来都是复杂的,困难重重的,尤其是大型的系统框架设计,经历过无数次的失败之后你就会很清楚的意识到这一点。但是一旦获得优秀的OO框架设计,其所能产生的效果绝对是达到数量级的影响。 OO是用于表达客观世界的模型和思考方法,这种麻烦正是客观世界的多样性决定的,如果我理解正确的话,这就是age0所表达的观点之一。OO提供的是一种思考和描述问题的方法,OO并不担负也不需要担负对模型正确与否检验。是否能够正确地应用这个工具是domain expert 和开发者的resposibility。 |
|
返回顶楼 | |
发表时间:2005-07-04
继承、多态与泛型冲突的一个例子
http://spaces.msn.com/members/zbw25/Blog/cns!1pA6-3FOo9yNp_4lmEHxdDqA!278.entry |
|
返回顶楼 | |
发表时间:2005-07-04
引用 OO是用于表达客观世界的模型和思考方法,这种麻烦正是客观世界的多样性决定的,如果我理解正确的话,这就是age0所表达的观点之一。OO提供的是一种思考和描述问题的方法,OO并不担负也不需要担负对模型正确与否检验。 我也有同感,age0的许多观点在我看来是正确的。例如,好的OO设计是困难的。在某种意义上,它往往正好反映了问题固有的复杂性和深刻性,要求你做出全面的考虑。 前面firebody指出了庄某对于抽象类和接口的认识问题,我也感到庄某可能在这些方面缺乏深刻认识。我曾经这样想过,若有人要求我用极简练的话说出这些年来学到什么,或者体会最深的是什么,我的回答可能是:抽象。 在我从事五六年开发经历之后,有一天我明白了“面向接口编程,而不是面向实现编程”的深刻含义。然后发现我以前写的一些引以自豪的代码的脆弱。随后的一两年,我愈发清晰地认识到这一点。Robert Martin的“依赖倒置原则”,也表达出相似的含义。不过这里我还是想对初学者说,做你自己理解的,认为对的事情,就可以了。我以前的道路错了吗?我不认为。重要的是你在进步,通过你的思考和实践。 抽象类是极有价值的。当然接口也很重要。接口是一种极至的用法,完全通过“行为”来刻画对象。把抽象类视作代码重用的手段,是狭窄的认识。要从概念内涵来认识。我们为什么要设计和使用抽象类?简单说,因为它允许、包容着演进的可能性(也许不久就要发生)。 庄某关于多重继承的几句话说的有点意思。几天前,我看到了去年的Trustno1等人讨论的接口和继承的贴子,里面也谈到了这个问题。对此我的看法是,Java不支持多重继承,是个遗憾。的确,可能很难回避多重继承的需要(这里指多实体继承)。它不是其它方式(如Java中的多接口继承)所能完全取代的。也许单继承已经够麻烦的了,何况多重继承。多重继承毫无疑问非常困难。在理论或技术上,最主要的困难是什么?我不知道。若我能知道一点,显然,需要花大精力去研究它。多重继承直观上有不自然的地方,理论或概念上可能确实存在困难(技术上可能也存在困难,但也许是次要的)。在C++中,我看到的一般实现也不太自然。但是话说回来,我们很可能确实需要它。 |
|
返回顶楼 | |
发表时间:2005-07-04
庄表伟 写道 如果listy能够被转型为ArrayList<X>,那么就可以往里面添加Y2类型的对象了,这又是原来的泛型ArrayList<Y1>不允许的。也就是说:除非addListX能够保证只对listy1做只读操作,否则,类型安全性这个泛型原本要追求的目标就不能实现了。而如果要追求绝对的类型安全性,像C++和Java那样,那么代码要么就得写三遍,要么X、Y1、Y2类型的对象就得都放到ArrayList<X>这样的泛型容器里去。
你给的这个例子不用写三遍,我们只要写成 public <T extends X> void addListX(ArrayList<T> listx);{ for(int i=0;i<listx.size();;i++);{ T x=listx.get(i);; x.add(1);; } } 那么就可以保证类型不“走样”了,不知道我是否理解了你的本意。 |
|
返回顶楼 | |
发表时间:2005-07-04
tomswan 写道 我也有同感,age0的许多观点在我看来是正确的。例如,好的OO设计是困难的。在某种意义上,它往往正好反映了问题固有的复杂性和深刻性,要求你做出全面的考虑。
前面firebody指出了庄某对于抽象类和接口的认识问题,我也感到庄某可能在这些方面缺乏深刻认识。我曾经这样想过,若有人要求我用极简练的话说出这些年来学到什么,或者体会最深的是什么,我的回答可能是:抽象。 在我从事五六年开发经历之后,有一天我明白了“面向接口编程,而不是面向实现编程”的深刻含义。然后发现我以前写的一些引以自豪的代码的脆弱。随后的一两年,我愈发清晰地认识到这一点。Robert Martin的“依赖倒置原则”,也表达出相似的含义。不过这里我还是想对初学者说,做你自己理解的,认为对的事情,就可以了。我以前的道路错了吗?我不认为。重要的是你在进步,通过你的思考和实践。 抽象类是极有价值的。当然接口也很重要。接口是一种极至的用法,完全通过“行为”来刻画对象。把抽象类视作代码重用的手段,是狭窄的认识。要从概念内涵来认识。我们为什么要设计和使用抽象类?简单说,因为它允许、包容着演进的可能性(也许不久就要发生)。 庄某关于多重继承的几句话说的有点意思。几天前,我看到了去年的Trustno1等人讨论的接口和继承的贴子,里面也谈到了这个问题。对此我的看法是,Java不支持多重继承,是个遗憾。的确,可能很难回避多重继承的需要(这里指多实体继承)。它不是其它方式(如Java中的多接口继承)所能完全取代的。也许单继承已经够麻烦的了,何况多重继承。多重继承毫无疑问非常困难。在理论或技术上,最主要的困难是什么?我不知道。若我能知道一点,显然,需要花大精力去研究它。多重继承直观上有不自然的地方,理论或概念上可能确实存在困难(技术上可能也存在困难,但也许是次要的)。在C++中,我看到的一般实现也不太自然。但是话说回来,我们很可能确实需要它。 很多OO程序员在最近这几年里,都有“脱胎换骨”、“醍醐灌顶”的感觉。因为OO原则,设计模式这样的东西出现之后,很多人看到了“OO复用”的希望,而这本是面向对象早就答应了要提供的东西。 在看到复用的希望之后,大多数人并没有停下来想一想,OO原则是OO的本意吗?设计模式是一种进步吗? 大约在两年前,我看设计模式的时候,也一样的欣喜过,看到精辟总结的OO原则时,也似乎顿悟过。但是,我的思考并没有就此停止,我的内心一直存在一个疑问:“这些所谓的发展,怎么这么‘逆天而行’呢?怎么这么‘违反常识’呢?或者说,如果OO复用要搞得这么High Level才能掌握,OO岂不是离那个想要直观描述的现实世界更远了吗?” 从抽象类到接口,不只是一个纯虚类那么简单,而是从代码的重用变成了接口的重用。这样的重用,本来并不应该以接口的形式出现的。因为接口作为一个扁扁的类型,依然和类型有着千丝万缕的联系,这就是副作用。而我们真正需要的,其实只是接口编程方式带来的“Design By Contract”的设计方式。我们需要这样的设计方式,而目前采用接口这种技术,又并不够用,这其实是我们需要更进一步分析的。 如果tomswan同志,总是认为我的思考不够深入的话,那么我写出来的那些东西所蕴涵的深入的思考,只怕你也是看不见的。 |
|
返回顶楼 | |