面向对象和面向过程_UML - 面向对象还是面向过程

我对面向对象编程的目标从就就不是复用。相反,对我i来说,对象提供了一种处理复杂性问题的方式。这个问题可以追溯到亚里士多德:您把这个世界视为过程还是对象?早面向对象兴起运动之前,编程以过程为中心,例如结构化设计方法。然而,系统已经到达了超越其处理能力的复杂性极点。的了对象,我们能够通过提升抽象级别来构建更大的、更复杂的系统 --- 我们认为,这才是面向对象编程运动的真正胜利。

------- Grady Booch

比掌握具体的技术更更重要的是掌握认识论所采用的方法和分析过程。只有掌握了方法才能自如地使用工具。

面向过程方法

面向过程方法认为我们的世界是由一个个相互关联的小系统组成的,依据严密的逻辑,环环相扣,井然有序。面向过程方法还认为每个小系统都有着明确的开始和明确的结束,开始和结束之间有着严谨的因果关系。只要我们将这个小系统中的每一个步骤和影响这个小系统走向的所有因素都分析出来,我们就能完全定义这个系统的行为。

所以我们要分析这个世界,并用计算机来模拟它,首要的工作是将这个过程描绘出来,把它们的因果关系都定义出来;再通过结构化的设计方法,将这些过程进行细化,形成可以控制的、范围较小的部分。通常面向过程的分析方法是找到过程的起点,然后顺藤摸瓜,分析每一个部分,直至达到过程的终点。这个过程中的每一部分都是过程链上不可分割的一环。

将世界视为过程的这个方法本身蕴含着一个前提假设,即这个过程是稳定的,这样我们才有分析的基础,所有的工作成果都依赖于对这个过程的步步分析。同时,这种步步分析的过程分析方法还导致另一个结果,即过程中的每一步都是预设好的,有着严谨的因果关系。只可惜我们这个世界从来都不是一成不变的。尤其是到了信息化时代,一切都无时无刻发生着变化,系统所依赖的因果关系变得越来越脆弱。

面向过程的困难

面向过程已经面临了太多的困难,世界的复杂性和频繁变革已经不是面向过程可以轻易应付的了,甚至对某些情况束手无策。那到底是什么样的困难。

例如,通过“商业分析”来收集和分析消费者的消费习惯,通过对细分市场的调查来了解商品需求变化。通过对这些采集来的数据进行分析和预测,销售策略就有可能发生变化。这个变化导致的结果是整个销售过程被颠覆。回想一下面向过程分析方法的前提和基础。当过程不再稳定,结果不再能预设的时候,面向过程方法还如何进行分析。

再例如,传统商业的销售数据可能只包含销售和利润,而到了今天,客户满意度、客户消费习惯、细分市场的变化,质量反馈......一份又一份的采样数据被包含进来。对以数据为中心的面向过程方法来说,数据的变化不但过于频繁,而且常常是结构性的颠覆。以数据为分析基础的面向过程该如何保持程序的稳定?

我们看到,面向过程的困难,本质上是因为面向过程方法将世界看作是过程化的,一个个紧密相连的小系统,构成这个系统的各个部分之间有着密不可分的因果关系。这种分析方法在需求复杂度较低的时候非常管用,如同一台照相机,将物体的反光经过镜头传导到感光胶片,再经过冲洗就能将信息复制出来。然而这个世界系统是如此的复杂和不可捉摸,就如同那个著名的蝴蝶效应,预设的过程仅仅因为一只蝴蝶轻轻扇动了一下翅膀就从此被颠覆,变得面目全非了。

31205f402f3a065de6b2b8bcf37e7a00.png

其实并非面向过程的方法不正确,只是因为构成一个系统的因素太多,要把所有可能的因素都考虑到,把所有因素的因果关系都分析清楚,再把这个过程模拟出来实在是太困难了。我们的精力有限,计算能力有限,只能放弃对整个过程的了解,重新寻找一个方法,能够将复杂的系统转化成一个个我们可以控制的小单元。这个方法的转换正如:如果一次成型一辆汽车太过困难,我们可以将汽车分解成很多零件,分布制造,在依据预先设计好的接口把它们安装起来,形成最终的产品。

这种把复杂工程转化成标准零部件的做法,在工业界早已非常普遍,这正是一种面向对象的方法。与过程方法不同的是,汽车不再被看过一个一次成形的整体,而是被分解成了许多标准的功能部件来分布设计制造。我们在市面上看到的每一款汽车,都是基于某个商业策略,由不同的标准零部件组合而成。当市场变化、商业策略变化时,可以通过变更标准零部件来迅速生产一款新车型。

面向对象方法

面向对象(Object Oriented,OO)方法是将世界看作一个个相互独立的对象,相互之间并无因果关系,有一种“鸡犬之声相闻,老死不相往来”的感觉。只有在某个外部力量的驱动下,对象之间才会依据某种规律相互传递信息。这些交互构成了这个生动世界的一个“过程”。在没有外力的情况下,对象则保持着静止。

独立对象依据某个规律结合在一起,具备了特有性质和功能,然后又构成更为复杂的更大的对象,这正是面向对象的基本原理。

从微观角度说,这些独立的对象有着一系列奇妙而古怪的特性。例如,对象有着坚硬的外壳,从外部看来,除了它用来与外界交互的消息通道之外,对象内部就是一个黑匣子,什么也看不到,这称为封装;再例如对象可以结合在一起形成新的对象,结合后的对象具有前两者特性的总和,这称为聚合;对象可以繁育,产下的孩子将拥有父辈全部的本领,这称为继承;每个对象都有多个外貌,在不同情况下可以展现不同的外貌,但本质只有一个,这就是接口;而多个对象却可能长着相同的脸,但同样的这张脸背后却是不同的对象,它们有着不同的行为,这就是多态

从宏观角度说,对象是“短视”的,它不知道也无法理解它所处的宏观环境,也不知道它的行为会对整个宏观环境造成怎样的影响。它只知道与它有着联系的身边的一小群伙伴,这称为依赖,并与小伙伴间保持着信息交流的关系,这称为耦合。同时对象也是“自私”的,即便伙伴之间,每个对象也仍然顽固地保护着自己的领地,这称为属性,只允许其他人通过打开的小小窗口,这称为方法,进行交流,从不允许对方进入它的领地。

然而对象也喜欢群居,并且总是“物以类聚,人以群分”。这些群居的对象有着一些相似的性质,它们依靠这些相似的性质来组成一个部落。对象们寻找相似性质并组成部落的过程称为抽象,它们组成的部落称为;部落里的每个成员既有共同的性质又有自己的个性,我们只有把特有的个性赋给部落成员才能区分它们并使它们活动起来,这称为实例化

对象或许是没有纪律的,但是一旦我们确定了一系列的规则,把符合规则要求的对象组织起来形成特定的结构,他们就能拥有特定的能力,给这个结构一个推动力,它们就能做出规则要求的行为。

每个对象都只与有限的其他对象有关系。分析对象时不再需要动辄把整个世界拉下水,从头到尾分析一遍,我们只需要关心与它有关系的那几个对象。这使得我们在分析对象的时候需要考虑的信息量大大减少,自然的,这就简化了我们所面对问题领域的复杂程度。

一个对象不只能用于这个东西,还能用于其他事物上,这是面对对象的一个重要特性:复用

由于对象是独立于最终产品的,只要符合规则要求,这些对象就可以替换,这给我们带来了极大的灵活性和扩展能力。

也就是说,我们用零件组装出了个刹车部件;相似的,按照其他特定的规则,我们用零件组装出发动机、底盘等其他大一些的部件。然后,我们还可以用这些大一些部件来组装更大一些的东西,例如一辆完整的小汽车,当然,也可能是一部拖拉机。

无论如何,以上描述揭示了面向对象的一个非常重要的特性:抽象层次。以上的描述是由小及大的(或称为自底向上)的抽象过程;我们也可以反过来,由大及小(或称为自顶向下)的来抽象。例如站在汽车的抽象层次,我们会发现汽车是由变速器、发动机、底盘等大一些的部件组成的;如果降低一点,站在发动机的抽象层次上,我们会发现发动机是由气缸、活塞等零件组成的;而站在活塞的抽象层次,我们还会发现活塞是由拉杆、曲轴等更小的零件组成的......只要你愿意,这种抽象层次可以一直延伸下去,直到原子,夸克......

抽象层次的好处是不论在哪一个层次上,我们都只需要面对有限的复杂度和有限的对象结构,从而可以专心地了解这个层次上的对象是如何共过的;抽象层次的另一个更重要的好处是低层次的零件更换不会影响高层次的功能,设想一下更换了发动机的火花塞之后,汽车并不会因此而不能驾驶。

面向对象方法与面向过程方法根本的不同,就是不再把世界看作是一个紧密关联的系统,而是看成一些相互独立的离散的小零件,这些零依据某种规则组织起来,完成一个特定的功能。原来,过程并非这个世界的本源,过程是由通过特定规则组织起来的一些对象“表现”出来的,原始的对象既独立于过程,也独立于组装规则。面向对象和面向过程的这个差别导致了整个分析设计方法的革命。分析设计从过程分析变成了对象获取,从数据结构变成了对象结构。

当然,世界上并无完美的事情,面向对象尽管有这么一大堆好处,它也有着与生俱来的困难,

面向对象的困难

综上所述,你可能会有如下疑问:

  • 你只告诉了利用零件能够组装出我们需要的功能,但是,你却没有告诉我们零件是怎么来的?难道零件是从石头里蹦出来的孙悟空,突然出现的吗?符合规则的标准零件是如何设计和制造出来的?
  • 经过测试,我承认现在这个结构可以完成那个特定的功能,但我还是不明白,如果我用另一些零件,换另一个组装规则,就不能完成那个特定的功能了吗?为什么是这个结构而不能是另外一个?这个结构到底是怎样实现那个特定功能的呢?
  • 零件是标准的,组装规则是可以变化的,这意味着我们可以任意改变规则来组合它们。显然的,即使是任意的组装,它们也必然表达了某一种特定的功能。那么我随意组装出来的结构表达了什么功能?

上面的疑问实质上体现了现实世界和对象世界的差距,即使面对简单的传统商业模式,我们仍有如下困惑:

  • 对象是怎么被抽象出来的?现实世界和对象世界看上去差别是那么大,为什么要这么抽象而不是那么抽象呢?Why?
  • 对象世界由于其灵活性,可以任意组合,可是我们怎么知道某个组合就正好满足了现实世界的需求呢?什么样的组合是好的,什么样的组合是差的呢?How?
  • 抛开现实世界,对象世界是如此的难以理解。如果只给我一个对象组合,我怎么才能理解它表达了怎样的含义呢?What?

在实际的工作中,我们常常设计出许多类来满足某个需求。但是如果问一问为什么要这样设计,为什么是五个类而不是七个类?为什么是十个方法而不是十二个?能很好回答这个问题的人并不多,绝大部分人的回答是凭经验。经验是宝贵的,可惜经验也是靠不住的,凭经验的另一个说法是拍脑袋。从需求到设计,从现实到对象,那些类的确正如孙悟空从石头里蹦出来一样,设计师一拍脑袋就出来了。而可怜的经验不足的设计师们,在面对一个复杂需求的时候,只好不断尝试着弄出几个类来,拼一拼,凑一凑,发现解决不了问题,在重新来过......许多项目就在这样的尝试中不断受伤。

不知您是否也是这样做设计的?

尽管不情愿,还是得承认很多时候我们只能通过不断测试来证明我们设计出来的那些类的确实现了需求,这往往需要在项目后期投入大量的返工成本,却不能清楚地在设计阶段就证明这些类已经满足了实际需求。许多设计师在被要求验证他的设计的确满足需求的时候,常常听到的回答是我的这个设计应用了某某设计模式,这个结构很灵活,扩展性很强,它肯定能满足需求......空谈了许多却无法拿出一个实实在在的推导过程。

不知您是否也有这样的经历?

而许多程序员,一手拿着设计师设计出来的结果,一手拿着系统分析员编写的需求说明书,苦思冥想,就是无法把两者对上号:既搞不清楚到底设计是如何映射到需求的,也找不到两者之间的关系:他们脑子里常常盘旋着的问题是:这个类表达了什么意思?为什么是这样的?

不知您是否也有这样的困惑?

如果您正被上面的这些问题困扰着,请您不要怀疑是否面向对象错了。我们把世界看作是由许多对象组成的这并没有错。只是现实世界和对象世界之间存在着一道鸿沟,这道鸿沟的名字就叫做抽象。抽象是面向对象的精髓所在,同时也是面向对象的困难所在。实际上,要想跨越这道鸿沟,我们需要:

  • 一种把现实世界映射到对象世界的方法
  • 一种从对象世界描述现实世界的方法
  • 一种验证对象世界行为是否正确反映了现实世界的方法

幸运的是,UML,准确地说是UML背后所代表的面向对象分析设计方法,正好架起了跨越这道鸿沟的桥梁。

如果你的分析习惯是调研需求时最先弄清楚有多少业务流程,先画出业务流程图,然后顺藤摸瓜,找出业务流程中每一步骤的参与部门或岗位,弄清楚在这一步参与者所做的事情和填写表单的结果,并关心用户是如何把这份表单传给到下一个环节的。那么很不幸,你还在做面向过程的事情。

如果你的分析习惯是调研需求时最先弄清楚有多好部门,多少岗位,然后找到每一个岗位的业务代表,问他们类似的问题:你平时都在做什么?这件事是谁交办的?做完了你需要通知或传达给谁吗?做这件事情你都需要填写些什么表格?......那么恭喜你,已经OO啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值