126

据我所知,尽管在 OOP 教育、语言和工具上花费了数百万或数十亿美元,但 OOP 并没有提高开发人员的生产力或软件可靠性,也没有降低开发成本。很少有人在任何严格意义上使用 OOP(很少有人遵守或理解 LSP 等原则);人们对问题域建模所采用的方法似乎几乎没有统一性或一致性。很多时候,这个类只是为了它的语法糖而使用。它将记录类型的函数放入它们自己的小命名空间中。

我为各种各样的应用程序编写了大量代码。尽管在某些地方,真正的可替代子类型在应用程序中发挥了重要作用,但这些地方非常特殊。总的来说,尽管很多人都在谈论“重用”,但现实情况是,除非一段代码完全按照您的意愿去做,否则几乎没有成本效益的“重用”。以正确的方式设计可扩展的类是极其困难的,因此扩展的成本通常非常高,以至于“重用”根本不值得。

在许多方面,这并不让我感到惊讶。现实世界不是“OO”,OO 中隐含的想法——我们可以用一些类分类法对事物进行建模——在我看来是非常有缺陷的(我可以坐在桌子、树桩、汽车引擎盖上) ,某人的膝盖——但其中没有一个是——椅子)。即使我们转向更抽象的领域,OO 建模通常也很困难、违反直觉,并且最终无济于事(考虑圆形/椭圆或正方形/矩形的经典示例)。

那么我在这里错过了什么?OOP 的价值在哪里,为什么所有的时间和金钱都未能让软件变得更好?

4

45 回答 45

119

现实世界不是“OO”,OO 中隐含的想法——我们可以用一些类分类法对事物进行建模——在我看来是非常有缺陷的

虽然这是真的并且已经被其他人观察到(以 STL 的发明者 Stepanov 为例),但其余的都是无稽之谈。OOP 可能存在缺陷,它当然不是灵丹妙药,但它使大型应用程序变得更加简单,因为它是减少依赖关系的好方法。当然,这只适用于“好的”OOP 设计。邋遢的设计不会带来任何优势。但是,好的解耦设计可以使用 OOP 很好地建模,而使用其他技术则不能很好地建模。

有更好、更通用的模型(想到Haskell 的类型模型),但这些模型通常也更复杂和/或难以有效实现。OOP 是极端之间的一个很好的权衡。

于 2008-08-23T14:48:10.523 回答
45

OOP 不是关于创建可重用的类,而是关于创建可用的类。

于 2008-08-23T18:04:49.520 回答
42

很多时候,这个类只是为了它的语法糖而使用。它将记录类型的函数放入它们自己的小命名空间中。

是的,我发现这也太普遍了。这不是面向对象的编程。它是基于对象的编程和以数据为中心的编程。在我使用 OO 语言的 10 年中,我看到人们大多在做基于对象的编程。恕我直言,OBP 很快就崩溃了,因为您基本上是两个词中最糟糕的:1) 程序编程没有遵循经过验证的结构化编程方法,2) OOP 没有遵循经过验证的 OOP 方法。

OOP 做得对是一件美好的事情。它使非常困难的问题很容易解决,并且对于外行(不要试图在那里听起来很浮夸),它几乎看起来像是魔术。话虽如此,OOP 只是编程方法工具箱中的一种工具。它不是万能的方法。它恰好适合大型业务应用程序。

大多数使用 OOP 语言工作的开发人员都在使用在他们日常使用的框架和类型中正确完成的 OOP 示例,但他们只是没有意识到这一点。以下是一些非常简单的示例:ADO.NET、Hibernate/NHibernate、日志框架、各种语言集合类型、ASP.NET 堆栈、JSP 堆栈等......这些都是在其代码库中严重依赖 OOP 的东西。

于 2008-08-23T16:42:45.053 回答
32

重用不应该是 OOP 的目标 - 或任何其他范式。

重用是良好设计和适当抽象级别的副作用。代码通过做一些有用的事情来实现重用,但不要做太多以使其不灵活。代码是否是 OO 无关紧要——我们重用有效的东西,而且我们自己做也不是微不足道的。这就是实用主义。

将 OO 视为一种通过继承实现重用的新方法的想法存在根本缺陷。正如您所注意到的,LSP 违规行为比比皆是。相反,OO 被恰当地认为是一种管理问题域复杂性的方法。目标是随着时间的推移系统的可维护性。实现这一点的主要工具是将公共接口与私有实现分离。这使我们可以拥有由编译器强制执行的诸如“只能使用 ... 修改”之类的规则,而不是代码审查。

使用它,我相信你会同意,允许我们创建和维护非常复杂的系统。这有很多价值,在其他范式中并不容易做到。

于 2008-09-13T00:14:21.480 回答
28

接近宗教,但我会说你正在描绘现代 OOP 状态的过于严峻的画面。我认为它实际上降低了成本,使大型软件项目易于管理,等等。这并不意味着它解决了软件混乱的根本问题,也不意味着普通开发人员是 OOP 专家。但是将功能模块化到对象组件中确实减少了世界上意大利面条式代码的数量。

我能想到几十个库,它们可以很好地重复使用,并且节省了无法计算的时间和金钱。

但就 OOP 浪费时间而言,我想说这是因为缺乏程序员培训,再加上学习特定语言的 OOP 映射的陡峭学习曲线。有些人“获得” OOP,而其他人永远不会。

于 2008-08-23T14:45:23.883 回答
24

没有经验证据表明面向对象是人们思考世界的一种更自然的方式。编程心理学领域的一些工作表明,OO 在某种程度上并不比其他方法更合适。

面向对象的表示似乎并不普遍更可用或更不可用。

仅仅采用 OO 方法并要求开发人员使用这些方法是不够的,因为这可能会对开发人员的生产力以及所开发系统的质量产生负面影响。

摘自 ACM 2000 年 10 月的 Communications of the Communications 的“On the Usability of OO Representations”。文章主要将 OO 与面向过程的方法进行比较。有很多关于使用 OO 方法的人如何“思考”的研究(Int. J. of Human-Computer Studies 2001,第 54 期,或 Human-Computer Interaction 1995,第 10 卷有一个关​​于 OO 研究的完整主题),从我读到的内容来看,没有任何迹象表明 OO 方法具有某种自然性,这使得它比更传统的程序方法更适合。

于 2008-08-24T14:03:42.790 回答
21

我认为使用不透明的上下文对象(Win32 中的 HANDLE,C 中的 FILE*s,举两个著名的例子——地狱,HANDLE 存在于内核模式障碍的另一边,它真的没有得到在过程代码中也可以找到比这更多的封装);我正在努力了解这对 OOP 来说是多么特殊。

HANDLEs(和 WinAPI 的其余部分)OOP!C 不能很好地支持 OOP,因此没有特殊的语法,但这并不意味着它不使用相同的概念。WinAPI 在任何意义上都是一个面向对象的框架。

看,这就是涉及 OOP 或替代技术的每一次讨论的问题:没有人清楚定义,每个人都在谈论其他事情,因此无法达成共识。对我来说似乎是在浪费时间。

于 2008-08-23T16:05:08.200 回答
14

它是一种编程范式。旨在让我们这些凡人更容易将问题分解成更小的、可行的部分。

如果你不觉得它有用.. 不要使用它,不要为培训付费,要快乐。

另一方面,我确实觉得它很有用,所以我会:)

于 2008-08-23T15:14:09.337 回答
14

相对于直接过程式编程,OOP 的第一个基本原则是信息隐藏和封装的概念。这个想法导致了将接口与实现分开的类的概念。这些是非常重要的概念,也是建立框架以不同方式和更好(我认为)方式思考程序设计的基础。你不能真正反对这些属性——没有权衡取舍,它总是一种更清洁的方式来模块化事物。

OOP 的其他方面(包括继承和多态性)也很重要,但正如其他人所暗示的那样,这些方面通常被过度使用。即:有时人们使用继承和/或多态是因为他们可以,而不是因为他们应该拥有。它们是强大的概念并且非常有用,但需要明智地使用,并且不是 OOP 的自动获胜优势。

相对于重用。我同意 OOP 的重复使用已被过度销售。这是定义明确的对象的可能副作用,通常是更原始/通用的类,并且是封装和信息隐藏概念的直接结果。它可能更容易被重用,因为定义良好的类的接口只是更清晰并且有点自我记录。

于 2008-08-23T15:43:04.120 回答
12

OOP 的问题在于它被超卖了。

正如 Alan Kay 最初设想的那样,它是对先前拥有原始数据和全局例程的做法的一个很好的替代方案。

然后一些管理顾问类型抓住了它并将其作为软件的救世主出售,像旅鼠一样,学术界和工业界都在追随它。

现在,在函数式编程等其他好想法被超卖之后,它们就像旅鼠一样翻滚。

那么我会做些什么不同的事情呢?很多,我为此写了一本书。(绝版了——我一分钱都没有,但你仍然可以得到副本。)亚马逊

我的建设性回答是,不要将编程视为对现实世界中事物进行建模的一种方式,而是将其视为一种编码需求的方式。

那是非常不同的,并且基于信息论(在任何人都可以理解的水平上)。它说编程可以被视为定义语言的过程,而这样做的技能对于良好的编程至关重要。

它提升了领域特定语言 (DSL) 的概念。它与 DRY 非常一致(不要重复自己)。它对代码生成大加赞赏。它导致软件的数据结构比现代应用程序的典型数据结构要少得多。

它试图重新激发这样一种观念,即前进的道路在于创造性,即使是被广泛接受的想法也应该受到质疑。

于 2008-12-31T13:53:25.920 回答
11

HANDLE(和 WinAPI 的其余部分)是 OOP!

他们是吗?它们不可继承,当然不可替代,它们缺乏定义明确的类……我认为它们与“OOP”相去甚远。

你曾经使用 WinAPI 创建过一个窗口吗?然后你应该知道你定义了一个类(RegisterClass),创建它的一个实例(CreateWindow),调用虚拟方法(WndProc)和基类方法(DefWindowProc)等等。WinAPI 甚至采用 SmallTalk OOP 的命名法,将方法称为“消息”(窗口消息)。

句柄可能不是可继承的,但final在 Java 中就有。它们不缺少类,它们类的占位符:这就是“句柄”这个词的意思。查看 MFC 或 .NET WinForms 之类的体系结构,很明显,除了语法之外,与 WinAPI 没有什么不同。

于 2008-08-23T16:42:13.230 回答
11

是的,OOP 并没有解决我们所有的问题,对此感到抱歉。然而,我们正在致力于解决所有这些问题的 SOA。

于 2008-09-17T04:59:06.987 回答
10

在我审查代码和项目设计的经验中,OOP 的价值并没有完全实现,因为许多开发人员没有在他们的头脑中正确地概念化面向对象的模型。因此他们不使用 OO 设计进行编程,经常继续编写自上而下的程序代码,使类成为一个非常扁平的设计。(如果您甚至可以首先将其称为“设计”)

看到同事对什么是抽象类或接口知之甚少,这非常可怕,更不用说正确设计继承层次结构以满足业务需求了。

然而,当存在良好的 OO 设计时,阅读代码并看到代码自然而然地放入直观的组件/类中只是纯粹的快乐。我一直认为系统架构和设计就像设计公司中的各个部门和员工工作 - 所有这些都是为了在宏伟的计划中完成某项工作,发出推动组织/系统前进所需的协同作用。

当然,不幸的是,这种情况非常罕见。就像世界上设计精美与设计糟糕的物理对象的比例一样,软件工程和设计也几乎可以这样说。拥有可供使用的好工具并不一定能带来好的做法和结果。

于 2008-08-24T14:57:43.987 回答
10

OOP 非常适合对内部计算机结构(如 GUI“小部件”)进行编程,例如 SelectList 和 TextBox 可能是 Item 的子类型,它们具有常见的方法,如“move”和“resize”。

问题是,我们 90% 的人在商业世界中工作,我们正在使用诸如发票、员工、工作、订单等商业概念。这些适合 OOP,因为“对象”更加模糊,可能会根据业务重新设计等进行更改。

最糟糕的情况是 OO 被热情地应用于数据库,包括对 SQL 数据库的令人震惊的 OO“增强”——这些都是正确地被忽略的,除非数据库新手认为它们必须是正确的做事方式,因为它们是更新的。

于 2008-10-23T16:12:15.520 回答
9

也许一顶帽子、一圈或一棵树不是椅子,但它们都是可坐的。

于 2008-08-25T20:19:07.170 回答
8

我认为那些现实世界的东西是物体

你做?

发票有哪些方法?等一下。它不能自己付款,不能自己发送,不能与供应商实际交付的物品进行比较。它根本没有任何方法;它是完全惰性且无功能的。它是一个记录类型(一个结构,如果你愿意的话),而不是一个对象。

你提到的其他事情也是如此。

仅仅因为某物是真实的,并不能使它成为 OO 意义上的对象。OO 对象是状态和行为的一种特殊耦合,可以自行执行。这在现实世界中并不丰富。

于 2008-10-02T08:31:38.797 回答
7

在过去 9 年左右的时间里,我一直在编写 OO 代码。除了使用消息传递之外,我很难想象其他方法。我看到的主要好处完全符合 CodingTheWheel 所说的:模块化。OO 自然地引导我从具有清晰接口和明确职责的模块化组件构建我的应用程序(即松散耦合、高度内聚的代码以及清晰的关注点分离)。

我认为当人们创建深度嵌套的类层次结构时,OO 崩溃的地方。这会导致复杂性。但是,将通用功能分解到基类中,然后在其他后代类中重用它是一件非常优雅的事情,恕我直言!

于 2008-08-23T15:02:58.273 回答
7

首先,观察结果有些草率。我没有任何关于软件生产力的数据,也没有充分的理由相信它不会上升。此外,由于滥用 OO 的人很多,即使 OO 是自花生酱以来最伟大的事情,良好使用 OO 也不一定会提高生产力。毕竟,一个不称职的脑外科医生可能比没有人更糟糕,但一个称职的脑外科医生可能是无价的。

话虽这么说,OO 是一种不同的安排方式,将程序代码附加到数据上,而不是让程序代码对数据进行操作。这本身至少应该是一个小胜利,因为在某些情况下,OO 方法更自然。毕竟,没有什么能阻止任何人用 C++ 编写过程 API,因此提供对象的选项反而使该语言更加通用。

此外,OO 做得非常好:它允许旧代码自动调用新代码,无需更改。如果我有按程序管理事物的代码,并且我添加了一种与早期类似但不完全相同的新事物,则我必须更改程序代码。在一个面向对象的系统中,我继承了功能,改变了我喜欢的,并且由于多态性而自动使用新的代码。这增加了变化的局部性,这是一件好事。

缺点是好的 OO 不是免费的:它需要时间和精力来正确地学习它。由于它是一个主要的流行语,所以有很多人和产品做得不好,只是为了做它。设计一个好的类接口并不比一个好的过程 API 容易,而且还有各种容易犯的错误(比如深层类层次结构)。

将其视为一种不同类型的工具,通常不一定更好。比方说,除了一把螺丝刀外,还有一把锤子。也许我们最终会摆脱软件工程的实践,因为我们知道使用哪个扳手来拧螺丝。

于 2008-12-31T15:24:11.803 回答
6

@肖恩

但是,将通用功能分解到基类中,然后在其他后代类中重用它是一件非常优雅的事情,恕我直言!

但无论如何,“程序”开发人员已经这样做了几十年。语法和术语可能不同,但效果是相同的。OOP 不仅仅是“在基类中重用通用功能”,我什至可以说这根本难以描述为 OOP。从不同的代码位调用相同的函数是一种与子过程本身一样古老的技术。

于 2008-08-23T15:08:58.460 回答
6

@康拉德

OOP 可能存在缺陷,它当然不是灵丹妙药,但它使大型应用程序变得更加简单,因为它是减少依赖关系的好方法

这就是教条。我没有看到是什么让 OOP 在这方面比旧的程序编程好得多。每当我进行过程调用时,我都会将自己与实现的细节隔离开来。

于 2008-08-23T15:11:06.413 回答
6

对我来说,OOP 语法本身有很多价值。使用试图表示真实事物或数据结构的对象通常比尝试使用一堆不同的平面(或“浮动”)函数对相同的数据做同样的事情有用得多。具有良好 OOP 的事物有一定的自然“流程”,这对于阅读、编写和长期维护更有意义。

发票不是真正的“对象”,它可以执行自己的功能,这并不重要——对象实例的存在只是为了对数据执行功能,而不必知道实际存在什么类型的数据。函数“invoice.toJson()”可以成功调用,而无需知道“发票”是什么数据——结果将是 Json,无论它来自数据库、XML、CSV,甚至是另一个 JSON 对象. 使用过程函数,您突然必须更多地了解您的数据,并最终得到诸如“xmlToJson()”、“csvToJson()”、“dbToJson()”等函数。它最终变得一团糟。如果您更改了基础数据类型,将会非常头疼。

OOP 的重点是通过抽象化来隐藏实际的实现。要实现该目标,您必须创建一个公共接口。为了让您的工作更轻松,同时创建公共接口并保持 DRY,您必须使用抽象类、继承、多态性和设计模式等概念。

所以对我来说,OOP 真正的首要目标是让未来的代码维护和更改更容易。但即使除此之外,如果以过程代码永远无法做到的方式正确完成,它确实可以大大简化事情。如果它与“现实世界”不匹配并不重要——用代码编程无论如何都不会与现实世界的对象交互。OOP 只是一个让我的工作更轻松、更快捷的工具——我会在任何一天都这样做。

于 2008-12-31T04:22:53.090 回答
5

@CodingTheWheel

但就 OOP 浪费时间而言,我想说这是因为缺乏程序员培训,再加上学习特定语言的 OOP 映射的陡峭学习曲线。有些人“获得” OOP,而其他人永远不会。

不过,我不知道这是否真的令人惊讶。我认为技术上合理的方法(LSP 是显而易见的东西)很难使用,但如果我们不使用这种方法,它会使代码变得脆弱且不可扩展(因为我们无法再对其进行推理)。我认为 OOP 导致我们得到的违反直觉的结果使得人们不接受它也就不足为奇了。

更重要的是,由于软件对于普通人来说已经很难可靠和准确地编写,我们真的应该赞美一种一直传授得很差而且似乎很难学习的技术吗?如果好处是明确的,那么尽管有困难,仍然值得坚持,但事实似乎并非如此。

于 2008-08-23T15:06:40.197 回答
5

@杰夫

相对于直接过程式编程,OOP 的第一个基本原则是信息隐藏和封装的概念。这个想法导致了将接口与实现分开的类的概念。

哪个具有更隐藏的实现:C++ 的 iostream 或 C 的 FILE*s?

我认为使用不透明的上下文对象(Win32 中的 HANDLE,C 中的 FILE*s,举两个著名的例子——地狱,HANDLE 存在于内核模式障碍的另一边,它真的没有得到在过程代码中也可以找到比这更多的封装);我正在努力了解这对 OOP 来说是多么特殊。

我想这可能是我努力看到好处的部分原因:明显好的部分不是 OOP 特有的,而 OOP 特有的部分显然不是好的!(这并不是说它们一定是坏的,而是说我没有看到证据表明它们广泛适用并且始终有益)。

于 2008-08-23T15:54:57.743 回答
5

在我读过的唯一一篇开发博客中,那个 Joel-On-Software-Founder-of-SO 的人很久以前就读到过,OO 不会导致生产力提高。自动内存管理可以。凉爽的。谁能否认数据?

我仍然相信 OO 之于非 OO 就像函数编程之于内联编程一样。

(我应该知道,因为我从 GWBasic 开始。)当您重构代码以使用函数时,variable2654就变成variable3了您所处的方法。或者,更好的是,它有一个您可以理解的名称,如果函数很短,它被称为value 并且足以完全理解。

当没有函数的代码变成有方法的代码时,你可以删除数英里的代码。

当您将代码重构为真正的 OO 时,b, c, q, 并Z成为this, this,thisthis. 而且由于我不相信使用this关键字,因此您可以删除数英里的代码。实际上,即使您使用this.



我不认为OO是自然的比喻。

我也不认为语言是一种自然的隐喻,我也不认为 Fowler 的“气味”比说“这段代码味道不好”更好。也就是说,我认为 OO 不是关于自然隐喻的,那些认为对象只是突然出现在你身上的人基本上没有抓住重点。您定义了对象宇宙,更好的对象宇宙导致代码更短、更容易理解、工作得更好,或者所有这些(以及我忘记的一些标准)。我认为使用客户/域的自然对象作为编程对象的人正在失去重新定义宇宙的能力。

例如,当您使用航空公司预订系统时,您所说的预订可能根本不符合法律/商业预订。



一些基本概念是非常酷的工具

我认为大多数人都夸大了“当你有一把锤子时,它们都是钉子”。我认为硬币/镜子的另一面也是如此:当您拥有像多态性/继承这样的小工具时,您就会开始找到它适合的用途,例如手套/袜子/隐形眼镜。OO的工具非常强大。我认为,单继承绝对有必要让人们不要得意忘形,我自己的多继承软件无法承受。



OOP 的意义何在?

我认为这是处理绝对庞大的代码库的好方法。我认为它可以让你组织和重新组织你的代码,并为你提供一种语言来做到这一点(超越你正在使用的编程语言),并以一种非常自然且易于理解的方式模块化代码。

OOP注定会被广大开发者误解

这是因为它是一个像生活一样令人大开眼界的过程:随着经验的积累,您越来越了解 OO,并开始避免某些模式并随着您变得更聪明而采用其他模式。最好的例子之一是您停止对您无法控制的类使用继承,而是更喜欢Facade模式。



关于你的小论文/问题

我确实想说你是对的。在大多数情况下,可重用性是一个白日梦。这是 Anders Hejilsberg 关于该主题(精彩)的引述:

如果你让初级程序员写一个日历控件,他们通常会想,“哦,我要写世界上最好的日历控件!它的日历类型将是多态的。它会有显示器,还有芒格,还有这个,那个,还有那个。” 他们需要在两个月内交付日历应用程序。他们把所有这些基础设施都放在了控件中,然后花了两天时间在上面写了一个糟糕的日历应用程序。他们会想,“在应用程序的下一个版本中,我会做更多的事情。”

然而,一旦他们开始考虑他们将如何实际实现他们抽象设计的所有其他具体化,结果证明他们的设计是完全错误的。而现在他们已经把自己画到了一个角落里,他们不得不把整个事情都扔掉。我一遍又一遍地看到这一点。我坚信极简主义。除非您真的要解决一般问题,否则不要尝试建立一个框架来解决特定问题,因为您不知道该框架应该是什么样子。

于 2008-12-31T01:11:46.237 回答
4

你曾经使用 WinAPI 创建过一个窗口吗?

比我想记住的次数还要多。

那么你应该知道你定义了一个类(RegisterClass),创建它的一个实例(CreateWindow),调用虚方法(WndProc)和基类方法(DefWindowProc)等等。WinAPI 甚至采用 SmallTalk OOP 的命名法,将方法称为“消息”(窗口消息)。

然后你也会知道它自己没有消息发送,这是一个巨大的空白。它也有糟糕的子类化。

句柄可能不可继承,但 Java 中有 final 。它们不缺少类,它们是类的占位符:这就是“句柄”这个词的意思。查看 MFC 或 .NET WinForms 之类的体系结构,很明显,除了语法之外,与 WinAPI 没有什么不同。

它们在接口或实现中都不可继承,最少可替代,并且它们与程序编码人员一直以来所做的没有本质区别。

真的是这样吗?OOP 最好的部分只是......传统的程序代码? 有什么大不了的?

于 2008-08-23T17:13:26.993 回答
4

我完全同意InSciTek Jeff的回答,我将添加以下改进:

  • 信息隐藏和封装:对于任何可维护的代码都至关重要。可以通过在任何编程语言中小心来完成,不需要 OO 功能,但这样做会使您的代码略微类似于 OO。
  • 继承:有一个重要的应用程序域,所有这些 OO是一种包含关系都非常适合:图形用户界面。如果您尝试在没有 OO 语言支持的情况下构建 GUI,那么无论如何您最终都会构建类似 OO 的功能,并且在没有语言支持的情况下更难且更容易出错。例如 Glade(最近)和 X11 Xt(历史上)。

在没有意义的情况下,使用 OO 特性(尤其是深度嵌套的抽象层次结构)是没有意义的。但是对于某些应用程序领域,确实有一点意义。

于 2008-09-11T14:42:05.310 回答
4

我相信 OOP 最有益的品质是数据隐藏/管理。但是,有很多 OOP 被滥用的例子,我认为这就是混乱的来源。

仅仅因为您可以将某些东西变成对象并不意味着您应该这样做。但是,如果这样做会使您的代码更有条理/更易于阅读,那么您绝对应该这样做。

OOP 非常有用的一个很好的实际示例是我在我们网站上使用的“产品”类和对象。由于每个页面都是一个产品,并且每个产品都引用了其他产品,因此对于您拥有的数据所指的产品可能会非常混乱。这个“strURL”变量是指向当前页面、主页还是统计页面的链接?当然,您可以制作各种不同的变量来引用相同的信息,但是 proCurrentPage->strURL 更容易理解(对于开发人员而言)。

此外,将功能附加到这些页面要干净得多。我可以做 proCurrentPage->CleanCache(); 其次是proDisplayItem->RenderPromo(); 如果我只是调用这些函数并假设当前数据可用,谁知道会发生什么样的邪恶。此外,如果我必须将正确的变量传递给这些函数,我又回到了为不同产品放置各种变量的问题。

相反,使用对象,我所有的产品数据和功能都很好,干净且易于理解。

然而。OOP 的最大问题是当有人认为一切都应该是 OOP 时。这会产生很多问题。我的数据库中有 88 个表。我只有大约 6 节课,也许我应该有 10 节左右。我绝对不需要 88 节课。大多数情况下,在我使用它的情况下,直接访问这些表是完全可以理解的,而 OOP 实际上会使获取正在发生的事情的核心功能变得更加困难/乏味。

我相信一个有用的对象和实用的程序的混合模型是最有效的编码方法。很遗憾,我们有所有这些宗教战争,人们提倡使用一种方法而牺牲其他方法。他们都很好,他们都有自己的位置。大多数情况下,在每个较大的项目中都有这两种方法的用途(在一些较小的项目中,可能只需要一个对象或几个过程)。

于 2008-09-15T21:27:39.700 回答
3

我不关心重用,就像我关心可读性一样。后者意味着您的代码更容易更改。仅此一项就在构建软件的工艺中价值不菲。

OO 是一种让你的程序可读的非常有效的方法。重用或不重用。

于 2008-12-31T13:30:38.837 回答
2

“现实世界不是‘OO’,”

真的吗?我的世界充满了物体。我现在用一个。我认为让软件“对象”模拟真实对象可能不是一件坏事。

面向概念事物的 OO 设计(例如 Windows,不是真实世界的窗口,而是我的计算机显示器上的显示面板)通常有很多不足之处。但对于发票、运输订单、保险索赔等现实世界的事物,我认为这些现实世界的事物都是对象。我的桌子上有一堆,所以它们一定是真的。

于 2008-10-01T08:08:59.030 回答
2

OOP 的重点是为程序员提供另一种方法,用于向机器和人描述和传达代码问题的解决方案。其中最重要的部分是与人的沟通。OOP 允许程序员通过在 OO 语言中强制执行的规则来声明他们在代码中的含义。

与关于该主题的许多论点相反,OOP 和 OO 概念在所有代码中普遍存在,包括非 OOP 语言(如 C)的代码。许多高级非 OO 程序员即使在非 OO 语言中也会近似对象的特征。

将 OO 内置到语言中只是为程序员提供了另一种表达方式。

编写代码的最大部分不是与机器通信,那部分很容易,最大的部分是与人类程序员的通信。

于 2008-12-17T23:12:32.653 回答
2

它是唯一一种将变量与与之交互的函数/方法/子例程分组在一起的语言可移植方法。

于 2008-12-31T03:00:31.540 回答
2

根据我在 1980 年代中期开始使用 C/Unix(非 OOP)然后在 1990 年转向 C++(OOP)然后在 1996 年左右进入 Java(OOP)的经验,我发现 OOP 可以极大地提高生产力、可维护性和健壮性与我之前从事的大型非 OOP 程序相比。

我观察到的主要事情是,在我研究的非 OOP 应用程序中,复杂性似乎相对于应用程序的复杂性以指数速度增长,而在 OOP 应用程序中,我研究的复杂性似乎具有更线性的与应用程序复杂性的关系。

换句话说 - 使用精心设计的 OOP 应用程序,您永远不会像使用大型非 OOP 应用程序那样获得“天啊,这个应用程序的源代码正在失控”的感觉。

作为 OOP 开发人员,我不能没有的其他事情是我可以编写代码来模拟应用程序问题域中存在的真实世界实体的方式。对象拥有自己的生命——远远超出了任何结构 (C) 或记录 (Pascal) 在糟糕的旧 =] 非 OOP 时代所做的事情。

一个规定是,OOP 项目的首席架构师必须知道他在做什么,并且他通常必须花费更多的思考时间来正确设计而不是实际实施它,但是“预先思考问题”的回报确实是惊人的. 重用或非常酷的设计优化的机会浮出水面,让你在办公室里打气并做触地得分......好吧,这对办公室里的其他人来说可能看起来有点奇怪,但这种热情从未发生在非OOP 天 :)

我见过一些写得很糟糕的 OOP 代码,也许这就是您所经历的,这可能会导致您提出这个问题。作为 90 年代中期的承包商,我经常发现“OO”设计已经由知道什么是类的人开始,但并不知道更多。这是一次非常痛苦的经历,我经常发现我在工作的头几个月涉及以非常不同的“OO”思维方式教育团队。只有在每个人的大脑都被重新连接之后,我们才能作为一个团队继续创造一些很棒的东西。

许多人发现“大脑重新布线”过程太难、太痛苦或太费力,所以他们一生都在反对 OOP,所以你会发现很多反对 OO 的人,但我很高兴,因为是那些人这让像我这样的人看起来不错:“什么,你可以花 X 美元做,它会在 2 个月内准备好,你会给我们一个可维护的代码库!!!哇,你今天可以开始吗?”

于 2010-02-03T05:26:29.563 回答
1

“即使没有实际的[信息架构],这并不意味着我们没有体验或感知它。禅宗佛教徒说没有真正的“自我”,但他们仍然为孩子命名。”-安德鲁·辛顿

于 2008-08-23T15:11:50.920 回答
1

HANDLE(和 WinAPI 的其余部分)是 OOP!

他们是吗?它们不可继承,当然不可替代,它们缺乏定义明确的类……我认为它们与“OOP”相去甚远。

于 2008-08-23T16:31:57.497 回答
1

也许一顶帽子、一圈或一棵树不是椅子,但它们都是可坐的。

是的,但只是事后。它们是 ISittable,因为有人坐在它们上面。

于 2008-08-27T20:11:52.817 回答
1

我知道我发现 OOP 仅在语法糖的基础上非常有用(封装、运算符重载、类型检查)。至于 OOP 的好处……我不知道。我不认为它比程序性的东西更糟糕。

在较轻的方面,我的 OOP 讲师说 OOP 很重要,因为否则“代码将有太多循环”。是的。有时我为每篇论文支付 500 美元而感到沮丧。:(

于 2008-08-29T01:30:38.800 回答
1

对我来说,OOP 的价值在于缩小范围并将状态与行为分开。范围更小,代码更容易理解。

它可以在大多数语言中完成,实现这一点所需要的只是一种状态将方法调用委托给行为的方式,以及行为进一步将调用委托给父行为的方式。

至于让一组类以有效的方式对域建模,没有什么神奇的方法。就像钢琴一样,我们必须练习。OOP 是一个抽象工具,它可以帮助您以更简单的方式构建代码,但它不能为您思考和分析您的应用程序的领域。

对我有用的是尽可能长时间地靠近域,同时仍然避免大多数代码重复。

于 2008-10-23T15:58:49.383 回答
1

OOP 有助于将接口与实现分开。您不需要语言中的 OOP 支持即可从 OO 设计中受益。

OOP 提供巨大帮助的一个小例子:

UNIX 虚拟文件系统 (VFS) 层使用函数指针表提供了一个统一的接口(打开/读/写)——很像 C++ 虚拟表调度。

客户端使用相同的调用集,无论它们是在与本地文件系统、远程网络文件系统 (NFS) 还是(今天)假文件系统(例如 /proc)通信。

请参阅原始 Sun 论文:Vnodes: An Architecture for Multiple File System Types in Sun UNIX

于 2008-12-31T12:40:22.073 回答
1

十年后我们还会对函数式编程说同样的话吗?

于 2008-12-31T13:19:12.557 回答
1

现实世界不是“OO”。现实世界在很大程度上不是由明智的部分构成的。相反,它是由混沌运动的粒子组成的。地球是一粒粒子汤。人们仍然看到鸟、树、天空、地面、森林、池塘。OO 是关于程序组件的抽象。将 OO 用于对程序以外的其他事物进行建模是根本性的缺陷。

所有的金钱和时间都没有让软件变得更好,因为它没有让程序员更聪明,也因为它没有改变人们对软件的看法。在您使用的意义上,“OOP”是一个流行词,用于从白痴那里赚钱。是的,那些把钱花在“OOP”教育和工具上的人都是白痴。容易陷入恶作剧的人往往是白痴。

“OOP”的价值在于抽象和代码在同一个程序内部的重用。OOP 旨在与命令式程序一起使用。

如果你从汇编程序中起床。组装是由标签和指令组成的有序序列对。汇编代码类似于“粒子汤”。现在您可以转到子程序。子例程从该标签中选择一个标签:指令汤,并将其余标签隐藏在子例程中。随着效果代码变得更加抽象并且您的命名空间保持清洁。

现在,如果您认为子程序的作用... 几十年前,人们认为子程序在处理参数时处于最佳状态。这使他们为每个对象提供了自己的协议。协议将包含 label:procedure -pairs。现在称为选择器:方法对。程序不再直接绑定到其他程序,解释了“后期绑定”-术语。除了从协议中保留历史(继承)外,这还形成了 smalltalk 中的“面向对象”。

你已经无法使用后期绑定机制,忘记了继承意味着什么。你还想知道你在那里缺少什么。“OOP 的价值在哪里,为什么所有的时间和金钱都未能让软件变得更好?” - 我想你把它们塞进了你的屁股。当您尝试进行结肠镜检查时,您会发现它们。

于 2008-12-31T14:14:13.817 回答
1

已经有很多答案了,因为这是一篇旧帖子,但我想我会加入。

您提到了一些涉及子类型和多态性的“类分类法”。这一切都围绕着继承,在它的鼎盛时期被认为是 OOP 的灵丹妙药。现在,继承和大类层次结构实际上是不鼓励的,即使在做很多 OOP 的商店中也是如此。这是因为已发现 OOP 的其他原则,例如封装、松散耦合、内聚等,远比继承有用。我什至会说松耦合是面向对象的原因,而不是代码重用。代码重用通常发生在方法/函数级别。我有时会在不同的情况下重用类,但不是那么频繁。松散耦合虽然有助于组织系统。每个对象都有自己的范围,对象中的数据是' t 或者不应该被操作,除非通过访问器方法或属性,每个对象应该做一件简单的事情,并应该通过简单的接口与其他对象对话。这少数原则有助于代码可读性,有助于隔离错误并防止您必须在许多不同的地方进行许多更改来更改一件事。当对象没有紧密地交织在一起时,您可以更改一个而不影响其他对象。这对我来说是一个巨大的好处。继承只是偶尔有用。你可以改变一个而不影响其他人。这对我来说是一个巨大的好处。继承只是偶尔有用。你可以改变一个而不影响其他人。这对我来说是一个巨大的好处。继承只是偶尔有用。

代码重用仍然很重要,如果您要复制和粘贴或重写相同的代码,即使在普通的过程、结构化或函数式编程中,这也是一种不好的做法。由于重复的工作、增加的维护和更多的错误,这实际上增加了成本。

于 2009-10-20T15:54:57.463 回答
0

OOP降低成本,提高了效率。

当我从经典的 ASP/VBScript 跳到 C# 时,我注意到由于 OOP,生产力大大提高。

于 2008-08-23T15:57:02.963 回答
0

我同意 InSciTek Jeff 的观点。即使您不使用最纯粹意义上的 OO,封装理论也可以帮助降低潜在的结构复杂性: http ://www.edmundkirwan.com

@DrPizza

如果过程编程在相同程度上使用封装的好处,那就太好了!

于 2008-10-28T20:42:56.790 回答
0

现实世界可能不是面向对象的,但人们倾向于通过类比(抽象)而不是逻辑来更好地学习或思考。

OOP 不适用于计算机,但它适用于不善于在没有类比的情况下找出复杂系统的程序员。我相信 OOP 的主要目的是使用抽象更好地组织代码,因此在不了解其他部分的情况下,程序员可以很容易地了解她/他想要进入的某个级别的特定部分或整个系统的工作。

要使用抽象组织代码,您还需要在您的语言中进行封装、继承和多态性。并且 SOLID OOP 原则和设计模式可以在这个组织中做得更好。但我认为 OOP 的全部意义在于抽象,因为人类以这种方式思考得更好。

于 2014-08-14T17:09:29.423 回答
0

OOP 是关于实例化......您想一遍又一遍地重新实例化同一件事,其活动的分类略有不同。共享活动是指共享类。

如果你不想那样想,就不要做 OOP。在说帕斯卡之后开始思考它肯定会扭曲头脑,因此会激怒程序员。

您详细说明了您的实例化机器人的每一个差异,并且您不会重复一次。

每个分类差异只有一个标签/类(不是每个不同的东西!),这就是 OOP 的力量......这就是它与人工智能的一些超级神经网络的相似之处,它永远不会用完不同事物的名称,因为它依赖于总分布,所以命名它。

——马格努斯·W。

于 2014-09-28T09:38:09.307 回答