博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象是软件开发范式的根本性颠覆: 主体建模, 非目标导向, 松耦合, 非逻辑分解, 软件进化...
阅读量:5992 次
发布时间:2019-06-20

本文共 8409 字,大约阅读时间需要 28 分钟。

  hot3.png

关于面向对象的文章,100篇里面有99篇要么离谱太远,要么不知所云,但剩下有1篇是好的。我历经多年找不到那一篇,最终还是决定自己研究(因为工作环境的原因,我的研究大多集中在性能与正确性这些东西上面,对进化的思考一直都很少,也一直都没有找到这方面的资料---它们真的很难找)。

面向对象很重要。在今天的软件业界,它基本上是一切的基础。比如设计模式,领域建模,甚至对框架的学习与研究和数据库,一切都宣称是面向对象的。要搞清楚它们是否真是面向对象的,就必须先搞清楚什么是面向对象。

因为这个词被滥用得太厉害了。我读过的有很多一看就知道是大家所著的谌称专业级的文章一样在上面犯下非常严重的错误(这个其实没有看上去那么奇怪。因为,一旦来到哲学的层面,犯错误是很正常的,不犯错误的才是不正常)。

实现一个系统很容易,难的是实现一个好系统。任何程序员都懂得怎么实现一个系统,但系统到底怎么样就要看各人的功底了。

要讨论面向对象,我想先从哲学入手会好一点。哲学史上有一种思想叫解构主义。而面向对象其实就是对面向过程思想的解构。解构很困难,因为它需要从根本上改变思维的方法。比如,要一个人从唯物论转向唯心论很困难,反之同样。原因就在于哲学所涉及的都是非常深层的概念,而这些东西都是在潜移默化中长年累月积累形成的东西,要改变它们当然不容易。从解构主义的角度理解,就是要在人脑中重新构建整个软件概念系统,以一种完全不同的思维方式进行思维。在这种思维方式中,系统不再为功能存在,系充单元也不再只具有功能性,而是具有独立个体特征与生存权的单元。系统在整体上再也不只是个功能复合体,而是由一个个具有生动个体特征的对象组成。系统能力的提供不再是人为规划的结果,而是由系统中的对象间接提供的。也就是说,面向对象的开发方法用对象的开发取代了直接的功能开发。功能不再是设计时的首要考量,只是系统恰好具有的一种能力。系统在本质上或至少在设计思路上,跟功能是没有关系的。这有点象中央集权的政体与民主政体的区别:中央集权的政体是具有高度目标一致性的政体,民主政体则完全颠覆了这种逻辑:个体不再为整体存在;国家也不再有由功能或职能单位组成,而是由鲜活的个体组成。国家存在是因为个体存在。个体优先于国家,这是民主政体的逻辑。这种逻辑比起高度目标化的中央集权政体更符合实际的现实情况,因为它承认个体(which is existing)的存在。承认存在物的存在还有一个好处就是它更稳定。因为不管国这怎么变,个体作为一个概念是不变的。变化的只不过是游戏规则而已。但是这样的规则在目标化的系统中只能通过硬编码的方式实现,因为目标化系统不存在主语,这样的形式系统表达能力其实非常有限。它只能通过对谓语的约束实现一种扭曲的,难以理解的逻辑。这一方面造成艰难的可理解性,另一方面因为低可理解性变成错误的源泉。因为它是一种要么以设计者要么以少数几个随意假想的无形式主语(只存在于设计者的大脑中)为主语的系统,不是一种更直接更容易理解与接受的领域模型。也就是说,因为主语的缺乏,这样的系统实际上最好都变成了一种双逻辑系统:用户逻辑与开发者逻辑。两种逻辑同时存在的结果是,需要有人不断地在实现翻译或者说概念映射操作。这也是面向过程的系统可维护性更差的原因:翻译官一走,就没有人看得懂系统了。

理解这一点也不是很容易,因为它涉及到形式系统理论甚至程序语义学:计算机程序只是一种形式系统,对它的理解过程实际上是一个语义赋值的过程。当一个形式系统在结构即语法上更加通俗化时,它的可理解性更好。相反,如果它使用了一些很难理解的结构,那么显然理解群体就要小得多,甚至可能一个也没有。但是过程化系统极大地鼓励在开发过程中使用一些个性化的形式,因为它是目标导向的系统,实现方式就无所谓了。一个过程系统设计者可以使用任何他喜欢的逻辑划分方式,只要他能够完成即定的任务:可理解性就是在从这里开始丢失的。在形式系统中鼓励个性化显然是个极大的错误。但是面向对象系统因为强调面向领域建模一下子将程序员的飞马行空式的想象缩窄到非常小的一个范围:目标领域,而提供了极大的可理解性。因为领域模型本来就是领域内人士用来沟通的“行语”,它本来就是一种沟通界面。它的形式系统的理解人群数量显然比个性化形式系统的理解人群大得多。

面向对象与面向过程系统最大的不同是:面向过程的系统由过程组成,而面向对象的系统由对象组成。过程的逻辑是输入输出,是严格定义的系统模块。模块间则通过输入输出接口进行合作。在这种合作模式下,无论采用多么抽象的设计与编程技术,耦合都不可能得到彻底的去除。原因是在这种模式中,耦合存在于编程或设计的范式本身。要想去掉耦合,就必须连范式一起去掉。而这显然是不可能的。也就是说,在软件开发中,只要采用了面向过程的技术系统就必然是一个紧耦合的系统。这样的结果,其本身是由面向过程系统的功利性决定的而面向对象的系统正是通过从根本上推翻了软件的功利性从而建立了一种低耦合的模型。正如民主国家从根本上将个人利益摆在国家利益的前面一样,它是一种根本上的思维转变:与集权制相比,民主制通过放弃短期的国家利益而使得国家的真正组成部分---民众可以从中长期受益。而民众就是国家,民众受益了自然也就是国家受益了。然后通过这种方式实现了“国家”利益。与此类似,面向对象则是通过从根本上修改了对“软件”的定义来达到重新定义软件的目的的:软件不是为了完成某个目标而构建的实体,它跟目标没有任何关系。它只是用来指代一大堆对象也即主体的名词而已。存在的不是软件本身,而是对象。正如民主思想中的“国家即人民”的构建思想一样,在面向对象的软件开发范式中,软件即对象。软件存在是因为对象存在。而“对象存在”则是这个逻辑的终点:对象存在是因为对象存在。面向对象并没有任何最终的构建理论,因为它没有目标。一个最终构建出来的系统它要么不能工作,要么能工作。如果不能工作则持续改进,直到其可以工作。这样的工作模式,听起来怎么很象我们平常的工作模式。的确,我们平常的工作正是这样的。对于研发工作,我有个理论那就是我们所对付的就是未知。因为如果其已经是已知的,为什么还会需要这么多的程序员呢。程序员的大部分时间都是用在对付未知上面了。而对付未知,唯一的办法其实就是时间。事实上,人+时间,本身也是软件业用来衡量开发成本的一种度量。所以说这样的工作模式虽然听起来好象很平常,但实际上它却是人类工作模式在计算机中的一种映射。这说明,使用这种模式,在某个程度上,电脑其实已经开始以人的模式进行工作。,,

的确,听上去很平常的东西往往并不平常。

而相对于面向对象,一个面向过程的系统也许能从一开始就能对系统进行精确的定义与分解,但越准确的系统其应变能力越差。也就是说,其可进化性越差。。。这样的结果在西方哲学可能很难解释,但是在东方哲学中却早就解决了(老子:福兮,祸之所伏;祸兮,福之所倚)。所以对我们没有任何理解上的困难。

面向对象因为不对系统作功能划分,所以自然就没有了在面向过程范式中引起了高耦合性的接口的概念。或者说,至少,接口在这里不再是一级成员。这样的分析结果是又一个让我吃惊的地方,因为很多面向对象的文章都认为OO是面向接口的。这难免引起新的冲突:必须解决掉面向对象与面向接口的统一性问题。因为系统中显然将同时存在对象与接口,如果不能在理论上将两者统一,那么系统当然是存在问题的。。。这里暂时坚持接口是二级成员的观点。

接上。既然没有了接口,也就没有了输入输出(出现在一级成员中)。而在一个没有输入输出的系统中,自然也就没有了解耦的问题(与此恰好相反,面向对象最大的问题非但不是解耦,而是正好相反的。即如何把那些原本就是分开设计的对象给“耦合起来)。因为对象们在设计时就不是在假想它们将一起工作的基础上设计的。

是面向对象最“伟大”的地方。

它在解决一个问题(即解耦)的同时创造了恰好相反的另外一个问题。或者说,它通过创造一个与原来问题正好相反的问题解决了一个问题。。。。。。通过创造问题的方式来解决问题,这难道不是人类智慧的最佳体现吗?

(NOTE:输入输出VS林立的对象)

只有一个对象的系统一定不是面向对象的系统。比如,一支军队,一个公司,这些都是面向过程的系统:系统中的任何或每一个部分,都只为了一个目的而生。因为这些系统它们本来就只有一个目标。面向过程的系统是面向目标的系统。实际上,面向对象在初期也有少少的面向目标的特征。这就是为什么很多介绍面向对象的文章读完没有任何感觉的原因:它们并没有把面向对象当成一种软件开发模式的根本改变来论述。它们只是把面向对象作为另一种实现软件目标的系统。

我认为事实并不是那样。因为我把面向对象当成一种多主体系统。既然是面向对象,那么肯定是以对象的思维进行建模。这么做的一个肯定结果是,系统将存在多个对象。而对象即主体。所以面向对象其实就是多主体系统。

什么是多主体系统?主体的意思是,它独立于任何其它事物。它并不附属于任何事物。其实从哲学的角度考虑,主体,个体,都只是人类概念,它们并不是客观存在的事物。但是思维或语言的意义本来就只在于它是我们的一种工具。思维力与行动力一样,只是人类的工具。

既然它是工具,那么我就应该使用它。我并不同意工具或实用主义哲学,但在现在的语境下,我只能把它当成工具来使用一次。

多主体意味着思维上的根本改变。这个改变就是,当在考虑如何构建一个系统时并不以构建一个系统为目标。或者说,有些任务本身就是没有目标的系统(比如,我只是想看看这么做以后到底会发生什么。我的目标就是这个程序本身份---在这种情况下,系统以自身为目标,所以可以被视为没有目标),取而代之的是,我的目标是建立一个存在诸多主体的系统。这里的主体,有两层含义:

1,面向过程的系统实际上是没有主体的。也就是说,当在构建一个面向过程的系统时,构建者即是主语。系统所做的任何事情是谓语。系统本身并不完整。因为其缺乏主语。系统所完成的任何工作,只能被视为由构建者完成的。因为在这样的系统中,系统的全部工作其目标就是为了完成设计者的目标。根据系统所处的位置,规划者从构建过程的最开始就已经决定了系统的目标。也就是说,在这样的系统中,系统为构建者工作。因为系统中不存在任何主语。这样的系统在完工以后,一旦存在任何改变,都会要求对系统的更改。因为系统没有主语,自适应等等所有的工作都无法,至少在正常的语义上,无法完成。相反,在面向对象的系统中,因为已经将主语从系统设计者的脑中移到系统中,系统显然一方面在逻辑上更完备(因为所有系统设计者脑中存在的概念已经被原封不动地转移或被实现到系统中),另一方面则因为主语的存在将具有更强的环境或变化适应力(因为原来的无主语系统其工作模式是:如果改变发生,那么我将改变某个模块。所以这个设计是良好的!?但是有主语系统的工作模式是:主谓系统本身将解决大部分的应变与鲁棒性问题(因为主谓系统是一种更完备的逻辑形式------证据就是人类本身的应变能力));

2,称其为主体,是因为其并不为其它对象存在。它甚至并不为系统而存在。它存在于系统中,是因为它存在于客观世界中(由此也可见,面向对象设计的根据是模拟客观世界的解决方案,而不是提出自己的解决方案------也即在设计以前,我并不知道问题是怎么解决的。我也没有问题到底应该怎么解决的任何想法或前提。我使用它,是因为在现实世界中,类似的东西解决了问题------这个跟神经网络的工作逻辑其实差不多:神经网络并不知道问题到底是怎么解决的,也就是说,它对于解决问题并没有任何理论------从这一点上,也可以很容易看出面向对象与面向过程的区别:面向过程的步骤化,其实就是一种逻辑化方案:它将问题划分成多个子问题,然后逐个解决。当所有子问题都解决以后,(总)问题自然就解决了。这是一种典型的逻辑化思路------但现实世界并不总是逻辑的。日常生活中就存在很多逻辑束手无策的领域,如音乐、美术。在构建这样的系统时,只有一种办法,就是主体建模。不过这样的结论并不影响将面向对象应用到可以或已经逻辑化的领域,因为前面讲过,面向对象只是一种方案。所以在遇到可以同时使用逻辑化与非逻辑化处理两种方案时但非逻辑化方案显然优于逻辑化方案时,显然它应该被优先采用)。它具有独立的存在权。也就是说,在真正的面向对象设计阶段,考虑的并不是如何完成任务,而是主体"是"什么。因为面向对象的系统并不是目标导向的系统。它是面向主体建模的系统。它的目标永远都只有一个:形式化真实的物理世界。并且这里还要注意的是,被形式化的对象只能是物理对象。因为前文讨论过,人类思维中的概念有很多种,对象只能概括其中的一小部分。很多其它概念如幸福,科学,或痛苦等等,这些跟对象都没有任何关系。但是对象对于描述真实的物理对象本身即唯物主义中的真正的思维对象却是足够的。因为所有的物理对象都是对象。事实上,object这个词本身就带有很重的唯物主义味道。它的语义在很大程度上其实依赖于对外部世界其客观性的承认或者说唯物主义的意识形态。

面向对象从面向主体建模中得到的最大好处是:真实世界的主体,它拥有应变能力。这种应变能力,几乎等同于设计师或程序员本身的应变能力。比如,如果需求的确发生变更,那么设计师将会对程序进行修改。

 

不面向目标的另一个好处是, 系统变成一个更稳定的松耦合系统. 这一点也可以从军队或公司系统的结构看出来. 所有军队或公司都是紧耦合系统.  因为在公司或军队的内部, 所有职能单位的存在都具有非常明确的目标性. 而面向对象则因为逻辑不同所以产生了一种完全不同的效果: 对象之所以存在是因为对象它存在. 对象不因为任何别的事物而存在. 至于目标是怎么完成的, 它并不知道. 这个答案必须从真实世界中去寻找. 系统本身不回答这样的问题, 也不研究这样的问题. 系统本身只做一件事情, 那就是照搬现实世界的案例. 照搬现实当然不可能总是最好的方案, 但它却是一个最灵活的方案. 也更(完整地. 因为面向过程显然也不是什么其它生物的思维模式. 它也是人类的一种思维模式. 只不过这种方式相对面向对象, 所能承载的东西更少而已0000-0--比如, 它没有主语?)符合人类的思维模式.  使用面向过程的思路可能构建出非常好的方案, 但是这样的方案不管是对当前目标的耦合性还是自身内部的耦合性也非常高. 这是造成软件进化困难的根本原因. 因为软件进化与自然进化在本质上其实是一样的, 都是一种环境适应能力. 环境适应性需要经历长期的优胜劣汰得到, 如果软件开发者一直陷在解耦的泥潭中不得解放, 如何能把心思放到对软件进化的研究中来呢?

在面向过程的系统中, 每一个过程都只不过是系统的一个螺丝钉. 也就是说, 面向过程系统中的组成单元除了职能性, 不具有任何其它属性. 但在面向对象的系统中, 其组成单元对象因为是一个独立存在的个体, 所以可以拥有任何属性. 也正是这些属性构成了对象的独立性.

说面向对象的系统是自顶向下的或自底向上的都不对,因为面向对象的系统不是一个面向目标的功能分解系统。它是一个主体系统。它不是通过直接考虑职能来实现系统的。它的思路是,在更高的层次即主语层次而不是主语的职能属性上来考虑问题。它所考虑的唯一对象就是“对象”。而在一个对象系统中,所有的对象都是客观存在物,其本身并不存在相互的附属性。所谓的相互附属或依赖性,都不在对象的讨论范围内。因为Object意味着客观物理存在,而相互附属或依赖性这些东西都不是objective的,它们全是subjective即主观的概念。面向对象其实本身意味最大的就是从主观向客观的转移。也就是说在使用面向对象的思维构建系统时,并不考虑对这个系统的评价或任何其它主观因素如职能,因为它们都是主观的。取而代之的是一种客观思维,即一种描述性思维,其思维重点是对象本身到底是怎么样的,而不是对象好不好。这是面向对象与面向过程的最大区别:面向过程是在一种主观思维环境下进行的,而面向对象则是在一种完全客观的思维环境下进行的。在这种思维环境下,我并不评价我所构建单元的优劣,我所做的一切即描述系统的描述对象。一旦我完成了描述整个系统,我也就完成了系统的构建。

所以可以说,在使用面向对象的思维进行系统分析或设计时,相比于面向过程的功利性构建它更象一个艺术思维与创作过程。艺术当然也可以功利(就如其实面向对象的最终目的当然也是功利的),但其过程却是不功利的。而且也只有通过一个不功利的过程才可能创作出真正好的艺术。这就是为什么艺术总是强调原创的原因,因为只有原创者,才能进行真正的非功利创作。原因是,只有原创者才能或最完整地描述自己的描述对象,或者说,甚至是“知道”自己的描述对象。这也是为什么面向对象的分析工作要求对领域的深入分析的原因(相反地,面向过程则不需要这么做------面向过程的思路是,别跟我说你们是怎么工作的,请告诉我你想让系统完成什么------这也是传统的需求分析为什么喜欢追根问底的原因,,这种分析模式往往在需求分析阶段把客户逼向绝境,然后在产品验收阶段又被客户逼向绝境。这样当然不好)而面向过程的分析可以在完全不了解领域对象的情况下完成的原因:面向过程的关注点只有一个,那就是“功能”。功能是一个外部概念,所以面向过程设计出来的东西全部都是内外高度耦合的系统。这样的系统,怎么可能拥有应变的能力?它也许可以在构建期缩减不少的企业成本(这可能就是它流行的原因------快速实现或实施显然意味着更低的开发期成本),但却几乎不具有任何应变或进化能力。这有点象请求-线程的多任务处理模型,它们都因为太僵硬所以失去了弹性。在系统设计中进行内外分离很重要---首先,它带来了设计上的自由性这给了系统很大的可“能”性。其实面向接口的思想只是这种思想在编码设计工作中的一种应用。因为这种思想其实在很多地方都有应用,即使人们并没有意识到它的存在;其次它更安全,并且在系统发生变更时带给系统原有元素更好的可复用性---内部元素不直接对应外部元素的一个好处是,它不需要随外部元素的改变而改变。因为它从设计一开始就并不依赖于外部元素而存在。

注: 本文所指对象, 非数据对象, 也非职能对象, 指的是作为系统组成单元的对象. 它在概念上其实有点象"人". 比如, 不管是好人还是坏人他都必须首先是自由的, 然后才可能是人. 一个对象也必须首先是自由且独立的,  然后才可能是一个对象.  不自由的不是对象, 附庸品不是对象(它是属性或者, 过程(在面向过程的开发模式中)), 只有在真正具有了独立存在的能力以后, 它才算得上是一个真正的对象. 实际上生活中的对象正是如此, 比如一块石头, 它就是独立的,一滴水也是独立的。

我讨论面向对象的动机有两个:一是当前的设计任务,一是长期的软件进化。可以看出这是一种将论域按时间进行划分的逻辑方法:即按现在的系统特性和以后的系统特性来进行划分。我以客观的眼光或方法来构建系统的结果并不影响我以主观的眼光对它进行评判。那么,我现在就要进行我的评判。

通常,系统的当前特性包括可理解性,性能,正确性,环境友好性,用户友好性(这两者好象已经属于政治问题了,,但是,难道政治真的不重要吗),健壮性等等。系统的未来特性则包括可扩展性,灵活性,可伸缩性,可进化性。

面向对象对正确性,环境友好性,健壮性好象没什么太大的帮助(这可能就是它为什么事实上从来没有真正流行过的原因---至少在国内,我观察的结果是这样的---因为国内的软件构建水平就只在当前特性,甚至很多连当前特性也不考虑),它的主要帮助集中在未来特性。因为面向过程同样可以得到很好的短时正确性或健壮性。事实上,一个经过良好设计与测试的过程系统一样可以得到非常好的健壮性。但是可理解性在过程系统中永远是个问题。因为它没有主语。理解这样的系统需要大量的大脑周期,因为它没有主语所以理解者必须在大脑中建立“假设”的主语,然后才能对它进行逻辑思考。也就是说,这样的系统在逻辑上是不完整的,在逻辑上是一个没有完成的系统。这种不完全的形式化表达,不适合于应用开发。当它处于系统底层时,也许反而工作得更好,但一旦进入真正的逻辑环境,它的缺点便暴露无遗。这可能正是面向对象的兴起时间跟软件商用的大量兴起时间很相近的原因。因为逻辑完整性是应用层的问题而不是系统层的问题。系统层因为高度的复用它考虑更多的当然不是其可理解性,而是应用支撑的能力。

自治-->进化

转载于:https://my.oschina.net/digerl/blog/33810

你可能感兴趣的文章
使用mvc时,在视图view中使用强类型视图,在web.config文件中添加命名空间namespace的引用不起作用,解决方法...
查看>>
开启mysql慢查询日志
查看>>
jquery遍历DOM方法总结
查看>>
关于ISDN
查看>>
swoole安装报错详解 mysqlnd_find_charset_nr in Unknow
查看>>
@interface注解类、 @Target:注解的作用目标 @Retention
查看>>
软件工程第一次阅读作业
查看>>
Slides使用
查看>>
java并发下订单生成策略
查看>>
软件工程概论总结
查看>>
Linux 进程退出后自动启动
查看>>
通用类 ImagesHelper 图片操作:生成缩略图、添加水印、截取图片等
查看>>
转 重载、隐藏和覆盖的区别
查看>>
JMeter安装
查看>>
EJB3.0 EJB开发消息驱动bean
查看>>
Example010实现浏览器兼容改内容的函数,自写
查看>>
句柄和指针
查看>>
C语言重写网络发送/接收封包
查看>>
Ubuntu18.04下make menuconfig缺少ncurses库
查看>>
C++实现矩阵的相加/相称/转置/求鞍点
查看>>