前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面向对象编程是否走向了消亡?

面向对象编程是否走向了消亡?

作者头像
Python猫
发布于 2019-08-30 08:04:02
发布于 2019-08-30 08:04:02
73000
代码可运行
举报
文章被收录于专栏:Python无止境Python无止境
运行总次数:0
代码可运行

? “Python猫” ,一个值得加星标的公众号

【CSDN 编者按】作为一种程序设计思想,OOP 在最初诞生之际就收到了广大开发者的喜爱。但是在技术革新日益实践过程中,不少人发现面向对象的设计会使代码复杂化,难以理解而且难以测试,对此,后来有网友更是将 OOP 称之为是反模块化、反并行的,从而开启了一波又一波的吐槽模式。而论 OOP 在各个领域中的应用时,其是否真的有想象中那么糟糕?接下来,本文将带领大家一读 OOP 的兴衰成长史。

《天空之城》剧照

作者 | Talin

译者 | 王艳妮,责编 | 屠敏

授权转载 | Python猫(ID:python_cat)

不,面向对象编程(OOP)并没有消亡。但它远没有以前那么流行了。

我记得当时在90年代,关于面向对象编程的教科书和计算机科学课程很多。当时那就是“风口”,下一波潮流。如果你没有以那种方式编程,你就不是一个优秀的程序员,或者至少是可悲地落后于时代发展潮流了。

当时,CS专业的学生以非常严格和教条化的方式学习OOP。从业者们不仅被鼓励以对象和类的形式构建他们的应用程序,甚至被认为应该根据对象和类来考虑问题空间。这样的做法被称为“面向对象的分析和设计”。

然而,随着时间的推进,人们开始意识到严格的面向对象方法会带来许多问题。这些问题往往会使代码复杂化,难以理解而且难以测试。

事实证明,OOP在某些问题领域确实比其他方法更出色。例如,OOP仍然是构建用户界面(窗口和按钮)的最自然的方式。但是,试图使面向对象适应关系数据库一直以来都简直是一场灾难。

以下是我所观察到的一些问题:

“鸭嘴兽”效应

现实世界并不总是能被整洁地划分为具有明确属性定义的类(class)。例如,假设你创建了一个代表动物王国的类层次结构。现在,有爬行动物——冷血,有鳞片,卵生等等。还有哺乳动物——温血,有绒毛,胎生。以及鸟类,两栖动物,无脊椎动物等等

然后鸭嘴兽出现了,它似乎不适合你的任何类别。你该怎么做呢?你是创建一个全新的类别呢,还是重新考虑整个分类方案?这两种方法在工作量和程序复杂性方面都会产生巨大的成本。

(感谢Anselm Hook创造了“鸭嘴兽效应”一词。)

深层次结构

我记得我在谷歌工作时,当时我们有一个JavaScript库叫goog.ui,它被用于创建基于Web的用户界面。以下是此库中某个UI组件的继承层次结构示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ToolbarColorMenuButton
* inherits from ColorMenuButton
  * inherits from MenuButton
    * inherits from Button
      * inherits from Control
        * inherits from Component
          * inherits from EventTarget
            * inherits from Disposable
              * inherits from Object

九个级别的类。太多了。

但情况会变得更糟。

许多高级类被只与少数子类相关的方法和属性“污染”。例如,“Control”类有超过90种方法(method)。它具有设置状态的方法,即使特定的子类是无状态的; 它有添加和删除子元素的方法,即使对control来说子元素没有意义。

这种复杂性的一个重要原因是,该库的作者试图组织组件的不同方面——例如组件是按钮还是滑块,或者它是否有颜色——并通过将它们放入类的不同层次来实现这一点。

但实际上,这些不同方面彼此之间无关。咖啡杯是红色的,和它是由陶瓷制成的,这是两个独立的特性。将红色咖啡杯划入“红色物品”类别,还是将其放入“陶瓷制品”甚至“家居用品”类别中都是同样正确的。任何一个选择都是任意的,因为类别是由人头脑中的反映和社会结构决定的。

在Google工作的最后几年里,我创建了一个名为“Quantum Wiz”的新用户界面工具包,旨在替代goog.ui。我们采用的规则之一(以典型的Google风格,以方程式编写)是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
composition > inheritance

用直白的英语解释的话,这说的是:

“更偏向于采用组合的思路——也就是说,能够用更小的构建块来组装组件的功能——而不是继承作为代码重用的手段。”

因此,举个栗子,如果按钮有颜色,你将采用常规的“Button”对象(object)并向其添加“Color”方面(aspect),作为属性或子对象,而不是创建一个新的“Color Button”类。

作为这项任务的结果,新工具包的类层次结构相对较浅,如果我没记错的话,只有两三个级别。而且更容易理解和使用,也更强大。

(感谢Malte Ubl向我介绍了组合大于继承的概念。)

对象不是真实的

Buckminster Fuller曾经说过:“事物并不存在”。他的意思是,事物之间的区别主要由人的偏见导致。

例如,我坐的沙发是由分子力束缚在一起的原子的集合。然而,这些原子也会受到房间内其他物体的影响——地毯,茶几,甚至是房间内的空气。沙发本身由各种部件组成——织物,木材,金属弹簧等等——它们也受到分子力的约束。那么沙发是一个对象,还是很多对象?也许世上只有一个对象——即我们所在的这个宇宙。

因为人类的视觉和触觉在很大程度上只对表面属性有响应——比如颜色和质感——我们倾向于基于表面现象对世界进行分类。相反,想象一下,如果我们能够直接感知周围物体内的分子组成。我们可能会看到一个“铜”对象,代表着房屋中的所有布线和管道,一个“氮”对象,代表着房间的气体,一个“水”对象,一个“木头”对象,等等。

Fuller的观点是,我们将世界“解析”为离散的“事物”的能力是任意的,这更多地反映了我们的人类心理而不是物理现实。

因为面向对象的继承涉及将事物组织成类,所以它不能很好地模拟现实世界; 但它能很好地模拟人类思考现实世界的方式。

方法(method)也不真实

我记得大约二十年前的一段小插曲,一位软件供应商的技术代表试图向我司的工程人员解释OOP。他试图争辩说,面向对象是一种模拟现实世界的方式,他给出的例子就像上面说的咖啡杯那种。他说杯子可能有个“drink()”的方法。

我记得的是,我对此有一个非常强烈的反应——我认为他所说的完全是胡说八道。除了它的特定目的之外,一个物理对象可以有许多用途。我可以用咖啡杯作为镇纸或门挡; 这是否意味着它有一个“holdDownPapers()”或“keepDoorOpen()”方法?我可以将它用作武器,玩具或艺术品。我甚至可以将杯子碎成碎片,或将其研磨成粉末,并以创造性的方式使用其残余物。

(我认为这个可怜的家伙对我的反驳感到吃惊。)

内部逻辑与外部逻辑

严格的OOP风格的一个原则是,永远不可能从外部改变对象的内部状态。任何改变对象状态的业务或应用程序逻辑都必须作为对象本身的方法实现。因此,举个栗子,如果要删除文本字段中的所有文本,则不能简单地进行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
textField.value = ""; // Set to empty string

这将违背规则。相反,你不得不这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
textField.clear(); // Clear the content of the field

对于简单的操作,这没关系。但是这很容易过火,特别是正在进行的操作处理的是不同对象之间的复杂关系时。

有时候,如果算法独立于任何对象之外,反而更好。这真的是一个重要的问题:对于这个问题集,你更关心名词还是动词?

下面这是一个具体的例子:最近我开始研究编译器(编写编译器是我的一个爱好; 在我做游戏开发的时候,我发明了许多脚本语言)。在过去,当我编写编译器时,我会采用非常严格的OOP方法来设计内部数据结构。有各种类层次结构表示抽象语法树,表达式图,类型等。

通常,编译器通过一系列阶段或“传递”来处理这些数据结构,每一步的输出被送到下一步的输入中。

在过去,我倾向于按照推荐的OOP样式为每个操作中的每个对象设置一些逻辑。这带来不好的后果,当我添加更多步骤时,对象变得越来越复杂。

更糟糕的是,这使得给这些对象写单元测试异常困难。这些复杂的对象在被创建出来之前就需要大量的基础结构。这意味着为了测试一个对象,我必须创建大量的脚手架来满足所有先决条件。

结果,我的测试覆盖率往往很差,因为编写测试是一项耗费大量精力的工作。

最近,我采取了另一种方法。在我最新的编译器中,所有这些内部数据结构都是“傻瓜型”的,意思是说它们所做的只是保存数据而已,没有别的。用于操作和转换对象的所有代码都在这些对象的外部。

这对代码的组织有很大的好处。每个算法都集中在一个地方,而不是分散在一堆源文件中。当我想测试一个特定的编译器操作时,我可以轻松地创建一些示例对象并将其提供给该操作。因此,我的测试写起来更容易了,所以我就能写更多的测试了,从而就能有比以前更好的测试覆盖率了。

关系数据库

前面我提到过,以面向对象的方式处理关系数据库会有问题。对象关系映射(ORM)被一位评论家称为计算机科学领域的越战。(警告——那篇文章很长,很深奥,而且有点倾向性。)

我的大致感觉是,在处理大数据时,你不应将你的记录视为“对象”。关系数据库非常强大,但它们提供的强大功能并不是非常“类似对象”。我倾向于认为关系数据流更像流体,你可以使用代数运算的方式来划分,转换和组合数据。

(感谢Guido Van Rossum指出上面关于ORM的文章的链接。)

函数式编程

在过去十年左右的时间里,人们越来越关注函数式编程(FP)。与OOP一样,函数式编程不仅仅是单纯的一件事物,而是一套整体的风格上的原则。然而,它的要点是,虽然OOP专注于与对象进行交互或通信,但在FP中,重点在于对它们的转换。这里的“转换”,意思是你获取一些对象,将它传递给一个函数,结果是一个全新的对象,代表着对输入内容所做的一些转换。原始对象要么被保留,要么被丢弃,但不会以任何方式被更改或修饰。

在我自己的编程过程中,我更喜欢“混合”方法,在某些地方使用FP技术,而在其他地方使用OOP技术。在解决某些问题上FP确实能大放异彩,但也有另一些问题上OOP是更明智的选择。

我知道很多FP爱好者都热衷于“纯粹”的函数式语言,其中所有对象都是不可变的,并且只能被转换,而不能被修改。然而,我发现纯粹的方法倾向于把某些相对简单的编程实践变成谜题。我的意思是一些聪明的,但不那么显而易见的技巧,这能吸引那种喜欢脑筋急转弯的人,但是对其他人来说却是完全无法理解的。

因此,我倾向于在合理的范围内使用FP,使阅读我代码的普通程序员都能理解。如果我想做任何抖机灵的事情,我会写一篇长篇评论来解释我所做的事情,以及它是如何work的(这满足了我炫耀的心理——我经常认为编程应该是一种表演艺术。)

所以,面向对象编程不再有昔日的辉煌了。它仍然是一个很好的工具,仍然值得学习。但它已跌下神坛,你很难再看到有人能像 25 年前那样,以宗教般的狂热来吹捧它了。

原文:https://medium.com/machine-words/the-rise-and-fall-of-object-oriented-programming-d67078f970e2

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python猫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面向对象变成VS函数式编程
面向对象编程(OOP)和函数式编程(FP)是软件开发中的两种主要范式。这两种方法都为组织、设计和实现软件系统提供了不同的方法论。虽然面向对象编程几十年来一直是主导范式,但函数式编程近年来获得了巨大的吸引力,这要归功于其处理状态和数据的独特方法。我们将学习研究每种范式的特征,检查它们的优缺点。并用Java来演示两者的差异。
FunTester
2024/05/28
1430
面向对象变成VS函数式编程
谈谈我对面向对象以及类与对象的理解
对于刚接触JAVA或者其他面向对象编程语言的朋友们来说,可能一开始都很难理解面向对象的概念以及类和对象的关系。笔者曾经带过一个短期培训班教授java入门基础,在最后结束课程的时候,还有很多同学不太理解面向对象的思维以及类与对象的意义。这几天有空,就想着整理整理自己的思路,谈谈自己对面向对象以及类与对象的理解。
Java团长
2018/08/06
5860
python快速入门【五】---- 面向对象编程、python类
面向对象编程(Object-oriented Programming,简称OOP)是一种编程范例,它提供了一种结构化程序的方法,以便将属性和行为捆绑到单个对象中。
汀丶人工智能
2022/12/01
6420
面向对象编程的弊端有哪些?
面向对象编程作为一种流行的软件开发范式,有助于提高代码复用性、可维护性和扩展性,但它并非完美无缺,在特定场景和大型软件项目中也存在诸多弊端。
不脱发的程序猿
2024/11/26
2040
面向对象编程的弊端有哪些?
Python面向对象编程
OOP,即面向对象编程(或 “面向对象程序设计” ,Object Oriented Programming)。类和对象是OOP中的两个关键内容,在面向对象编程中,以类来构造现实世界中的事物情景,再基于类创建对象来进一步认识、理解、刻画。根据类来创建的对象,每个对象都会自动带有类的属性和特点,然后可以按照实际需要赋予每个对象特有的属性,这个过程被称为类的实例化。
Francek Chen
2025/01/22
790
Python面向对象编程
面向对象编程,再见!
作为程序员,你是使用函数式编程还是面向对象编程方式?在本文中,拥有 10 多年软件开发经验的作者从面向对象编程的三大特性——继承、封装、多态三大角度提出了自己的疑问,并深刻表示是时候和面向对象编程说再见了。
JAVA高级架构开发
2018/10/08
1.1K0
面向对象编程,再见!
什么是面向对象编程?OOP 深入解释
面向对象编程 (OOP) 是一种基本的编程范式,几乎每个开发人员都在其职业生涯的某个阶段使用过。OOP 是用于软件开发的最流行的编程范例,并且在大多数程序员的教育生涯中被作为标准编码方式教授。 另一种流行的编程范式是函数式编程,但我们现在不讨论它。
用户4235284
2023/10/14
1.5K0
什么是面向对象编程?OOP 深入解释
适合初学者学习的面向对象编程(OOP)入门指南
类是一种蓝图,用来创建对象。它定义了对象将拥有的属性和方法。就像建房子的图纸一样,图纸决定了房子的结构和功能,但并不是真正的房子。
前端达人
2024/06/27
3210
适合初学者学习的面向对象编程(OOP)入门指南
第4章 类与面向对象编程第4章 类与面向对象编程
在前面的章节中,我们学习了Kotlin的语言基础知识、类型系统等相关的知识。在本章节以及下一章中,我们将一起来学习Kotlin对面向对象编程以及函数式编程的支持。
一个会写诗的程序员
2018/08/17
1.8K0
第4章 类与面向对象编程第4章 类与面向对象编程
再谈编程范式(3):理解面向过程/面向对象/函数式编程的精髓
面向过程是随着VB一起来到我的世界,那个时候会的非常有限,感觉能把程序写出来自己就非常棒了,VB是做那种可视化界面,在工具栏拖个框框放到面板上,然后就在各个事件上写完整的逻辑,什么封装,抽象,继承一概不懂,就有一种一个方法把实现过程需要的逻辑都罗列了,面向过程分析的是步骤。这样说过于抽象,举个例子,洗衣机洗衣服。
周陆军博客
2023/03/18
1.5K0
面向对象编程是计算机科学的最大错误
C++和 Java 可能是计算机科学中最严重的错误。两者都受到了 OOP 创始人 Alan Kay 本人以及其他许多著名计算机科学家的严厉批评。然而,C++和 Java 为最臭名昭著的编程范式--现代 OOP 铺平了道路。
张张
2021/03/17
6440
面向对象编程是计算机科学的最大错误
如何给6岁小朋友讲解面向对象编程
尽管这些问题可能微不足道,但它们很重要,因为它们提供了关于你的线索。你现在的心态,态度,观点。
AiTechYun
2019/07/22
1K0
函数式编程与面向对象编程[3]:Scala的OOP-FP混合式编程与抽象代数理论
Scala是纯种的面向对象的语言。从概念上讲,每一个值都是一个对象,每一个操作都是一个方法调用。语言支持通过类和特征的高级组件架构。
一个会写诗的程序员
2018/09/12
8280
全面深入理解Python面向对象编程
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
顶级程序员
2018/07/23
8720
面向对象编程会被抛弃吗?这五大问题不容忽视
20 世纪 60 年代,编程遇到了一个大问题:计算机还没有那么强大,需要以某种方式平衡数据结构和程序之间的能力。
机器之心
2020/10/27
5060
面向对象编程会被抛弃吗?这五大问题不容忽视
10 . Python之面向对象
类中的方法一般都是通过对象执行的(除去类方法,静态方法外),并且对象执行这些方法都会自动将对象空间传给方法中的第一个参数self
iginkgo18
2020/09/27
4150
10 . Python之面向对象
面向对象语言真有那么棒嘛?
在我的整个编程生涯中,我一直反复思考关于面向对象编程的问题:用还是不用。不过,去年我终于确定下来,决定不再使用面向对象编程,下面我会说明具体原因。 先讲一个小故事: 起初都是面条式代码(译注:spaghetti code指代码控制结构复杂、混乱而难以理解,尤其用了很多GOTO、例外、线程、或其他无组织的分歧架构)。 Dijkstra说:“要有结构式编程!应当考虑到goto的危害性,用恰当的控制流机制来组织代码、构建功能。” 程序员说:“没问题,当然要这样做。” 但之后Dijkstra发现代码还是面条式的,
程序员互动联盟
2018/03/15
8090
面向对象编程(OOP):什么是面向对象编程?三大特性继承、多态、封装如何实现?
面向对象编程(Object-Oriented Programming, OOP)是一种将数据和操作数据的方法封装成对象的编程方式。它的核心思想是:
猫头虎
2024/12/18
4220
面向对象编程
原文链接:https://note.noxussj.top/?source=cloudtencent 什么是面向对象编程? 面向对象程序设计(Object Oriented Programming,O
菜园前端
2023/05/16
3720
面向对象编程:理解其核心概念与应用
在编程的世界中,面向对象编程(Object-Oriented Programming, OOP)已成为一种主流的编程范式。它提供了一种组织和管理代码的有效方式,使得代码更加模块化、可重用和易于维护。本文将带您深入探讨面向对象编程的核心概念及其在现实世界中的应用。
用户8909609
2024/02/11
2130
面向对象编程:理解其核心概念与应用
推荐阅读
相关推荐
面向对象变成VS函数式编程
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验