SSH从头到尾都是围绕着一个中心建立的:面向对象。
Hibernate是作为一种对象持久化手段而存在的。所谓的O/R MAPPING其实就是持久化。因为对象与关系只不过是一个个体与集合的关系,本质上并不存在冲突。不需要映射。事实上,在大多数情况下,内存中的一个对象正好对应关系中的一条或多条记录。甚至连转化都不需要。概念是等同的,不存在映射。另一种看法是直接把关系中的记录直接看成对象。这样子的话对于理解持久化的概念会更容易与直接一点。
而Struts则在很大程度上是作为一种O/STREAM MAPPING的技术存在于系统前端的。从这个意义上讲,Hibernate与Struts都更像是一种对I/O的封装。因为对象只能生存在内存中,所以才需要这两种技术作I/O映射。否则“对象”怎么跟外界进行交互呢?
既然前两者在大多数情况下都只不过是作为某种程度上的MAPPER存在于系统中的,所以其实只有Spring才是这个框架的核心部分。
Spring的IoC与DI功能就是面向对象的系统中其对象系统的骨架。如果没有这个骨架,众多的对象就很难连接起来一起工作。
自己开发一个这样的框架当然也不是不可能。只是这样做的话就免不了掉入重复发明轮子的陷阱。而Spring正是为了防止或免于大家做这样的事情。
实际上,我对Spring从来没有做过任何详细的研究。IoC与DI的价值也是在我认识到面向对象的价值以后才被我认识到的。网上有人认为它们因为是应用设计模式的极佳工具所以很好。我认为这样的观点有点神化设计模式的味道。我面向对象不一定要使用设计模式好吧!
工欲善其事,必先利其器。但是同样有话:杀鸡焉用宰牛刀。设计模式为系统增加了很多不必要的类。使用它很容易掉入过度工程的陷阱。事实上,大部分设计模式的存在目的是为了解耦。但解耦本身其实是一种思想,对这种思想的贯彻不一定要通过设计模式来完成吧。
另一方面,面向对象本身其实已经在很大程度上解决了耦合的问题。
与其因为设计模式的使用而引入大量的静态接口,还不如将有些协作要求交给动态的运行时去处理(至于如何做到这一点,目前仍未想清楚。但是无论如何,大量接口的存在,对于系统肯定不是一件太好的事情。事实上,面向对象的本来目的就是为了减少接口,把接口降到第二类成员的地位)。
IoC的价值是很基础的:它完成了对象的“安装”工作。这使得应用开发过程无须考虑对象的连接。而只要把对象设计好就行了。无需考虑对象的“安装”。
比如,一个典型的使用Spring的面向对象开发流程将是这样的:
1,开发对象;
2,安装对象。
这种流程显然更适合于多人或大规模开发工作。使用它进行工业级开发变得很容易。一个对象的使用者甚至可以自己定义被使用对象的接口。然后再在安装阶段进行相关调整。
可以看出,这里最重要的是安装阶段的引入。因为如果没有这个阶段的话,开发者就必须在开发阶段完成对象的安装。这样子的话开发者的注意力就会很容易被转移而最终形成以接口为中心的系统。这样显然不利于整体的面向对象的开发。
因为在面向对象的开发中,如何更好地实现对象本身比对象之间的交互更重要。交互应该以对象系统副产品的形式出现而不是以主角出现在系统中。因为在面向对象的系统中,接口是第二类成员而不是第一类成员。
第一类成员是对象。系统是由对象组成的系统。
理解面向对象最重要的一点就是要认识到:对象系统不是功能型的系统。
而将整个对象的开发阶段分成开发与安装两个阶段正好是这种思想得以彻底贯彻的唯一方法。
因为这种方法使得在第一阶段几乎不用考虑对象之间的合作,而只需要考虑如何尽量贴切地实现对象本身。实际上,真正的对象开发也只能在这个阶段得以完成。
这样一来,安装阶段的工作逻辑就很清楚了。它就好象是在说:好了,现在让我们看看它们能不能一起相处。
而对象开发阶段的逻辑也因此变得更清晰。为了便于以后的长期协作,可能有必要对对象的行为进行更高层次的抽象以便于以后能提供更多的操作可能(组合)。
也就是说,为了更好的与其它对象相处,可能要对对象本身的价值系统进行重整。也即对对象的行为进行粒度控制。
面向对象在这一点上与其它开发模型是一样的。只不过向更高层次抽象的目的不同而已。如在面向过程的模型中,抽象的目的是为了提供更好过程粒度。在面向服务的模型中则是为了提供更好的服务粒度。而在面向对象的模型中则是为了提供更合适的对象行为粒度。
这个流程还隐含着另一种软件开发哲学,即:部件比接口重要。而不是恰好相反的。如果部件不能共同工作,那么需要修改的不是部件,而是部件之间的接口。可见,接口在这里是第二类成员。
这与真正的真实世界的语义其实很相近(除了功能紧凑型系统如汽车,机械,电力。。。这样的系统与软件系统存在本质的区别。它们的复杂度领域在技术而软件的复杂度领域在协作)。
并且它也正好是面向对象相对面向接口编程的优点之一:面向接口的结果是以接口为中心的系统。一旦接口修改则整个系统都要修改。
协作与对象到底哪个更重要,所暴露出来的其实正是面向接口与面向对象两种开发范式在思维上的根本不同。