人们经常会听到OOP自然地与人们对世界的看法相对应。但是我强烈反对这样的说法:我们(或者至少我)根据遇到的事物之间的关系来概念化世界,但是OOP的重点是设计单个类及其层次结构。

注意在日常生活中,关系和动作主要存在于对象之间,这些对象本来是OOP中无关类的实例。这样的关系的示例是:“我的屏幕在桌子的顶部”; “我(一个人)坐在椅子上”; “道路上有汽车”; “我正在键盘上打字”; “咖啡机烧开水”,“文本显示在终端窗口中。”

我们用二价(有时是三价,例如“我给你送花”中的)表示动词,其中动词是对两个对象进行操作以产生某种结果/动作的动作(关系)。重点放在行动上,两个(或三个)[语法]对象具有同等的重要性。

与OOP相比,您首先必须找到一个对象(名词)并告诉它执行一些操作。对另一个对象的动作。思维方式从对名词进行操作的动作/动词转变为对名词进行操作的名词-好像一切都是被动或反身的声音所说的,例如“文本正在终端窗口中显示”。或“文本在终端窗口上绘制”。

不仅焦点转移到了名词上,而且一个名词(我们称其为语法主语)比其他名词(语法对象)具有更高的“重要性”。因此,必须决定是说terminalWindow.show(someText)还是someText.show(terminalWindow)。但是,当一个人真正表示show(terminalWindow,someText)时,为什么要给这些琐碎的决定加重负担却又没有任何操作后果呢? [结果在操作上无关紧要-在这两种情况下,文本都显示在终端窗口上-但在类层次结构的设计中可能会非常严重,并且“错误”的选择可能会导致代码混乱且难以维护。]

因此,我认为进行OOP(基于类,单调度)的主流方法很困难,因为它是不自然的,并且与人类对世界的看法不符。 CLOS的通用方法更接近于我的思维方式,但是,可惜,这并不是一种普遍的方法。

鉴于这些问题,如何/为什么会发生这种情况,为什么目前主流的OOP方式变得如此?流行?而且,如果可以的话,可以做什么呢?

评论

OOP用于“编程”,是供编译器使用的。这不是以任何方式对现实世界建模的方法。在教授OOP的过程中,通常使用诸如动物类和矩形类之类的真实示例,但这只是简化概念的示例。不幸的是,编程语言和范式以非进化和非科学的方式“发生”。除了少数例外,语言设计过程通常是少数人的最佳猜想之子!

我不同意“ OOP的重点是设计单个类及其层次结构”这一说法。由于可能是OOP的某些实现的重点,但是例如,我发现动态OOP语言通常没有大型的层次结构甚至类。好吧,OOP的定义将来可能会更改,甚至尝试更改一个对象wcook.blogspot.com/2012/07/proposal-for-simplified-modern.html

OOP正在标识系统中的对象,并基于这些对象构造类。并非相反。这就是为什么我也不同意“ OOP的重点是设计单个类及其层次结构”的原因。
的重复项:面向对象编程是否真的可以模拟现实世界?

我认为这是一个非常主观的问题,并且充满关于OOP以及“现实世界”是什么以及人们如何思考问题的怪异假设。最后,它甚至问:“还有什么方法可以废除它呢?”这确实表明,OP对此有非常强烈的意见。如果您对编程范例是“宗教的”,我想您不需要任何答案...您已经知道您想听什么。如果我第一次问这个问题时就知道,我可能会投票关闭它。

#1 楼

OOP对于某些问题是不自然的。这样的程序。所以功能。我认为OOP有两个确实使它看起来很难的问题。




有些人的行为就像是编程的唯一方法,而所有其他范例都是错误的。恕我直言,每个人都应该使用一种多范式语言,并为他们当前正在处理的子问题选择最佳的范式。您的代码的某些部分将具有OO样式。有些将起作用。有些将具有直接的程序样式。有了经验,很明显哪种范例最适合:

a。 OO通常最适合于您的行为与行为所依赖的状态紧密相关,并且状态的确切性质是实现细节,但是状态的存在不能轻易抽象出来。示例:集合类。

b。当您有一堆行为与任何特定数据没有强烈关联时,过程式方法是最好的选择。例如,也许它们对原始数据类型进行操作。在这里将行为和数据视为单独的实体是最容易的。示例:数字代码。

c。当您拥有相当容易声明式编写的东西,从而任何状态的存在都可以很容易地抽象出来的实现细节时,功能是最好的。示例:映射/减少并行性。

OOP通常在大型项目中很有用,因为在大型项目中,确实需要封装良好的代码段。在初学者项目中,这种情况不会发生太多。


评论


我认为这个问题的重点不是OOP是否自然,而是面向OOP的主流方法是否是最自然的OOP方法。 (仍然是个好答案。)

–乔治
2011-09-21 19:11



“ OOP通常在确实需要封装良好的代码段的大型项目中显示其有用性。”:但这不是OOP的特定属性,因为对于命令式,功能式,...编程语言也有很好的模块概念。 。

–乔治
2011-09-21 19:27



OOP确实位于过程/功能的不同轴上;它解决了如何组织和封装代码,而不是如何描述操作。 (您总是将OOP与执行范例配合使用。是的,有OOP +功能语言。)

–研究员
2011-09-22 21:33

难道不是说OOP只是我们将程序性内容放入其中的盒子吗?

–埃里克·雷彭(Erik Reppen)
2012年8月2日,下午2:25

在OOP中,您仍然可以编写方法。是什么使OOP弱于过程编程?

– Akcakaya专家
2012年8月2日在6:39

#2 楼

恕我直言,这是个人品味和思维方式的问题。我对OO没什么问题。


我们(或者至少我)根据我们遇到的事物之间的关系来概念化世界,但是OOP的重点是设计单个类和其层次结构。


恕我直言,虽然可能是一种普遍的看法,但事实并非如此。 OO术语的发明者Alan Kay始终强调对象之间发送的消息,而不是对象本身。消息,至少对我来说,表示关系。


请注意,在日常生活中,关系和动作主要存在于对象之间,这些对象本来是OOP中不相关类的实例。


如果对象之间存在关系,则根据定义它们是相关的。在OO中,您可以用两个类之间的关联/聚合/用法依赖关系来表示它。


我们用二价(有时是三价)来思考,例如“我给了你花”)动词,其中动词是对两个对象进行操作以产生某种结果/动作的动作(关系)。重点是行动,两个(或三个)[语法]对象具有同等的重要性。


但它们在上下文中仍具有其明确定义的角色:主题,对象,动作等。“我给你花了”或“你给我花了”是不一样的(更不用说“花给我了花” :-)


与OOP首先需要找到一个对象(名词),然后告诉它对另一个对象执行某些操作。思维方式从对名词进行操作的动作/动词转变为对名词进行操作的名词-好像一切都是被动或反身的声音所说的,例如“文本正在终端窗口中显示”。或“文本在终端窗口上绘制”。


我不同意这一点。恕我直言,英语句子“ Bill,go the hell”在程序代码中更自然地读为bill.moveTo(hell)而不是move(bill, hell)。实际上,前者实际上更类似于原始的主动语音。


因此,必须决定是说terminalWindow.show(someText)还是someText.show(terminalWindow)


同样,要求终端显示一些文本或要求文本显示终端也不相同。恕我直言,很显然哪种方法更自然。


考虑到这些问题,为什么/为什么当前流行的OOP方式如此流行?


也许是因为大多数OO开发人员对OO的理解与您不同?

评论


+1,直接提到对象之间的消息及其重要性,来自Alan Kay

–废纸t
2011年3月18日在12:41

@zvrba,的确,还有其他面向对象的先驱,但这不在本文讨论范围之内。 “最自然的事情是要求显示文本。” -现在您使用的是您声称在OOP中是如此“不自然”的被动语音。

–彼得·托克(PéterTörök)
2011-3-18在22:32

@zvrba,您说“总是有一个“代理人”在做一些事情”,但抗议OO方法来识别和命名这些代理人(对象),并以该语言将其作为头等公民来对待。对我来说,这是对问题域进行建模的一部分-无论如何,您都需要进行这项工作,然后根据您的语言是否是面向对象的,然后将生成的域模型以不同的方式映射到代码中。

–彼得·托克(PéterTörök)
2011年3月19日在20:18

@zvrba,它本身不是面向对象的,而是决定不同对象的角色和职责的开发人员/设计人员。使用OO方法可能会产生好坏的领域模型和设计,就像使用刀可以为您带来一片精美的面包或流血的手指一样-我们仍然不怪这刀,因为它只是一种工具。还要注意,模型中的概念/对象/代理是现实世界中事物的抽象,因此总是受限制和扭曲,仅关注特定的“有趣”方面。

–彼得·托克(PéterTörök)
2011年3月20日在20:19



@zvrba,汽车的确不会按照自己的意愿启动-就像Car对象只有在某人显式调用其方法时才会启动()一样。

–彼得·托克(PéterTörök)
2011年3月20日在20:23

#3 楼

一些程序员觉得OOD很难,因为那些程序员喜欢思考如何为计算机解决问题,而不是思考如何解决问题。


...而是OOP的重点正在设计各个类及其层次结构。


OOD与此无关。 OOD就是要弄清楚事物的行为和相互作用。


我们用二价(有时是三价,例如“我给你送花”一词)动词来思考是对两个对象进行操作以产生某种结果/动作的动作(关系)。重点放在动作上,两个(或三个)[语法]对象具有同等重要的意义。


始终把重点放在动作上,其中动作是对象的行为。没有它们的行为,物体就什么也不是。 OOD的唯一对象约束是一切都必须由某事完成。

我认为做事者比完成某件事更重要。


但是,当一个人真的要显示(terminalWindow,someText)时,为什么要给这些琐碎的决定加重负担却又没有任何操作后果呢?


对我来说,这是同一回事,只是符号不同。您仍然必须决定谁是表演者,谁是表演者。知道了这一点之后,OOD就不会再做决定了。 Windows显示文本-> Window.Show(text)。

那里很多东西(尤其是在旧版区域)说不是OO。例如,有大量的C ++代码没有实现OOD图。

一旦您摆脱了要解决计算机问题的观念,OOD就很容易。您正在为做事的事情解决问题。

评论


我不完全喜欢OOD,因为我更喜欢思考如何解决问题。我不想考虑如何将问题域的自然语言转换为对象,消息,继承等外来世界。我不想发明不自然存在的分层分类法。我想用自然语言描述问题,并以最简单的方法解决它。而且,顺便说一句,世界不仅仅是由“做事的东西”构成的。您对现实的看法极为狭窄。

– SK-logic
2011年3月18日在13:22

@Matt Ellen,我编写了一些程序来模拟不是“事物”并且没有“做”任何“东西”的实体的行为。任何不可变实体都不做任何事情。任何数学纯函数都不会做任何事情-仅仅是从一组到另一组的映射,而这个世界主要由此类函数来描述。任何逻辑形式主义都不会“做”任何事情。是的,OOD不会对我有帮助,因为我能够使用很多很多更强大的抽象和模型。回到原始的,有限的,有限的OOD将会严重阻碍我。

– SK-logic
2011年3月18日在17:44



@Matt Ellen,是的,我希望看到引用支持这样奇怪的说法,即世界最好被视为“做事的事物”或“通过消息进行交互的对象”的集合。这是完全不自然的。接受任何科学理论(因为在这个阶段,它们都尽可能地接近对现实世界的建模),并尝试使用您的术语对其进行重写。结果将是笨拙和尴尬的。

– SK-logic
2011-3-18在17:47

@ Antonio2011a,没有一个编程或建模范例可以有效地覆盖所有可能的问题领域。 OOP,功能,数据流,一阶逻辑等等,它们都是特定于问题领域的范例,仅此而已。我只是在提倡多样性和思想开放的方法来解决问题。将您的思维范围缩小到一个范例只是愚蠢的。 en.wikipedia.org/wiki/Language-oriented_programming是最接近通用方法而不是将您限制在单个语义框架上的方法

– SK-logic
2012年1月3日上午10:37

@Calmarius为什么会让计算机编程更轻松?那真是愚蠢。是人类必须付出更大努力。

–马特·艾伦(Matt Ellen)
2012年8月1日在21:14

#4 楼

也许,我无法理解这一点,但是:

阅读有关OOP的第一本书(90年代初,Borland编写的Pascal精简手册),我对它的简单性和潜力感到惊讶。 (以前,我一直在使用Cobol,Fortran,汇编语言和其他史前语言。)对我来说,很清楚:狗是动物,动物必须吃,我的狗是动物。狗,所以它一定要吃...

另一方面,编程本身固有地是不自然的(即人工的)。人的言语是人为的(不要怪我,我们都从别人那里学习了我们的语言,没有人认识发明英语的人)。一些科学家认为,人的思想是由他首先学习的语言形成的。

我承认,现代面向对象语言中的某些构造有些笨拙,但这是进化。 >

评论


从cobol到fortran,再到组装(及其余),您的工作到底是什么?

–浏览
2011-3-18在11:15



顺序错误。实际上,我一直是从Basic开始的,然后是Fortran,然后是Assembly和Cobol(是的,这是正确的顺序:首先是Assembly)。我生命中的第一台计算机是一个“巨大的”大型机,内存为256kB,在其控制台上打字,并向打孔卡供电,因为我是计算机的操作员。当我成长为一名系统程序员之后,一个叫做PC-AT的可疑东西落在了我的办公桌上。因此,我沉迷于GW-Basic,Turbo-Pascal等。

– Nerevar
2011年3月18日在17:55

我不是那个人。更多关于您的工作领域;因为我认识的人(真正的人)不多,涉及过COBOL(面向业务),fortran(科学领域),汇编程序(更多面向CS)以及其他人员。尽管如此,他们还是不是专业程序员。

–浏览
2011年3月20日12:00

毫无疑问:加入之前已经决定使用语言方法的团队和项目。以及对他们使用的工具的好奇心。

– Nerevar
2011年3月21日在11:29

#5 楼

让我感到难过的一件事是,我认为OOP就是要对世界建模。我以为,如果我做错了,可能会有些东西咬我(事情是对的还是不对的)。我非常意识到假装一切都是对象或实体的问题。这使我对OOP中的编程感到非常的尝试和信心不足。

然后,我阅读了SICP,并有了新的认识,那就是它实际上是关于数据类型和控制对它们的访问。我解决的所有问题都是基于错误的前提,那就是在OOP中您正在建模世界。

我仍然惊叹于这种错误前提给我带来的巨大困难(以及我如何看待它)。

评论


感谢您指出尝试建模世界的危险。

– Sean McMillan
2011-09-22 13:58

#6 楼

是的,OOP本身是非常不自然的-现实世界并不完全由层次分类法构成。它的一些小部分是由这些东西组成的,而这些部分是唯一可以用OO充分表达的东西。所有其他自然不能适应这种琐碎而有限的思维方式。看看自然科学,看看发明了多少种不同的数学语言,以便以最简单或至少可以理解的方式表达现实世界的复杂性。而且几乎没有一个可以轻松地翻译成对象和消息的语言。

评论


好吧,这对于试图精确描述现实世界的任何形式的表示法也同样适用。

–彼得·托克(PéterTörök)
2011-3-18在10:50

@PéterTörök,正是我的意思。没有一种形式主义可以涵盖所有内容。您必须全部使用它们,因为它们令人恐惧。这就是为什么我相信面向语言的编程的原因-它允许将各种通常不兼容的形式主义引入到坚实的代码实体中。

– SK-logic
2011-3-18在10:58

一切都可以归类为分层分类法。诀窍在于提出有意义的方案。通常涉及多重继承。软件与现实世界之间的最大区别是,在现实世界中,我们经常不得不推断或发现分类方案;在软件中,我们发明了它们。

–卡莱布
2011年9月22日下午16:20

通过使用“层次分类法”之类的术语,我认为您正在考虑继承。继承确实很难推理。这就是为什么人们建议使用合成而不是继承。

–坦率的剪毛
2011-09-22 17:47

@弗兰克:现实世界中有许多类型的层次分类法,其中继承只是其中一种。正确地完成所有这些工作需要比OOP更好的工具(例如,本体论推理),并给哲学家造成了数千年的困扰……

–研究员
2011-09-22 21:38



#7 楼


我们(或至少是我)根据遇到的事物之间的关系来概念化世界
,但是OOP的重点是设计单个类及其层次结构。


您是从(IMO)开始的错误前提。可以说,对象之间的关系比对象本身更重要。这些关系提供了面向对象的程序结构。继承,即类之间的关系,当然很重要,因为对象的类决定了该对象可以做什么。但是,由各个对象之间的关系决定对象在类定义的范围内实际执行的操作以及程序的行为。

起初,面向对象的范例可能很困难,不是因为很难想出新的对象类别,但是因为很难预见对象图并了解它们之间的关系,尤其是当您没有描述这些关系的方法时。这就是设计模式如此有用的原因。设计模式几乎完全是关于对象之间的关系的。模式既为我们提供了可用于在更高层次上设计对象关系的构造块,又为我们提供了可用于描述这些关系的语言。

对于在物理世界。任何人都可以将一堆房间拼凑成一栋建筑物。房间甚至可能都配备了所有最新的装备,但并不能使建筑正常工作。建筑师的工作是根据使用这些房间的人的需求和建筑物环境优化这些房间之间的关系。从功能和美学的角度来看,使这些关系正确是使建筑工作的原因。
如果您不习惯OOP,建议您多考虑一下您的对象如何组合在一起以及它们的职责如何安排。如果您还没有阅读过,请阅读有关设计模式的信息-您可能会意识到,您已经了解了所阅读的模式,但是给它们起名字将使您不仅可以看到树木,而且还可以看到看台,林木,灌木丛,树林,树林,林地,最后是森林。

#8 楼

这只是OOP错误的一部分。

本质上,函数成为二等公民,这很糟糕。

现代语言(ruby / python)不会会遇到此问题并提供作为一流对象的功能,并允许您在不建立任何类层次结构的情况下制作程序。

评论


OOP对我来说似乎很自然,实际上我很难以任何其他方式考虑编程任务。尽管如此,多年来,我逐渐了解到,OOP倾向于过分强调名词而不是动词。来自2006年的这句话使我理解了这一区别:steve-yegge.blogspot.com/2006/03/…

–吉姆·德州(Jim In Texas)
2011-09-22 17:49

#9 楼

OOP不难。很难很好地使用它的原因是对它的好处有一个浅浅的了解,在这种情况下,程序员会听到随机的格言,然后屏住呼吸重复自己,以得到神圣的四人帮,祝福的马丁·福勒(Martin Fowler)的祝福。他们正在读的其他人。

#10 楼

编辑

首先,我要说的是,我从未发现OOP比其他编程范例更难或更难。编程天生就很难,因为它试图解决现实世界中的问题,而现实世界则极其复杂。另一方面,当我阅读此问题时,我问自己:OOP是否比其他范式“更自然”?因此更有效吗?

我曾经找到一篇有关命令式编程(IP)与面向对象编程之间的比较研究的文章(希望我能再次找到它,以便将其作为参考)。 (OOP)。他们基本上测量了在不同项目中使用IP和OOP的专业程序员的生产力,结果是他们没有看到太大的差异。因此,他们声称两组之间的生产率没有太大差异,真正重要的是经验。

另一方面,面向对象的拥护者声称,在系统OOP的早期开发甚至可能比紧迫性花费更多的时间,从长远来看,由于数据和操作之间的紧密集成,代码更易于维护和扩展。

我主要使用OOP语言(C ++,Java),但我常常觉得即使从未在大型项目中尝试使用Pascal或Ada,我也可以达到同样的生产力。


与OOP相比,您首先必须找到一个对象(名词)
并告诉它对另一个对象执行某些操作。


[cut]


因此,我认为进行OOP的主流方法是困难的,因为它是不自然的,并且不符合人们对工作原理的看法。 rld。 CLOS的通用
方法更接近我的思维方式,但是,可惜,这不是广泛的方法。


当我更仔细地阅读了最后一段时,我终于理解了您问题的要点,我不得不从头开始重写我的答案。 :-)

我知道其他面向对象的提议,其中多个对象接收一条消息而不是仅接收一条消息,即,多个对象在接收消息时起着对称的作用。是的,对我来说,这似乎是一种更通用,更自然(不太严格)的面向对象操作方法。

另一方面,可以使用“单个调度”和“单个调度”轻松模拟“多个调度” ”更易于实现。也许这就是“多重派遣”尚未成为主流的原因之一。

#11 楼

停止寻找专门的OOP范例,并尝试使用一些JavaScript。

我目前有一种解决方案,其中UI对象在事件驱动的界面下运行。也就是说,我将拥有一个看起来像是典型的公共方法,该方法在被触发时会导致内部定义的操作。但是当它被触发时,真正发生的是我在对象本身上触发了一个事件,并且该对象内部的预定义处理程序做出了响应。该事件和可以附加属性的事件对象可以传递给任何其他侦听器,任何关心侦听的事物都可以听到。您可以直接侦听该对象,也可以大致侦听该事件类型(事件也会在该通用对象上触发,该对象由工厂构建的所有对象都可以侦听)。因此,举例来说,我现在有一个组合框,您可以从下拉列表中选择一个新项目。 comboBox知道如何设置自己的显示值并根据需要更新服务器,但是我也可以根据需要收听其他任意组合框,以换出与当前值绑定的选择列表。第一个组合框。

如果需要,(我很惊讶地发现我通常不想要-这是易读性问题,当您看不到事件的来源时)可以具有完全的对象分离,并通过传递的事件对象建立上下文。无论如何,您仍然可以通过注册多个响应者来避开单调度。

但是我并不是仅靠OOP来做到这一点,并且从某些定义上来说,JS甚至都不是“正确的” OOP。我觉得好笑。在我看来,对于更高级别的应用程序开发而言,适当的力量是可以将范式转变为适合您的情况的一切,并且如果我们愿意的话,我们可以很好地模拟类。但是在这种情况下,我将功能方面(传递处理程序)与OOP混合在一起。

更重要的是,我的感觉很强大。我不是在考虑一个对象作用于另一个对象。我基本上是在决定对象关心的事情,为它们提供所需的工具,以便将它们整理出来,然后将它们放入混合器中,并使它们相互反应。

所以我猜我在想什么我的意思是:这不是switch语句的问题。它是混合搭配。问题是语言和时尚希望您相信这是一回事。例如,初级Java开发人员如何认为OOP在默认情况下总是做得正确呢?

#12 楼

向我解释的方式是用烤面包机和汽车。两者都有弹簧,所以您会有一个“弹簧”对象,它们的大小,强度和其他功能都不同,但是如果您有很多轮子,它们都将是“弹簧”,然后将这个比喻扩展到汽车上(很明显,车轮,再加上方向盘等),这很有道理。

然后您可以将该程序视为一个对象列表,并且比“可以做事的东西的列表,所以这与您之前看到的指令列表不一样。“

我认为OOP的真正问题在于如何向人们解释。通常(在我的uni类中)我看到它的解释是说“这是关于许多类的事情,而您可以从中创建对象”,这会使很多人感到困惑,因为它使用的是本质上抽象的东西用来解释这些概念的术语,而不是人们在五岁时与乐高玩耍时已经掌握的具体想法。

评论


弹簧有数以百万计的形式,所有形式都具有相似的功能。我会说这是函数式编程的完美示例。

–l0b0
2011-3-18在11:12

#13 楼

这是通过分类思考世界的自然方法。或多或少是面向对象的。 OOP很难,因为编程很难。

评论


但是,您是否根据某些对象具有共同的属性或共同的行为进行分类?所有有名字和姓氏的人都是人吗?走路的动物都是动物吗?

– zvrba
2011-3-18 14:03

当涉及分类时,能够执行某种行为是一种属性。斑马和马可以繁殖,但后代是杂种。除非您知道它们不是同一物种,否则很难根据拥有的交配功能来预测此结果。

– JeffO
2011-3-19在0:26

@zvrba:我对评论中提出的问题的回答是,这无关紧要。每个有名字和姓的东西都是每个程序中只关心人的人。对于任何不了解人或非人的程序,它都是IHasNameAndSurname。对象只需要解决眼前的问题。

–汤姆·W
2011年9月22日在16:24

@Jeff O即使在相同的物种/品种/人口中,也存在变异,没有理想的(必要的)例子。因此,是的,OO并非自然界那样,但这很适合人类的自然思维。

– Tom Hawtin-大头钉
2011年10月5日在8:20

#14 楼

我认为当人们尝试使用OOP表示现实时会遇到一些困难。大家都知道汽车有四个轮子和一个引擎。大家都知道汽车可以Start()Move()SoundHorn()

当我意识到自己应该一直停止尝试这样做时,我的脑海里发出了光芒。对象不是与其共享名称的东西。对象是(即应该是)与问题范围相关的足够详细的数据分区。它完全可以完全解决问题所需的解决方案。如果使一个对象负责某种行为导致代码行多于某些含糊的第三方(某人可能称其为“ poltergeist”)的行为,则该poltergeist赢得了筹码。

#15 楼

为了管理复杂性,我们需要将功能分组到模块中,这通常是一个难题。就像关于资本主义的古话一样,除我们尝试过的所有其他方法外,OOP是在那里最糟糕的组织软件的系统。

将交互作用归为名词的原因是,尽管经常发生关于将两个名词分组在一起的模棱两可的是,名词的数量恰好适用于可管理的大小类,而按动词分组往往会产生非常小的类(如一次性),或者会产生非常大的类。功能像表演。当按名词分组时,诸如继承之类的重用概念也更容易解决。

此外,在实践中,决定是在窗口中显示还是在文本中显示的问题几乎总是比在实践中更为清晰。理论。例如,几乎所有GUI工具包组都随容器一起添加,但随窗口小部件一起显示。如果您尝试以另一种方式编写代码,即使抽象地思考这两个方法似乎是可以互换的,其原因也会很快变得显而易见。

评论


您见过合适的模块系统吗?怎么说OOP是最好的呢? SML模块的功能要强大得多。但是,即使没有一点OOP提示,即使是Ada包也足以满足大多数情况。

– SK-logic
2011-3-18在13:40



@ SK-logic,我认为您已经迷上了过于精确的定义。对于OOP,我不是指类,而是指对按其操作的“名词”在逻辑上对“动词”进行分组,并能够根据碰巧对其进行操作的特定名词重用和专门化这些动词。类碰巧是最著名的实现,但不是唯一的实现。我承认对SML模块的了解是无知的,但是当我查找SML模块时,看到的第一个示例是队列的实现,该队列的实现可以来自任何OO设计手册,并进行了语法更改以使其能够运行。

–卡尔·比勒费尔特(Karl Bielefeldt)
2011-3-18在14:52

不幸的OOP对于不属于它的东西给予过多的赞誉根本是不公平的。模块是一个伟大的发明。一流的模块很棒。但是OOP与它们完全无关。某些OOP语言采用了某些模块功能(最著名的是名称空间),但是模块比类具有更通用,更强大的概念。您说过课堂是“最好的”,这与事实相去甚远。一流的模块要好得多。而且,当然,类型系统比带有子类型的OO更加广泛和深入。

– SK-logic
2011年3月18日在14:57

“这就像关于资本主义的古话,OOP是在那里组织软件的最糟糕的系统,除了我们已经尝试过的所有其他东西。”:也许我们还没有尝试足够长的时间。 :-)

–乔治
2011年9月21日19:21在

我认为您的意思是“民主”:quotationspage.com/quote/364.html

–nicodemus13
2012年6月11日上午10:33

#16 楼

否。使用编程可以解决问题的方法有几种:功能,过程,逻辑,OOP等。

在现实世界中,有时人们使用功能范式,有时我们使用功能范式。程序范式,等等。有时我们混在一起。最终,我们将它们表示为一种特定的编程样式或编程范例。

LISP中也使用了“一切都是列表或项目”范例。我想提一下与函数式编程的不同之处。 PHP在关联数组中使用它。

O.O.P.和“一切都是列表或项目”范式被认为是MORE NATURAL编程风格中的2种,正如我在某些人工智能课程中所记得的那样。

听起来很奇怪,“ OOP不是自然的”学习方式或关于OOP的学习方式是错误的,但不是O.O.P.本身。

#17 楼


考虑到这些问题,为什么/为什么发生当前流行的OOP主流方式如此流行?而且,如果可以的话,
可以做些什么来使它失效呢?


OOP之所以流行,是因为它提供了比流行的过程更高的抽象层次来组织程序的工具。之前的语言。使一种语言具有方法内部的过程结构以及围绕它们的面向对象的结构也相对容易。这使已经知道如何以编程方式进行编程的程序员可以一次选择一种面向对象的原理。这也导致了很多只面向名称的OO程序,这些程序是包装在一个或两个类中的过程程序。

要废除OO,请构建一种语言,使其可以轻松地从大多数语言中逐步过渡如今,程序员已经了解了您偏爱的范例(大部分是面向过程的,带有一些OO)。确保它提供了方便的API来执行常见任务并对其进行了很好的推广。人们很快就会用您的语言制作“仅X名”程序。然后,您可以预期人们要花很多年才能熟练完成X。

评论


OP并不认为OO一般而言是不好的,应该予以废除,但是“目前主流的OOP方式”并不是最自然的方式(与“多次派发”相比)。

–乔治
2011-09-22 14:14

OP似乎也过于专注于定义类型层次结构,而最好的OO程序往往更依赖于接口和组合。如果“多重调度”是X,那么使人们逐渐学习与多重调度相关的技能的语言仍然是更改环境的关键。

– Sean McMillan
2011-09-22 14:32

#18 楼

我认为OOP和OOP语言也有问题。

如果正确理解,OOP就是关于黑匣子(对象)的黑匣子,上面有可以按下的按钮(方法)。上课只是为了帮助组织这些黑匣子。

一个问题是程序员将按钮放在错误的对象上。终端无法在其自身上显示文本,文本也无法在终端上显示其自身。可以执行此操作的操作系统的窗口管理器组件。终端窗口和文本只是一个被动实体。但是,如果我们以这种方式思考,我们就会意识到大多数实体是被动的事物,而实际上只有很少的对象可以做任何事情(或者仅仅是一个对象:计算机)。确实,当您使用C时,将其组织到模块中,这些模块代表的对象很少。

另一点是计算机只是按顺序执行指令。假设您有一个VCR和一个Television对象,您将如何播放视频?您可能会这样写:

connect(television, vcr);
vcr.turnOn();
television.turnOn();
insert(vcr, yourFavoriteCasette);
vcr.play();
while (vcr.isPlaying()) {} // Wait while the VCR is playing the casette.
vcr.eject();
vcr.turnOff();
television.turnOff();


这很简单,但是您至少需要3个处理器(或多个进程):您,第二个是VCR,第三个是电视。但是通常您只有一个核心(至少不足以容纳所有对象)。在大学里,我的很多同学都不了解为什么按钮执行昂贵的操作时GUI会冻结。

所以我认为面向对象的设计可能很好地描述了这个世界,但这并不是最好的计算机的抽象。

#19 楼

看一下MVC模式的发明者发明的DCI(数据,上下文和交互)。

DCI的目标是(引自维基百科):


在对象(名词)上方赋予系统行为一流的状态。
将用于快速变化的系统行为(系统的工作)的代码与用于缓慢变化的领域知识(系统的内容)的代码干净地分开将两者结合在一个类的界面中。
要支持一种与人们的思维模式相近的对象思维方式,而不是类思维方式。

这是一篇很好的文章,作者,如果您想看一些代码,这里是一个小的示例实现(.NET)。它比听起来容易得多,而且感觉很自然。

#20 楼


人们经常可以听到OOP自然对应于人们思考世界的方式。但是,我强烈不同意这个
声明(...)


由于几十年来在书本和其他地方传福音,我也不同意。尽管如此,我认为Nygaard和Dahl就是这样说的,我认为他们关注的是与当时的替代方案相比,设计仿真的思考有多容易。


(...),但是OOP的重点是设计单个类及其层次结构。


鉴于OOP的普遍误解,这种主张进入了明智的领域,并且OO对定义有多敏感。我在该领域有十多年的经验,从事行业工作和有关编的学术研究。语言,我可以告诉您,我花了很多年的时间来学习“主流OO”,因为我开始注意到它与早期创作者的目标有何不同(和次等)。对于主题的现代,最新处理,我将参考W. Cook的最新工作:

“关于“对象”和“面向对象”的简化,现代定义的提案
http://wcook.blogspot.com.br/2012/07/proposal-for-simplified-modern.html


鉴于这些问题,为什么/为什么发生这种情况?
主流的OOP方式变得如此流行


也许是因为QWERTY键盘变得流行,或者是DOS操作系统变得流行。在流行的车辆上,尽管它们具有某些特性,但它们却变得很流行。有时,某些东西的相似但较差的版本才是实际的东西。


完成王位吗?


使用高级方法编写程序。使用OO方法编写相同的程序。说明在重要的各个方面(系统本身的属性和工程属性),前者的属性都比后者好。表明所选程序是相关的,并且如果将其应用于其他类型的程序,则所提出的方法可以保持高质量的属性。进行严格的分析,并在必要时使用精确且可接受的定义。

最后,与我们分享您的发现。

#21 楼

以Java为例:对象是一种抽象瓶颈,大多数“事物”要么严格是对象的子组件,要么将对象用作其子组件。在这两种类型的事物之间,对象必须具有足够多的用途来构成整个抽象层-多用途意味着它们没有一个隐喻。特别是Java使对象(&类)成为您调用/调度代码的唯一层。坦率地说,对象所包含的大量内容使它们过于复杂。对它们的任何有用的描述都必须限制为某种特殊形式或受限形式。

继承和接口层次结构是将对象用作子组件的“事物”。这是一种描述对象的专门方法,而不是获得对对象的一般理解的一种方法。

“对象”可以说具有或具有很多东西,因为它们是一种多用途抽象,即“ OO语言”中的通用性。如果它们用于包含局部可变状态或访问某个外部世界状态,则它们看起来非常像“名词”。相反,代表进程的对象,例如: “加密”或“压缩”或“排序”,看起来像一个“动词”。

一些对象被用作它们的命名空间,例如在Java中放置“静态”函数的地方。

我倾向于同意Java在对象方法调用上过于繁重而对对象进行分派的论点。这可能是因为我更喜欢Haskell的类型类来控制调度。这是调度限制,并且是Java的功能,但不是大多数语言,甚至不是大多数OO语言。

#22 楼

我目睹并参加了许多有关OOP的在线辩论。 OOP的支持者通常不知道如何编写适当的过程代码。可以编写高度模块化的过程代码。可以将代码和数据分开,并确保函数只能写入自己的数据存储区。可以使用过程代码来实现继承的概念。更重要的是,过程代码更苗条,更快,更容易调试。

如果使用严格的命名约定构建单文件模块,则过程代码比OO更易于编写和维护,并且相同或更快。并且不要忘了,当您的应用程序运行时,无论脚本中包含多少个类,它始终都是程序性的。

然后,您就会遇到像PHP这样的语言,它们并不是真正的面向对象的语言,依靠黑客来伪造诸如多重继承之类的东西。影响语言方向的大人物已将PHP变成了不一致规则的拼凑而成,这些规则对于其最初的意图而言太大了。当我看到开发人员为过程模板语言编写了巨大的模板类时,我禁不住笑了。

如果将正确编写的OO代码与编写不好的过程代码进行比较,那么您总是会得出错误的结论。很少有项目需要面向对象的设计。如果您是IBM并管理着一个需要多个开发人员维护多年的大型项目,请选择面向对象。如果您正在为客户编写小型博客或购物网站,请三思而后行。

要回答最初的问题,OOP很难,因为它不解决现实生活中的编程难题,而没有采用比实际复杂100倍的解决方案。对于许多编程问题,最强大的解决方案之一是明智地使用全局数据。然而,新浪潮的大学毕业生会告诉你,这是一个很大的禁忌。仅当您笨拙的编程兔子时,全球可用的数据才是危险的。如果您有一套严格的规则和适当的命名约定,则可以使所有数据都处于全局状态。

对于任何面向对象的程序员来说,知道如何在汇编器中编写国际象棋应用程序以达到16K的最大可用内存应该是一项强制性要求。然后,他们将学习如何修剪脂肪,减少懒惰并产生巧妙的解决方案。