重新诠释SOA
虽然写了不少AOP的文章了,也没少关注SOA,不过最近才发现自己以前的认识多少有些狭隘,不,应该说非常狭隘才是。在这里,我要结合自己最近的感悟,重新诠释一下什么是SOA,什么是AOP。本文原出处为我的MSN SPACE,原文标题是重新诠释SOA和AOP,因为实在写得太长了点,这里分成两篇来写,这是第一篇:重新诠释SOA。之后还会有下一篇,重新诠释AOP,敬请期待!
-
什么是SOA呢?
一直以来,个人就认为SOA有些奇怪,有点回到原始的过程化设计的味道,一度怀疑是不是web service的兴起,因为web service没有状态,又是粗颗粒的,所以,出现了这样一个不伦不类的SOA。虽然也一直认为自己理解是有偏差的,但到现在才知道错得很远。
那么,到底什么是SOA呢,所谓Service Oriented自然肯定是突出Service,可是为什么要突出Service,甚至Web Service(Web Service)呢?
首先,让我来先给Service下一个定义,该定义的有效域至本文中下一次对Service的定义进行修正(如果有这样的修正定义的话,否则定义就一直有效知文章结束)为止。
-
Service - 一种执行接口,接受外部的调用请求,请求可以包含0到多个参数,根据参数处理该请求后,返回执行结果,结果包含处理的成功或失败状态及0到多个返回参数,其中每个请求参数或返回参数都由一个Key/Value对表示。
-
根据该定义,让我们来看看,在现实世界中,在哪里我们可以看到这样的Service呢?
依照一般的问题分析方法,对任何一个问题点,我们都可以从水平和垂直两个纬度来分析,水平纬度一般指问题的广度,垂直纬度一般指深度。无论水平或垂直纬度上的每个点,我们又可以从水平垂直两个方向来递归分解。
这里,我们先以一个计算机软件的执行过程这个水平点,在不同的抽象层次深度上,找找Service的影子。
-
我们知道,对于任意一个冯·诺依曼体系的计算机,任意一个程序,归根结底到最后都会被转换为一串串的0和1,这些0和1的不同组合代表了不同的计算机指令或者数据。Ok,我们找到了一个词-“指令”,一个指令是什么东西呢?在计算机内部,一个计算机指令的执行过程实际上是由解码器解析传入的一串0和1,根据这些0和1代表的不同含义,执行一些操作,其间可能会读取或改变一些指定寄存器或者存储器单元的值,不论是否执行成功,他都会有一定的反馈,可能是一个中断信号或者一个计数器递增,总之代表了这个指令执行过程的结束,如果需要的话,以后的指令可以去读取该指令修改的寄存器或存储器的值。
比较一下一个计算机指令的执行过程和我们的Service的定义,我们可以发现,一个“指令”,就是一个“Service”。它是一个执行接口,接受调用请求和读取指定位置(key,如约定的寄存器名称或存储器地址)的传入参数(由0和1序列指定哪个指令被调用,并有之前的指令为其准备好了可能要去读的寄存器或者存储器的value),执行一定的处理,并返回执行状态(如中断或计数器递增)和返回参数(写寄存器或存储器,允许之后的指令访问)。
除了“指令”的这些表面特征,他还有些什么特点?我们可以看到,计算机的发展日新月异,但是,基本的最操作指令却基本是类似的,无外乎对一些0或1的处理嘛-与、或、非、异或、同或、左移、右移等等。但是,不同时代,甚至同时代的不同结构或者同结构的不同上下文环境,同一个指令的请求、输入参数和返回结果可能相同,但是,执行的内部处理机制可以是不同的。比如,最早最简单的计算机,可能仅仅通过硬布线的与、或、非门及一定的线路组合就能够完成一个指令,比如“非”这个操作,用一个“非”门就够了;随着技术的进步,这些与或非门可能被封装进了各种通用组合元件中以方便支持复杂处理,或者不完全用这些“门”,用Rom阵列,或者半导体非数字模拟元件配合特殊的信号刺激,同样能够完成等价的处理效果;计数再进步,可能一个计算机处理器内部又有一个个特殊功能的微处理器,也就是一个个内嵌的小型计算机处理器,不同的指令直接传递给这些微处理器来处理就好了,速度不够快了,人们又发明了各种缓存寄存器,流水线,微处理器阵列,等等等等。内部结构和设计思想在变,但是,什么没变呢?没错,这些基本指令的调用接口和执行结果基本不变。
这种“调用接口和执行结果不变”是什么思想呢?其实就是一个“黑盒”的思想,封装的思想。外部的调用者无需知道处理的内部细节,每个“黑盒”可能在执行效率,寄存器、存储器或时间等花销这样的非功能性效果上会有不同,但是,它们功能性效果-输入输出返回值,是不会变的,也不允许变,变了就不是同一个指令了。
显然,指令的这样一种“调用接口和执行结果不变”的特性,也是Service的特性。
-
让我们从与或非门中稍微解脱一些出来,到一个新的抽象层次-汇编。什么是汇编呢?其实,它离0和1也不远,教科书上说了,汇编是对0和1这些机器指令的抽象封装,用add,or,not这样的有那么点人性的词代替了001,010,100,一下子,写计算机程序变得简单多了,效率大大提升。但是,本质上,机器指令和汇编指令基本上是一一对应的,当然也可能一个汇编指令对应了一个有多个机器指令组成的指令序列。于是乎,很显然的,我们当然可以说,一个汇编指令也是一个Service。
非常幸运的,除了对机器指令调用的简化,汇编对我们关于Service的讨论也不是一点帮助都没有。我们注意到“一个汇编指令也可能一个汇编指令对应了一个有多个机器指令组成的指令序列”!这是一种什么特性呢?其实是一种分而治之的思想,一个汇编指令可以分别由多个机器指令的组合,甚至其它更简单的汇编指令甚至递归调身指令本身的组合来实现效果。
Nice,我们再次发现,汇编指令的这样一种“一个汇编指令也可能一个汇编指令对应了一个有多个机器指令组成的指令序列”的特性,也是Service的特性。换句话说,也就是说“一个Service内部可以调用其它的Service,甚至递归调用Service自己来实现需要的功能逻辑,而这种内部细节,对调用者完全透明”。
-
好了,我们再进一步,来到我们可爱的高级语言C/C++,Java,C#。。。不知道读者是不是看了这些词松了口气,至少Teddy是呼了口气的-多优雅美丽的世界啊,机器指令、汇编,见鬼去吧,这年头还谁喜欢和你们瞎掺乎啊~~
本来还想将我们的高级语言们分分过程化、OO什么的,不过仔细想想也没必要了,反正比起汇编都美多了,不是吗?:)还是来看看这些新家伙给我们带来了什么新东西吧。
恩~~ 似乎在汇编之后,我们漏了过程化的汇编,从某个时候起,汇编也是可以有“过程”的,现在这年头叫子函数,总之就是程序不再一股脑儿从第一条指令执行到最后一条,而是中间有调用子函数,再跳转回来,或者来个递归调用什么的,只不过,这和我们前面说的一个汇编可以包含多个机器指令,内部可以递归调用等等真的有区别吗?本质上其实一会事,不是吗?只是,随着高级过程化语言的出现,使得过程化的程序设计应用更简单了,子函数多了,我们自然给他们归类,他们成为一个个--对了,一个个“模块”,恩,准确地说应该是“过程化模块”。
为什么说是“过程化模块”呢?因为,过程化的程序设计,除了过程/子函数,还有一些东西叫变量,尤其有一种叫全局变量。很多过程化程序教科书教育的好,如果数据需要被其它过程使用和共享的话,可以定义全局变量,这样的好处是,不需要每次都把这些数据作为参数在过程间传过来传过去了。说心里话,我觉得全局变量这东西挺好的,大大简化了过程化的程序代码。姑且,请读者允许我将这类过程/函数式,并且包括共享变量在内的模块设计思想,和OO基于类的模块化思想相区别。
好了,老样子,比较一下过程模块和Service的定义,很好,一个过程就是一个Service。
-
下面,就轮到我们来看看我们噢年工作中最亲密的伙伴OO了。相比较于传统的过程化设计,OO带来了什么呢?让我们来回想一下-接口、类、封装、方法、多态、继承、重载。。。除了这些词,当然,更重要的是smalltalk的作者倡导的“世间万物一切都是对象的,一切都是OO”的“变态”思想,很抱歉用了个粗话词,虽然加了引号,但是,说真的,我是真的在说粗话,真的觉得他很变态。他提出的OO,当然是不错的进步,有很多好处,帮助我们在认识世界,用计算机描述我们生活的世界方面居功至伟,但也带来了很大的局限,导致包括我在内的无数程序员市场变得神经兮兮,以五比七怪的视角一次又一次的审视着这个世界,这个后头再谈了,这里还是先说说他的好吧!
下面,就轮到我们来看看我们噢年工作中最亲密的伙伴OO了。相比较于传统的过程化设计,OO带来了什么呢?让我们来回想一下-接口、类、封装、方法、多态、继承、重载。。。除了这些词,当然,更重要的是smalltalk的作者倡导的“世间万物一切都是对象的,一切都是OO”的“变态”思想,很抱歉用了个粗话词,虽然加了引号,但是,说真的,我是真的在说粗话,真的觉得他很变态。他提出的OO,当然是不错的进步,有很多好处,帮助我们在认识世界,用计算机描述我们生活的世界方面居功至伟,但也带来了很大的局限,导致包括我在内的无数程序员市场变得神经兮兮,以五比七怪的视角一次又一次的审视着这个世界,这个后头再谈了,这里还是先说说他的好吧!
“封装”, “继承”-多优雅的词啊!世界变得整洁,没有不知定义在那里的全局变量了(喂,老兄,类里面还是有作用类全局的变量啦-嗨,我能不知道这个嘛,可是,看他可不是作用全世界的变量),还有,拿我家的小狗为例吧,你知道吗?真是太棒了,当我定义好我家的小狗这个类,我可以给他指定各种它能做的活动-专业的叫法是“方法”,还有我给他定义了各种属性,这样我操纵我的小狗真简单,让它跑它就跑,让它叫它就叫,把它的颜色这个属性改成红,他就变红毛了,改成绿他就变绿毛了,真他X简单。你知道吗,你操纵它的时候根本不用去关心它里面的细节,只要看它能干什么就行了。还有还有,你知道吗,我也可以不把它当一只狗,它同时还是一个动物呢,就和现实中小狗食动物是一个道理,很有意思吧?嘿嘿~~因为它是一只公狗,在他还很小的时候,长辈给它做了一个小手术,我也不太清具体的细节,总之,他们说做过这样的手术他就会变得很温顺了,也不用担心它以后被其它小母狗拐跑了,他只会忠于你一个人,所以,我后来不用“小狗”这个类来表示它,我用最忠诚的小狗来表示,这其中的区别,我现在已经知道了,可是不告诉你~~而且,它还是一只小狗,他也还是一只动物呢~~
好了,各位,我们别想到其它方面去了,现在可是在OO的世界,OO模块化的世界是那样的清洁而优雅,如果你问我“一只小狗会不会上网写Blog”这种弱智问题,我不会直接告诉你的,在以前的过程化的年代,也许我会去问问动物研究专家,或者直接告诉你我的意见,但我不得不if很多条件,有时还要去问世界万狗之神狗当(汗,不知道这是不是指全局变量呢),总之,你明白我的意思,那种做法过时了,我现在只要让我的小狗直接回答我就行了,你不信?我是这样做的,告诉你吧,我用了很新的设计思想的,叫设计模式,你问那个设计模式?恩,一看就是内行,可是还真不好回答你,瞧,我这里定义了一个接口,他有一个方法叫“会不会上网写Blog”,然后呢,我写一个新的类,让他继承自我的小狗,然后,我问小狗“你会不会上网写Blog”,它摇遥尾巴就告诉我了。什么?你问,他是怎么知道答案的?这个我就不能告诉你了,你还是猜猜吧~~(嘿嘿,我才不告诉你其实我还是用了不少if,发email问的小狗的祖宗“动物神”,他怎么知道的我就不知道了),关键在于,我现在是直接问的小狗,它也回答了问题,这和以前的做法可是有天壤之别的。是不是感觉到不服不行啊,哈-哈-
直接了当的说了,既然方法都只能放到类里了,那么,类的一个方法就是一个Service。
-
说到这里,亲爱的读者朋友,不知道你是不是被我彻底弄糊涂了,既然一直以来,什么都是Service,那我们现在还提什么SOA啊?大声高呼,我们一直都在SOA不就得了,还浪费我这么多宝贵时间来读你的狗x臭x文章,真是他xx的。息怒息怒~~
其实,您的理解没错,Service无处不在,尤其是当Service是按照我在本文开始的定义来理解的话!我还是再把它完整的写一遍好了:
-
Service - 一种执行接口,接受外部的调用请求,请求可以包含0到多个参数,根据参数处理该请求后,返回执行结果,结果包含处理的成功或失败状态及0到多个返回参数,其中每个请求参数或返回参数都由一个Key/Value对表示。
Service的特性:
1)封装了细节,只要接口和返回结果不变,被封装了的实现细节对用户并不需要关心;
2)一个Service内部可以调用其它Service来实现,甚至可以递归调用Service自身;
-
但是~~ 要说SOA中的Service,以上的定义还缺了点东西。缺了什么呢?缺少了上下文,缺少了依赖关系的限制。
以机器指令为例,一个机器指令如果能被称为Service的话,首先他其实隐含了这样的限制,首先,致令的执行环境是特定的机器,和元件的组成结构,其次,它隐含约定了寄存器、存储器的数量,名称,位置,这些和读取输入数据,返回执行结果都是密切相关的。如果我从另一台机器的一个指令直接访问本机器的一条指令,到然不行,甚至同一台机器,在不同的隐含约定下,相同的指令的执行效果和功能也可以是完全不同的。
再到汇编,到C到C++,Java,C#。。。语言越抽象,越高级这样的隐性限制和约定越来越少了,但是归根结底,不管多少,都还是有上下文限制的,或者有语言限制的,就是语言没限制也可能有运行平台限制。那么是不是可能没有任何限制呢,当我要一个逻辑功能的时候,能不能让我只要关心结果,不用关心任何限制和细节呢?
从哲学的角度讲,没有任何限制是不可能的,记得以前的哲学课上,老师一再强调,任何命题,如果没有前提条件,没有任何限制,那它就一定是错误的!任何错误的命题,只要加上合理的限制,那就一定可能变成正确的!金玉良言,金玉良言啊,同志们!!
借助哲学老师的名言,我们可以重新理解上面的命题:
- “是不是可能没有任何限制呢,当我要一个逻辑功能的时候,能不能让我只要关心结果,不用关心任何限制和细节呢?”-错,不可以!
- “如果能有统一的输入输出接口,能有跨平台支持的数据交换协议,最好再辅以不同语言环境到同一接口的等价映射的话,能不能让我只要关心结果,不用关心任何实现细节,互相协同工作呢?”-对了,可以!
所以,什么是SOA,Service Oriented Architecture,什么是SOA中的Service呢?加上一个限定上下文和条件,在指定的上下文这个前提限制下,还是以前面定义的这个Service的定义为中心来架构软件,就是SOA。大,可以大到跨平台、跨语言甚至更大,小可以小到机器指令,脉冲信号,甚至更小。
SOA,不就是那么简单吗?