开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
面向对象编程的绝地反击 - 技术翻译 - 开源中国社区

面向对象编程的绝地反击 【已翻译100%】

标签: <无>
oschina 推荐于 11个月前 (共 11 段, 翻译完成于 08-14) 评论 14
收藏  
7
推荐标签: 待读

免责声明:该帖子含有幽默成分,如果您对幽默类题材比较敏感,建议您停止阅读。

最近,我阅读了发布在 DZone 上的关于面向对象编程的文章。我在博客上发现过好几篇关于面向对象编程的函数编程文章。所有这些帖子都在说,面向对象编程已经死亡(或多或少)。我认为所有这些帖子存在基本问题的误解:没有真正理解什么是函数编程。现在是时候让我谈谈不同编程范式之间的争论了。

首先,我想说,我尊重上述文章作者的意见。我要说的是我个人对这个问题的看法。对这个富有争议的问题上没有绝对正确或绝对错误的观点。所以,请大家不要互相攻击。

亚林瓜子
 翻译得不错哦!

函数式编程是什么?

我认为为了更好地理解我对函数式编程的观点,首先必须理解函数式编程是什么意思。

在计算机领域,函数式编程是一种编程范式 [..] ,它将计算机运算视为数学上的函数计算,并且避免状态变更以及数据可变。

这是维基百科给出的定义。你读过 lambda 表达式吗?没有。因此,在代码中滥用 lambda 表达式并不意味着您使用的是函数式编程范型。

根号7
 翻译得不错哦!

首先,您需要“引用透明性”,这意味着任何时候使用相同输入的调用函数必须返回相同的输出。实现引用透明性的先决条件是状态的不变性。一旦创建了一个结构(我们可以说一个类型?),就不能在随后以任何方式进行修改。

简单吗?引用透明性意味着没有副作用,没有异常抛出,没有从外部来源的读取等等。如果没有这些能力,我们如何才能实现高产出呢?

Tocy
 翻译得不错哦!

故事的难点

我们似乎被困在一个黑洞里,不是吗?我不能在一个函数内产生副作用(这并不坏),我不能向函数调用者发出信号,说可能出了问题,我不能访问任何外部资源。哦,天哪!

你听说过幺半群、函子、单子吗?这些结构直接来自于范畴论,数学的一个分支。描述这些结构超出了本文的范围,但我们可以举一些例子。

圣洁之子
 翻译得不错哦!

我确定地知道你在你的代码中至少使用一些单子(Monad)。如果你是一个 Scala 开发者,很可能你使用过 Option[T] 类型,或 [T, E],或任何一种集合比如 List[T]、Set[T] 等。如果你是一个 Java 开发者,你可以把 Optional<T>、Collection<T> 和 Stream<T> 类型纳入考虑。所有这些类型都是单子(Monad)。

这些类型从行为的角度看没有任何共同之处,这意味着单子(Monad)是一种机制,用于在彼此不直接相关的类型之间共享一些属性(基本上,代码复用)。这是什么意思?下文引用自 Scala 设计模式

单子(Monad)结构代表计算的步骤序列。单子(Monad)被用于构建一切都不可变的管道,而干净利落地给一门语言增添带有副作用的操作。

圣洁之子
 翻译得不错哦!

让我们从优秀图书 Scala 函数式编程借用单子(Monad)的定义:

一个单子(Monad)是一元组合子的最小集(即 unit 和 flatMap)之一的实现,满足结合性和同一性的法则。

一元结合子?结合性?同一性?独角兽?Wtf?!!? 我只是一个普通的开发人员:我听说过数学,我改变编程范式。

我想用这篇论文来说明什么?真正的函数式编程实际上涉及数学规律和理论。如果你遵从这些规律开发你的程序,就会从一组好的属性中获益,比如可组合性、可测性、线程限制,直接来自数学理论。

然而,你需要学习数学。范畴论的小雨滴将会沾湿你的脸庞。

圣洁之子
 翻译得不错哦!

面向对象编程

面向对象编程是什么呢? 你有没有遇到过你必须遵循的无聊的数学法则? 你有没有听过有关诸如 monad 或 functor 这样的深奥词汇,还是别的什么? 你有没有将一些数学理论应用于面向对象的程序中?

没有。面向对象编程的美丽之处在于它是与数学无关的。每个人都可以学习面向对象的编程语言,如 Java、C ++ 或 Kotlin。第一印象里,面向对象的编程非常接近于我们看待现实世界的方法。

Tocy
 翻译得不错哦!

作为生活在世界幸运地区的人类,我们知道车都是由发动机、一些轮子、一个车身等构成的。我们明白 Car 类型是什么意思,为什么它拥有引擎、车轮和车身的属性。

面向对象编程比函数式编程更容易学习。 到此为止。这是唯一的事实。 从计算机时代开始,这两种模式就或多或少地存在(例如,想想在 1958 年发明的 Lisp)。你有没有听说过用函数式编程语言来编写的操作系统的? 没有。

Tocy
 翻译得不错哦!

简单化导致的权衡

更简单意味着更少的约束。  更少的约束意味着更少的拘泥于形式。更少的形式意味着更容易用一种错误的方式使用编程语言的特性。

以我们刚刚提出的一元定义为例。 在定义中,类型必须满足的约束是非常明确的指定为一元。 数学不会说谎。

现在,采用面向对象编程的任何原则:例如,单一责任原则。 原则规定:

一个类只因一个理由而改变。

开易
 翻译得不错哦!

需要改变的原因究竟是什么?所有适用于函数编程语言的数学魔法在哪里?没有。

在与面向对象编程有关的所有理论的基础上,耦合的定义都不是以正式的方式定义的。

组件之间的耦合取决于其依赖程度。

好吧,那么如何衡量组件之间的依赖程度? 没有正式的方式。 我试图在我过去的帖子“依赖关系”中给出耦合的数学定义,但这只是一个试验。

缺乏严谨的原理定义导致了原理的解读。个人的解读往往导致错误和不良做法。

总长
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(14)
Ctrl/CMD+Enter

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。
get set在解决多线程修改变量查错方面很有用

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。

引用来自“MZHS”的评论

get set在解决多线程修改变量查错方面很有用
不要共享变量,通过消息来传递。
面向对象本是一种思维方式,用工具硬表现就是一种错误。而函数式编程只能说呵呵了,那么多的细节无视掉,理想化的编程方式--Boss一拍屁股,下面累死。
一层层不断套,套着套着就出问题了。另外,函数式编程和对象编程有啥关系????

引用来自“黑传说”的评论

一层层不断套,套着套着就出问题了。另外,函数式编程和对象编程有啥关系????
就像PHP和Java的关系:laughing:

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。

引用来自“MZHS”的评论

get set在解决多线程修改变量查错方面很有用

引用来自“LinkerLin”的评论

不要共享变量,通过消息来传递。
公司里你控制不了别人怎么写代码,我的意思就是在debug和生产环境抓log时,有get和set一抓一个准。如果你碰到的变量值和你推理出来的值不一样的时候,就需要在set处抓内奸,看看是谁改了值,如果想看都是谁用了该变量的值的时候,get就起到了作用。一个管修改,一个管权限,就跟出入境管理是一样一样的
绝地反击....无语
好吧。。两种都可以直接用啊。。又不冲突的咯。。真是二。。

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。
那是语言的锅,不是面向对象的锅。现代语言可不用写一堆getter/setter。
我是做移植的,纯面相对象的代码迁移到函数式语言的环境中,比重构都难。相反的话,就容易很多。
面向对象是好的,但是一个问题直接的解决方法有那么多种,而且效率不相上下,未免让我心烦。

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。

引用来自“MZHS”的评论

get set在解决多线程修改变量查错方面很有用

引用来自“LinkerLin”的评论

不要共享变量,通过消息来传递。

引用来自“MZHS”的评论

公司里你控制不了别人怎么写代码,我的意思就是在debug和生产环境抓log时,有get和set一抓一个准。如果你碰到的变量值和你推理出来的值不一样的时候,就需要在set处抓内奸,看看是谁改了值,如果想看都是谁用了该变量的值的时候,get就起到了作用。一个管修改,一个管权限,就跟出入境管理是一样一样的
弱弱的问一句,在 scala 里面,val 变量的值是无法改变的,那你还 debug 什么。。。

引用来自“梅开源”的评论

面向对象本来是好的,但是一大堆get set以及为了解决继承和接口和强类型而引入各种奇技淫巧后, 看这些代码已经不再享受智慧的共鸣。

引用来自“MZHS”的评论

get set在解决多线程修改变量查错方面很有用

引用来自“LinkerLin”的评论

不要共享变量,通过消息来传递。

引用来自“MZHS”的评论

公司里你控制不了别人怎么写代码,我的意思就是在debug和生产环境抓log时,有get和set一抓一个准。如果你碰到的变量值和你推理出来的值不一样的时候,就需要在set处抓内奸,看看是谁改了值,如果想看都是谁用了该变量的值的时候,get就起到了作用。一个管修改,一个管权限,就跟出入境管理是一样一样的

引用来自“水山清风”的评论

弱弱的问一句,在 scala 里面,val 变量的值是无法改变的,那你还 debug 什么。。。
不了解scala,java里被final修饰的基本数据类型变量也是不能被修改的。既然都是一个常量了,一般除了出了不是被三方程序修改(像八门神器这种),就是传错了变量,也是需要debug的。
顶部