为什么面向对象编程很重要






3.50/5 (6投票s)
为什么变革性的软件开发方法论今天仍然相关
面向对象编程很重要
原因就在这里……
引言
眼下,函数式编程非常流行。Haskell 和 JavaScript 等语言很时髦。虽然 JavaScript 主要可以通过 TypeScript 等语言实现面向对象,但随着函数式编程的兴起,在 JavaScript 中使用对象变得越来越少见。
函数式编程的支持者宣扬纯函数使测试更容易,不变性减少了副作用等等。这些都很好,但它忽略了使用面向对象的最大原因。世界是由对象组成的,而不是由线性函数组成的(好吧,不完全是,但一个能接受世界所有参数的线性函数将完全难以维护)。
使用面向对象编程(OOP)本质上是创建一个定义做什么(接口/抽象类)和如何做(具体类)的系统。OOP 将系统分解为定义交互的契约,以及执行操作的实现。OOP 和现实世界中的对象都通过基于用例和*正常*行为的可定义条件集进行交互,并通过异常返回*异常*行为。纯函数无法表达模糊性,因为模糊性是一种副作用。
一个简单的系统
一百多年来,我们一直有电话。尽管技术发生了巨大的变化,但电话的用例一直保持不变。
拨号者拨号,接听者接听电话,他们交谈,然后一方挂断。
一个如此根本简单的系统!
尽管技术已经飞速发展,但今天的智能手机仍然可以拨打墙上的人工接线电话,反之亦然。
那为什么会这样呢?因为世界是由实现具有特定功能的接口(继承)的对象组成的(封装)。一些设备随着微小的变化而演变,例如脉冲拨号电话演变为触控拨号电话(多态)。
电话只是这个系统的终结点。互联电话是电话网络,它们接受呼叫请求,找到将呼叫路由到接收者的方法,然后通知接收者有来电。我们有三个接口定义了这四个简单用例之间的交互。
这个关键系统不仅由三个接口定义,而且接口本身也非常简单。如果你曾经听过“保持简单,傻瓜”(KISS)这个词,那么你就知道这正是这个说法的精髓。这个系统在 100 多年来基本保持不变。我们所要做的就是填补空白!
系统中最重要的部分是ITelephone
。这是拨号者或接听者用来交谈的对象,这是整个系统整个目的的基本用例。
电话网络始于拨号者拿起听筒,按了几下开关,然后与接线员一起工作,接线员会将您的电话从一个网络路由到另一个网络,直到接收者的电话响铃。这很粗糙,但有效。
今天,拨号者拿起听筒,按了几下数字,计算机找到到接收者的最有效路径,然后接收者的电话响铃。
在过去的 100 年里,ITelephone
、ITelephoneNetwork
和 IRoute
都随着技术的发展而演变,但那无关紧要。
ITelephone
从一个听筒和按键变成了复杂的便携式计算机,它恰好也能拨打/接听电话。向后兼容性是这种演变的标志。ITelephone Interface
强制执行了一组通用的可用操作和接收器,因此任何 ITelephone
实例都可以通过位于设备之间的适配器与任何 ITelephoneNetwork
实例进行通信,这些适配器负责处理不同技术之间的转换。
ITelephoneNetwork
定义了呼叫路径中每个网络之间的基本通信。同样,适配器填补了技术空白,但它们只是将一种技术翻译成另一种技术。
我们可以通过一个(非常)简单的活动图来查看这些用例的交互。
三个接口真的能描述这一切吗?是的,是的,它们可以。当然,每个操作的细节并没有在这里体现,但它们也无关紧要。请注意,此时我们还没有创建一个类。我们已经定义了用例、接口以及电话呼叫期间发生的活动。此时,您可能会 tempted 直接开始创建那些实现,但首先让我们定义一下这些接口如何与序列图相互交互。
序列图从左到右,从上到下读取。每条线代表沿途的一个方法、事件或返回值。这里的一切都在接口中,并且接口中的所有内容也都在这里。序列匹配了满足用例的活动。在过去 100 年里,各种技术的混合体实现了这个序列,每一步都完全不关心下一个实现的细节。
结论
在大多数书籍和文章中,您会看到该系统的一个具体示例。会有RotaryTelephone
、TouchToneTelephone
、CellPhone
和 SmartPhone
。您会看到接线员将电线插入面板,计算机以数字方式路由呼叫。您会看到CopperNetworks
、FiberNetworks
、CellularNetworks
和 DigitalNetworks
。在这里您看不到那些实现。为什么?因为它们无关紧要。
这正是 OOP 的宗旨。接口封装功能,对象通过新的或演进的设计实现接口,但由于系统的简单设计,实现无关紧要。
我希望将 OOP 简化为一个简单、改变世界的系统,有助于您理解良好设计的重要性以及良好设计如何带来良好的系统。实现会随着时间的推移而改变——这是不可避免的——您可以简单地继承现有对象或创建一个实现通用接口的全新对象。OOP 允许您以有意义的方式执行所有这些操作。没有纯函数式的混乱,要求为每种技术到技术的组合提供实现。没有巨大的 API 调用库来在技术每次进步时提供新功能。您只需添加或扩展需要添加或扩展的内容即可。正确完成,现有系统不会受到影响。