| Teddy_Ma_1982's profileTeddy's SpacePhotosBlogLists | Help |
|
November 24 Teddy's Blog is moved, no furture update here...Teddy's Blog is moved to http://www.dotnetjunkies.com/weblog/teddy/. November 25 谁说动物不搞笑 - 笑话集锦大象死了
一天一个动物园里的大象死了,饲养员趴在大象身上大哭,游人见到无不感动。但是一个人一语道破天机,他问游人:“你们知道他为何哭吗?”游人说不知。他说:“这个动物园有个规定,谁养的动物死了,饲养员要自己挖坑埋葬。。。”
-
北极熊:现在轮到你摸我了
一位老先生要养宠物,于是便到宠物店告诉店员说:“给我一只特别的宠物。” 店员便带老先生到店后面,有一只大北极熊,老先生很高兴便决定买下来。 店员最后警告老先生说:“你什么都可以作,就是不要摸它的鼻子。”几天后,老先生实在忍不住了,便偷偷摸了一下它的鼻子,这时,北极熊“吼...” 的一声,突然用后脚直立起来,舞著巨掌,开始追著老先生。老先生于是拔腿就跑, 飞也似的逃命。终于,不幸的被逼到角落。此时,北极熊缓缓的靠近,伸出手掌,摸了一下老先生的鼻子说:“现在轮到你捉我了。”
-
老鼠爸爸:“泡猫去”
有一家老鼠吃完饭开始聊天,不知怎么就谈起了胆子的问题。小老鼠首先发言:“现在的人真坏,居然做出老鼠药想毒死我们,根本不管用,我吃那玩意儿跟吃饼干似的”。
老鼠妈妈说:“在旧社会,没有老鼠药。人们用老鼠夹子,我根本不怕,有时 想锻炼身体了就把那玩意儿拿来当健身器玩儿。” 老鼠爸爸听完以后站起来就往门外走,老鼠妈妈问:“你干什么去”? 老鼠爸爸坏坏地一笑:“泡猫去”。 -
小白兔快乐奔跑的原因
一只小白兔快乐地在森林中奔跑。
途中,它碰到一只正在卷大麻的长颈鹿,“长颈鹿呀!你为什要做伤害自己的 事呢?看这片森林多美好!让我们一起在大自然中奔跑吧!” 长颈鹿看看大麻烟,再看看小白兔,它把大麻烟向身後一扔,跟著小白兔在 森林中奔跑。 後来它们遇到一头准备吸古柯硷的大象,"大象呀!你为什么要做 伤害自己的事呢?看这片森林多美好!让我们一起在大自然中奔跑吧!” 大象看看古柯硷,再看看小白兔,它也把古柯硷向身後一扔,跟著小白兔和 长颈鹿在森林中奔跑。接著,它们遇到一头准备打海洛因的狮子,“狮子呀!你为 什么要做伤害自己的事呢?看这片森林多美好!让我们一起在大自然中奔跑吧!” 狮子看看针筒,再看看小白兔,它把针筒向身後一扔,冲过来把小白兔狠狠 地揍了一顿。“你为什么要打小白兔?”大象和长颈鹿紧张的问。狮子生气地说:“ 这混蛋兔子!每次嗑了快乐丸就拉著我像白痴一样在森林里乱跑。” -
蜘蛛和蜜蜂订婚了
蜘蛛和蜜蜂订婚了。
蜘蛛感到很不满意,于是就问他的妈妈:「为什么要让我娶蜜蜂?」 蜘蛛的妈妈说:「蜜蜂是吵了一点,但人家好歹也是个空姐。」 蜘蛛说:「可是我比较喜欢蚊子耶.. 」 蜘蛛的妈妈说:「不要再想那个护士了,打针都打不好,上次搞到妈水肿..」 蜜蜂也感到很不满意,于是就问她的妈妈:「为什么要让我嫁给蜘蛛呢?」 蜜蜂的妈妈说:「蜘蛛是丑了一点,但人家好歹也是搞网络的...」 蜜蜂说:「可是人家比较爱蚂蚁ㄚ..」 蜜蜂的妈妈说:「别再提那瘦巴巴的工头,整天扛着东奔西跑连台货车都没有..」 蜜蜂说:「那隔壁村的苍蝇哥也不错..」 蜜蜂的妈妈说:「他是长的蛮帅,但也不能拣个挑粪的..」 -
倒霉的小毛虫
瘦弱的小毛虫给漂亮的雀小姐发现了,连忙哀求道:「请不要吃我,我可以告诉你我同伴的住处,它们比我肥美的多呢!」雀小姐答:「不必了,我正在减肥。」说罢便把毛虫一口吃掉。
-
速度很快的乌龟
-
为什么在这里
小骆驼一天问爸爸说:「爸,我们的背上为什麽要有驼峰??」「因为我们在横越沙漠时要储存脂肪和水分呀!!」骆驼爸爸说。「那我们为什麽要有长睫毛呢??」「因为沙漠风沙大呀,可以保护我们的眼睛呀!!」「那我们的脚底为什麽要长肉垫呢?」小骆驼又问。「这样比较容易横度沙漠呀!!」骆驼爸爸很自豪的说!最後,小骆驼问:『那。。。。那我们现在在动物园干嘛??』
-
腿与蛋
农场中一猪与一母鸡在谈慈善。 猪说:"我很想有一个方法能帮助那些没有饭吃的穷人。" 母鸡说:"我们来合作,可以做一个火腿蛋给他们吃。" 猪摇头道:"你说得容易,你只是贡献了一个副产品,我却要不见一条腿。"
-
胡搞出来的孩子
老鼠:我现在正和蝙蝠谈恋爱,以后孩子们就生活在空中,不怕你们猫了。猫冷笑一声,指着树上的猫头鹰说:看见没有,她已经怀上我的孩子了!
-
学会祷告的鹦鹉
有一名贵妇养了一只母鹦鹉,
但这只鹦鹉只会说:「来ㄚ!要不要爽一下ㄚ......」 贵妇觉的这鹦鹉的行为实在有辱她的身份 有日贵妇看到对面教堂的神父也养了一只公鹦鹉,而且很乖的在笼子里祷告 於是便去请教神父:「为何你的鹦鹉那麽乖?养多久啦? 我把我家的鹦鹉给你调教好吗?」 神父:「我养两年啦,它ㄧ直都很乖,你的鹦鹉怎麽啦?」 於是贵妇便把家里那只说话低贱的鹦鹉的情形ㄧ五一十地说给神父听 神父ㄧ口答应:「好ㄚ,你把你的鹦鹉给我养,我保证它会和我的鹦鹉ㄧ样, 乖乖地在笼里祷告。」 隔日,贵妇把鹦鹉送给神父,神父便把母鹦鹉关在与神父的公鹦鹉同一个笼子, 希望能以近朱者赤的方法把母鹦鹉教化 未料,只见母鹦鹉一看见公鹦鹉便叫著:「来ㄚ!要不要爽一下ㄚ......」 只见正在祷告的公鹦鹉眼睛为之一亮:「神ㄚ,我祷告两年的愿望终於实现啦.......」 -
好nb的蚂蚁
一只蚂蚁在路上看见一头大象,蚂蚁钻进土里,只有一只腿露在外面。
小兔子看见不解的问:“为什么把腿露在外面?蚂蚁说:“嘘!别出声,老子绊他龟-儿子一跤!” 第二天,兔子看见整窝的蚂蚁排着队急匆匆赶路,问何故? 蚂蚁答:“昨天有头大象被我们一兄弟绊倒,摔成重伤,我们给那丫献血。” 没多久,兔子见大批蚂蚁又回来了,就问怎么回事,一只蚂蚁说:“哦,只有一个跟那大象的血型一致,留他一个在那抽血呢,足够。” 第三天兔子赶来问蚂蚁:那丫活了吗?蚂蚁无可奈何的说:我把它抬回去了,**真重,腰都累弯了,那丫也太不经得摔了! 大象病好后要告蚂蚁,法庭判决,蚂蚁绊倒大象属恶意伤害,监禁6个月。 蚂蚁不服,“人身伤害罪最多监禁2月,为何判我半年?” 法官:“人身伤害罪判2月,绊倒大象为种族歧视罪,追加4个月~~~” 于是蚂蚁向高级法院提出诉状:我等与大象本来平等,何来“歧视”,请高院明判,还我等清白,另诉法官诬陷罪。 一天兔子忽然看见一只大象躲在树后面,将一只腿伸在外面。就问:“ 你在干什么啊?” 大象说:“嘘!别出声,我tmd等那蚂蚁龟-儿子来,好拌他丫一下,为我兄弟报仇。” 兔子刚离开大象就听见大象一声惨叫,于是马上跑回去看,途中遇见一只蚂蚁在路边喘气。兔子还没问蚂蚁就听蚂蚁自己说话了:tmd想整老子,还好我发现的早。把脚给它踩断了哈!! 大象又被送回了医院,因为股动脉被踩断,这次失血更多,连输80l还不够,血库告急,而那只唯一与大象血型的相符的蚂蚁已经在上次输血后虚脱了。 过了几天大象突然死了,大家跑去看它。发现她旁边有只母蚂蚁。就问它大象是怎么死的。母蚂蚁哭着说:我就告诉它说我怀了它的孩子它就~~~~ 母蚂蚁产了一堆卵,孵啊孵啊,结果孵出一群鸵鸟,靠!大象死的真tmd冤啊 -
两只麻雀在树上吹牛
大麻雀对小麻雀说:”我可厉害了,什么动作我都可以做得出来。像俯冲啊,盘旋呀,什么高难度的动作我不会呀?”小麻雀很是不服气,可一时又找不出什么好的法子要难为它。恰好树下有一个屠夫正在切肉。于是,小麻雀就对大麻雀说:“你不是厉害吗?那你有本事飞下去从屠夫手中弄块肉上来吗?”大麻雀笑笑说:“小KS!”于是一个俯冲,飞到桌上叼了一块肉就要飞上树,可一下子被屠夫抓了个正着!屠夫非常生气,便一根一根地拔大麻雀的毛。大麻雀只呼:HELP!!!
小麻雀实在看不过去了。一下子飞下去,冲着屠夫的手就咬了一口,屠夫手一疼便把大麻雀放了,大麻雀拼命飞上树来,小麻雀说:“这下不吹牛了吧,要不是我救你,你早活不成了。”可大麻雀说:“谁要你救我呀?我正准备脱光了衣服跟他干呢。” -
猪的笑话
一男养一猪,特烦它,就想把它给扔了,但是此猪认得回家的路,扔了好多次都没有成功。某日,此人驾车弃猪,当晚打电话给他的妻子问:“猪归否?”其妻曰:“归矣。”男非常气愤,大吼道:“快让它接电话,我迷路了。”
-
企鹅和北极熊的共识
有一只企鹅,闲得没事干,拔自己毛玩拔光了,他说了一句话:真冷。 续集:有一只北极熊,闲得没事干,拔自己毛玩,拔光了,他说了一句话:那企鹅说得没错. November 24 With AOP, Component Oriented == Object Oriented在本人之前的《Component/Service Oriented Software System Development Thinking 》一文中,我将包括BinaryLevel和Source Code Level的软件模块统称为Component。这种分类方式,和传统的对Component的一般定义应该说并不是十分一致。本文就是要对我为什么要这样分类作一些补充解释。
-
传统的定义中,一般认为,Component Oriented和Object Oriented有本质区别,在O'Reilly的《Programming .Net Component》一书中,列举了两者的主要区别和Component Oriented的基本原设计准则。没看过的读者可以下载下来看看,这里给的链接只包含该书了第一章,当然,这里说的区别和设计准则是包含在这一章里的。
区别:
1. Building Blocks Versus Monolithic Applications - 多程序集还是单一程序集
2. Interfaces Versus Inheritance - 黑盒还是白盒
设计准则:
1. Separation of cnterface and implementation
2. Binary compatibility
3. Language idependency
4. Location transparency
5. Concurrency management
6. Version Control
7. Component-based security
-
那么,我为何将这两个原本有区别,区别似乎还不是很小的区别的概念归在一个统一的概念-“Component”中呢?
首先我们来谈谈,上面提到的两个主要区别。
原书的作者的主要观点是,组件总应该是语言无关的二进制级别的黑盒模型,而OO则一般是语言相关的源代码级别的白盒模型。接着又说到,组件的重用,一般是不去关心其内部细节,而以大颗粒的功能调用或类继承来使用;而OO则可以以细颗粒去继承,并且可以方便的通过设计模式的运用组合、拦截函数调用,插入代码、修改内部细节等等,类的继承,也可以是细颗粒的。因此,说两者有本质区别。
从作者考虑这个问题的角度,也是传统的组件定义的角度来说,以上的论点当然是不错的。但是,有一项思想或者说技术的出现,很大程度上打破了以上的界限,是什么技术呢?您可能已经词到嘴边了,没错——AOP。
-
关于AOP的基础思想介绍,我这里就不多说了,如果您还不是很了解,可以在博客园站内搜索一下AOP。我这里要为您说明的是,为什么有了AOP的思想,以上这种CO和OO的界限和区别就大大减弱了呢?
当然这里我要特别提一下,我这里指的AOP,主要指有二进制级别织入能力的AOP,如Teddy所写的一个.Net下的AOP工具AspectWeaver,而不仅仅是像Castle.Aspect#这样的基于DynamicProxy的AOP实现。
因为AOP的二进制级别的织入能力,更直白一点说,是AOP使得操作二进制级别的组件或者说程序集就和操作源代码级别的模块一样容易的能力,使得只要您愿意,就可以像有源代码的组件一样使用二进制的程序集。在二进制级别将一个程序集分解成多个程序集,或者多个程序集者病程一个程序集同样是轻而易举的。所谓黑盒还是白盒的区别,也就变得没有太大的意义了。现在都可以看作白盒。只要相应的源代码能够编译成相互兼容和可识别的二进制程序集,那么我们就能在二进制级别对程序模块进行任意的重用和改造。
当然,上面所列的组件化设计的基本原则,现在还是适用的。同时,这种二进制级别的细节操纵能力,使得AOP不但能够使用OO中所有可以使用的工具和设计思想,还是一个超集,可以做到许多超越OO限制的功能,如Mixin,接口实现,基类变更,静态代码拦截等等/插入/删除等等,感兴趣的朋友可以自查看相应的资料。
-
正是因为AOP的这种特殊能力,很大程度上破除了二进制组件和OO组件的界限,更将带来软件开发思想,可重用软件设计等的巨大变革,和很多以前实现不了的可能性变为现实。这样的变革的大致风貌我在之前的文章《重新诠释AOP》中已有些许描述,在稍后的《Looking into Component》中,我也将会有进一步阐述。敬请期待!
资料收集正在构思如何写下一篇文章《Looking into Component》,随手从网上摘的资料先在这里放一下~~
OO设计的重要原则
1.开闭原则 (Open-Closed Principle)
模块在开放性方面应该是开放的(易于扩展),在更改性方面应该是封闭的(易于修改而不需要更改类的源代码)。 实现OCP的技术主要有多态和模板,均基于抽象。我们应该努力实现OCP以高效地复用和维护代码。 2.Liskov替换法则 (Liskov Substitution Principle) 使用指向基类B(抽象类或者接口)引用的模块(方法或者类),必须能够接受任何继承或实现B的具体类S,仍然能够正常工作而不需要知道具体类的实现细节。 3.针对接口编程 组件之间应该尽可能使用接口进行通讯,具体的业务逻辑由子类去实现不变的接口。 4.将可变的部分和不可变的部分分离 任何时候都将不变的接口与可变的实现分离。 如果使用继承的复用技术,我们可以在抽象基类或接口中定义好不可变的部分,而由其子类去具体实现可变的部分。如果使用对象组合,我们可以定义好不可变的部分,而可变的部分可以由不同的组件运行时动态配置。 5.优先使用对象组合,而不是类继承 优先使用黑箱复用(对象组合)而不是白箱复用(类继承)。利用对象组合我们可以在运行时动态配置组件的功能,并防止类层次规模的爆炸性增长。 6.高内聚,低耦合 很简单的一句话却是软件设计的精华所在:一个模块包含的功能彼此相关,相互依赖,而与外界很少关联,并且没有承担过多的责任,这样的模块(子系统或者类)称之为高内聚的(High Cohesion)。如果一个模块为实现自身的功能,并不需要了解或者依赖太多外部的知识,则该模块是低耦合的(Low Coupling)。 7.使用多态机制消除大量的IF/CASE语句 大量的IF/CASE使得代码难于维护和扩展,我们应该用多态来取代条件判断逻辑,状态和策略模式都可以帮助实现这一机制。 8.在多线程程序中谨慎地使用Singleton模式 Singleton模式在多线程应用中的不恰当使用会导致性能问题,在用到该模式时尽可能使用lazy initialization 方法。 待补充。。。 November 23 Current Component/Service Oriented Software System Development Model本文是Teddy关于基于组件及服务为中心的软件系统开发的进一步思考的系列文章的第一篇,探讨Teddy对当前的基于组件及服务的软件系统开发现状及基本思想的理解。本系列文章一共三篇,在之后两篇中Teddy将站在“组件”这样一个点上分别Looking into组件和Looking outside“组件”这个点,从而分别思考对第一篇中描述的软件开发模型的改进的可能方案。Teddy并非软件开发方面的资深专家,而只是一位喜欢思考的普通程序员,对软件开发这样一门科学的认识难免是具有非常的局限性的,因此,本文的观点仅代表Teddy的个人见解,如果您认为文中的观点过于奇特或幼稚,或者有失偏颇的,欢迎给与批评指教。
Current Component/Service Oriented Software System Development Model
我将自己理解的这样一个模型,比较简单的画了一张MindMap图。
请下载下面的MindMap图,并打开html文件察看MindMap图。您的浏览器需要支持Java Applet,您的系统必须正确安装Sun的JRE v1.4+及相关浏览器插件。如果在察看MindMap图方面有问题的话,请自行查阅在浏览器中正确运行Java Applet的相关参考资料,Teddy并不承诺回答您这方面的问题,这里先说句抱歉。另外,如果不能察看Applet,也可以打开zip包内包含的pdf文件察看MindMap展开后的静态效果。
-
如果您已经能够正确察看上图,欢迎继续往下阅读!
在这个MindMap图中,我简单的将主要的元素分成左右两类,左侧是功能性的元素,右侧则主要是辅助的非功能性元素。
既然是Component/Service Oriented,左侧当然是Component和Service了。而右侧则是使得Services和Component能够协同工作的过程中,起主要作用的一些辅助工具。
-
让我们从左侧的Service开始。
什么是Service呢?
节点上我给出了简单注释 - Langauge Independent Components with Unified Language/Platform Independent Interfaces。具体来说,这里的Service泛指语言/平台无关的功能组件,它的对外接口的具体表现形式逻辑上就像一个Method,更具体的定义可以参见Teddy之前的文章《重新诠释SOA》中关于Service的定义,即:
-
Service - 一种执行接口,接受外部的调用请求,请求可以包含0到多个参数,根据参数处理该请求后,返回执行结果,结果包含处理的成功或失败状态及0到多个返回参数,其中每个请求参数或返回参数都由一个Key/Value对表示。
Service的特性:
1)封装了细节,只要接口和返回结果不变,被封装了的实现细节对用户并不需要关心;
2)一个Service内部可以调用其它Service来实现,甚至可以递归调用Service自身; -
根据Service当前的所在位置,基本可以将Service分为Local Service和非本地的Web Service。
请注意区别这里的Service的定义和Web Service的定义与业界关于SOA的标准定义中Service和Web Service的定义相区别。您可以以业界的标准定义来直观地理解上述,但是,这里的定义本质上是一个更高一级的抽象描述。
-
那么什么又是Component - 组件呢?
这里我简单的将所有可重用的平台/语言相关的源代码级别的功能模块和二进制模块统称为Component。您可以展开MindMap图中的下级树枝往下看。
每个本地组件都会通过一组接口与外界交互,和组件的定义一样,组件的接口,也可以是源码级或二进制级别的接口。
本地组件怎样才能通过其接口和外部交互呢?两种情况:本地交互或远程交互。
如果组件希望和同样存在于本地的提供同样的或者至少是可以识别的本地接口的其他本地组件交互的话,只需要在语言或者二进制级别互相Reference就可以了。
如果需要交互的组件不能直接通过本地接口来交互,那么我们需要先将语言/平台相关的本地接口映射到平台无关的通用接口(Unified Language/Platform Independent Interfaces)。这个Mapping的过程需要Mapping工具来辅助,而Mapping工具则通过一定的Metadata Configuration来定义映射细节。
接着,可以通过更高一级的平台无关接口级Reference或者通过TCP/IP与本地Service或外部Web Service进行交互。这两种交互的媒介虽然不同,但是,基本的原则一致。同时,不论是平台无关接口级Reference或者通过TCP/IP,都需要Checking一组Policy来进行一定的约束,例如安全性检查或其他Contract约定。
-
我们可以看到,根据这个基本模型,基本可以构造出从大到小,无论是Component Oriented或Service Oriented或Component/Service Oriented的软件系统。因此,我称其为我理解的“当前的基于组件及服务的软件系统开发的基本模型”。
November 21 重新诠释SOA & AOP (2) - AOP前面谈到SOA,思维可能确实有点发散,但是,我还是坚持这样一种更高抽象层次的Service Oriented设计思想绝对是有益的。当然这个有待实践检验。另一方面,本人正在规划中的一个SOAHelper开源框架将会为基于通用的SOA思想的开发提供一些便利,当然,这里提到的SOA都不是业界对SOA严格的标准定义。而是更高层次的抽象,不过,对于严格的SOA,同样是有益的,不,应该是主要的服务对象。这个就是后话了,这里随便提一下。回到正题,本文是重新诠释SOA & AOP的下篇,即重新诠释AOP。大家放心,本篇不会像SOA那样发散,以至于什么都是AOP,毕竟AOP还是以OO为基础的抽象思想的扩展,这里谈论的主题还是在于AOP的意义及怎样的AOP实现方式是AOP未来的发展趋势,尤其会阐述一种所谓容器式的二进制/IL级别基于AOP的拦截机制。
-
什么是AOP呢?
这里引用wayfarer的《第三只眼看AOP》一文中的定义和解释(感兴趣的朋友也可以参考本人关于.Net下的AOP的一个文章系列):
简单地说,AOP就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
实质上,AOP只是OOP的一种补充或某种改进,它转换了编程的范式和视角,关注了一直以来被OOP忽略或者说未能解决好的角落,使开发人员可以更好地将本不该彼此纠缠在一起的责任(如银行业务和事务处理)分离开来。通过面向方面的编程,可以将程序的责任分开,对象与方面互不干扰。面向方面的模块并非显式地为对象所调用,而是通过或注入或截取的方式,去获得被封装的对象内部方法间的消息,然后做出相应地处理。也许面向方面的模式破坏了对象的封装,却正其如此,方才能降低模块与模块之间的耦合度。同样地,通过对“方面”的封装,将这些通用的功能从不同的类中分离出来,使不同的模块都能共享同样的“方面”,这也极大地减少了重复代码。
-
以上,是对于AOP的一般理解,当然,这样的阐述是没错的,本质上,AOP就是这么回事。但是,我相信,看完以上解释,还是会发现对于何时使用AOP,为什么我要用AOP,而不是传统的OO设计思想来实现我的软件功能呢?一旦觉得AOP听起来很美好去尝试过了,可能又会有更多关于性能、关于调试、关于事务一致性等等的疑问和担忧。如果您感觉到这些担忧,那么,非常好,您正在做非常理性的思考。会让人有这样的担忧,一方面是因为实现AOP,本身还不像OO那样直观,实现AOP的工具,也不像OO那样便利;另一方面,其实大多数人对使用AOP的时机,即如何去面对应用AOP可能带来的附带问题还是比较茫然的。我不指望您看完本文后能消除这种茫然,但是,我将尽力使您的这种感觉有所缓解。
-
说起AOP,我要提到一下MDA,我没有考证这两个词哪一个最先被提出,不过,我怀疑是MDA。AOP和MDA扯上什么关系呢?让我们先来谈谈MDA的基本思想。
MDA,Model Driven Architecture,是一种模型驱动的软件构架思想,发明者希望将来的软件开发能够用模型这种更直观的图形语言(一般来讲,这里的模型指UML),像搭积木一样来设计软件系统。理想情况下,一旦模型定义充分,从平台无关的模型(PIM)到平台相关的模型(PSM),进而到最终的可执行程序代码的过程是尽可能自动化的。
-
当然,这个是MDA最开始的思想,随着研究的深入,人们发现很多不那么实际的问题,首先就是PIM层往往过于复杂,很难构件化,我们可以想象,即使对于工作流这样一个相对比较雷同的领域,即使同一套系统,用户对于安全性、日志、事务这样的方面也往往有不同的要求,但是,可能对核心工作流引擎方面,很多系统有很相似。正在此时,有人发现了AOP,试想用AOP的思想将某些变化的可能性更大的逻辑分离出来,先关注核心业务逻辑精进和的重用,那么PIM不就会更清晰吗?
于是,有人提出MDA的过程,可以修正成一个新的模型:最开始除了核心基本不变平台无关的模型(PIM),新增一组Aspect(方面)层次,如日志、安全性、事务、Qos等等横切面模型(Aspects);第二步,通过一定的Converter将PIM和Aspects在一定的上下文条件下进行整合,成为平台无关的特定的模型,姑且称之为改进的平台无关的整合模型(EPIM);最后,再将这个EPIM转换到PSM。
这样做有什么好处呢?主要的好处是,有一些系统核心业务是基本不变的,比如,工作流,又如CRM,但是却有很多不确定的,易变化的,有时需要有时不需要的方面,那就可以将核心业务做成构件尽量充用,而将易变的方面做成Aspects,这就使得混乱的PIM,变得稍稍那么清晰一点。看起来,AOP,似乎有那么点用武之地了。可是,这就够了吗?
-
难道只能在一个整体雷同的业务模型上获得重用,不能再分的更细吗?如果一个构件流程显示比较美观,但是另一个构件性能更好,我就只能两者选一吗?问题的关键在哪里呢?关键在于,构件分得不够细,但是,很遗憾的是,这种分得不够细,不是我们不想分,而是无能为力。为什么无能为力呢?问题的瓶颈在哪里?非常遗憾,在于OO。
问题的瓶颈在于OO,为什么这么说呢?这也是我在关于SOA的上篇中说smalltalk的作者让我们认为世间万物都是对象,所有的对象都可以通过不断地继承,通过接口,通过重载等等这些OO元素就能完全描述了。这其实可笑之极!且不说,是不是世上就没有过程了,毕竟我可以让一个对象内只包含过程,并美其名曰对过程的对象化封装。OO中的对象和现实世界的对象的最大的区别在哪儿呢?
最大的区别在于,现实世界的对象,比如说人吧,必须在一个特定的上下文环境中才是有明确意义的。比如,当一个人在单位工作时,它是一个Employee,当他在健身房里,它是一位锻炼体魄的用户,当他和妻子在一起时,它是一个丈夫。而每种的角色的属性和方法是不尽相同的。那么,请问,一个人应该包含什么属性呢?以OO的思想,他只有用继承来描述。Ok,Employee继承自一个最简单的人,健身房的用户也可以继承自人,丈夫也可以继承自人,那我请问您了,假如这个人在单位的健身房里和妻子一起正在有说有笑的健身,这个时候你怎么表示这个人?
发现什么问题了吗?重复一下,一个对象,只有在一个特定的上下文环境,它才是有明确意义的。当上下文不同,它的属性方法可能完全不同。当一个程序员在单位的电脑前写代码的时候,谁关心他妻子是谁呢?老板在关心他写的代码质量的时候,时不时会关心他的二头肌脂肪含量多少呢?没错,我要说明的是,纯粹的OO没有描述这种非常常见的场景的自然方法。
-
那么让我们想象怎么来解决这个问题吧。很明显我们要解决类似当一个人处在一个特定的上下文环境时,自然而然的具有这些附加属性和方法,而当这个人处在集中叠加的环境时,自然而然的拥有叠加的附加属性和方法的问题。
解决这样的问题的最直观的方法,就是用一个容器来表示一个上下文环境,环境是可变的,当环境变化时,促使环境中的人变化的因素,应该自动的使得被管理的人获得附加的属性和方法。
有没有哪一种技术,可以达到这样的效果呢?有的,正是我们谈论的主题,AOP!
根据这种思想,有人提出了这样一种思路,进一步扩展上面的第二种改进的MDA过程:
将构件细分成更细的颗粒,比如人这样一个个构件,和描述不同上下文环境的人的附加属性和方法的不同的Aspects。这样,不论对于前面模型中的PIM和Aspect,都首先用一个容器来承载,对于每个容器包含人或者甚至是一个通用的事务处理方面这样的主构件的同时,只要插上不同的描述附加属性的特殊的Aspect构件,就使得这个容器描述了一个组合的,更加满足上下文需求的混合体。假设我们称这样的混合体为MPIM,和MAspect,那么,后面的不走不变,相应的再生成EMPIM和EMAspect,最后转换成PSM和可行性的代码。这样一来,是不是觉得MDA的实现更加实际呢?
-
当然,虽然以上分析以MDA的过程改进为主线来说AOP的地位,即使在目前MDA未被广泛采用的时候,AOP的这种应用方式,个人觉得,同样也是未来构件化的发展方向。细颗粒的构件,配合容器管理的AOP混合就能将软件构件重用发挥到一个非常高的层次。我想,通过以上论述,您多少应该有些认同吧?
如果再说到具体的AOP实现方式,一般有两种选择,也是现在的AOP框架的两条主线,即DynamicProxy和StaticWeave(也有一些可选方案,比如在.Net2.0中允许动态的为一个类附加动态方法,这里暂不评论其局限性),对于这两种实现线条,我倾向于,或者说得更肯定一些,我只看好StaticWeave,为什么呢?你就设想一下,以后的软件系统中的某个上下文环境中的一个人,它是由上百种甚至上千种叠加的上下文混合而来,如果用DynamicProxy来实现,是什么效率呢?短期内,像Castle这样的容器配合Aspect#这样基于DynamicProxy的AOP工具也是能达到一定的效果,但是,如果从长远来看,本人以为,基于容器管理的静态织入思想为基础的构件化软件自动化设计方法,一定是未来的发展方向。
这样一个易于静态织入的通用容器,也是本人希望努力尝试实现的方向。具体能达到怎样的效果,我不敢妄下判断,但是,我相信,尽管不坚信,能够起到很好的效果。还是有待实践的检验~~
November 20 重新诠释SOA & AOP (1) - SOA虽然写了不少AOP的文章了,也没少关注SOA,不过最近才发现自己以前的认识多少有些狭隘,不,应该说非常狭隘才是。在这里,我要结合自己最近的感悟,重新诠释一下什么是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,当然是不错的进步,有很多好处,帮助我们在认识世界,用计算机描述我们生活的世界方面居功至伟,但也带来了很大的局限,导致包括我在内的无数程序员市场变得神经兮兮,以五比七怪的视角一次又一次的审视着这个世界,这个后头再谈了,这里还是先说说他的好吧!
“封装”, “继承”-多优雅的词啊!世界变得整洁,没有不知定义在那里的全局变量了(喂,老兄,类里面还是有作用类全局的变量啦-嗨,我能不知道这个嘛,可是,看他可不是作用全世界的变量),还有,拿我家的小狗为例吧,你知道吗?真是太棒了,当我定义好我家的小狗这个类,我可以给他指定各种它能做的活动-专业的叫法是“方法”,还有我给他定义了各种属性,这样我操纵我的小狗真简单,让它跑它就跑,让它叫它就叫,把它的颜色这个属性改成红,他就变红毛了,改成绿他就变绿毛了,真他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,不就是那么简单吗?
-
文章太长了,关于AOP,还是另起一篇来阐述好了~~ November 19 上海科技馆C++大会第一天见闻上午,10:00秃头大师stroutrup风尘仆仆的到来,不紧不慢的介绍了下C++未来发展趋势,总的来讲只是些小特性的改进,例如可变类型的auto指针和嵌套vector<vector<int>>定义的改进,今后>>中间不必非要有空格了,还有新approved将加入标准的TR库。
下午,陈榕的《面向目标代码编程》倒是煽动力惊人,人也风趣,又阅历广泛,真让人感觉不虚此行。总结他话题,其实可以用两个词来代替,SOA(虽然他整个演讲过程都没说这个词,他说的是不仅仅是TCP/IP的Web Service),AOP(二进制代码级的基于容器的aspect织入),他的论点是这两个词,将代表了未来软件开发的总体方向,包括微软的LongHorn和真正的软件构建化,都脱不开这两个重点。 嘿嘿,SOA+AOP,陈榕和我想到一块儿去了~~ November 17 五年后的自己应该是什么样呢?在HPET的培训中,关于五年后的自己,记得是这样写的(这里进一步扩充至细节,以使目标更明确):
1、专业技术领域内公认的专家。xxxx
2、幸福的家庭和基本没有物质方面的生活压力。xxxx
3、具备创业所需的综合素质和资源。xxxx
(为保护个人隐私,细节部分已隐藏,查看完整版本需要额外权限,请见谅!) 关于个人知识管理的思考1. Blog
Blog社区,Blog社区适合存放希望得到反馈的技术文章,反馈——无论正面还是负面的反馈都是我们发布文章到社区的驱动力。但是如果有希望文章并不是自己非常希望得到反馈的,那么留在完全属于自己的空间可能更好。
2. Wiki
Wiki用来存储各种不太需要反馈的,又相互关联的资料是最合适的,就像Wiki的来源一样,他本来就最适合用作知识库。
3. 个人网站
那么还需要个人网站吗?如果需要的话,那么个人网站又能提供些别的什么帮助呢?
首先,我想个人网站应该是一个人的形象,就像穿衣服一样,给人的整体印象。而Blog更适合看一个人近期的研究、爱好、专注方向或者工作内容,而且也可以追踪之前的某个时候此人专注什么。至于wiki则是自己的知识总结,可以经常整理修改wiki中的资料来整理更新自己的思路,也可以让别人通过wiki看到你对一切知识的看法,而且应该总是维持在最新的。
其次,还是没说到重点,个人网站是一个形象,那么,这个形象到底应该包含什么内容呢?包含个人真实信息?包含到其他内容blog,wiki的引用?包含成片成论的文章?还是仅仅做一张漂亮的脸面呢?
4. MSN Space
最后想到这MSN Space,从今天起,姑且将这里作为自己的脸面,一方面作为到自己的其他网站的索引入口,一方面就堆积关于一切一切杂想和不成熟思考好了。:) |
|
|