“面向对象就是一个错误!”

[原创文章:www.ii77.com]

【CSDN 编者按】面向对象编程的风行是较量机科学范畴的不幸,它对现代经济造成了极大的损坏,造成了数万亿美元的间接损失。在曩昔的三十年中,几乎所有行业都因潜在的面向对象编程危机而受到影响。

[转载出处:www.ii77.com]

作者 | Ilya Suzdalnitski
编译 | 弯月   责编 | 张文
出品 | CSDN(ID:CSDNnews)
C++和 Java 或者是较量机科学范畴最大的错误。就连面向对象的建立者 Alan Kay 都曾对这两门说话提出了严峻的指摘。然而,C++和 Java 都是对照主流的面向对象说话。
面向对象编程的风行是较量机科学范畴的不幸,它对现代经济造成了极大的损坏,造成了数万亿美元的间接损失。在曩昔的三十年中,几乎所有行业都因潜在的面向对象编程危机而受到影响。
为什么面向对象编程如斯危险?下面我们一路来寻找谜底。
2007 年 9 月,美国 Jean Bookout 驾驶的 2005 款凯美瑞倏忽失控,Bookout 测验刹车然则失败,最终发生了碰撞事变,导致车内另一人身亡,Bookout 受伤。然而,此案只是丰田在美上百起车辆不测加快投诉的个中之一。
在 Bookout 事件查询的过程中,原告方礼聘了两位软件专家,他们花了快要 18 个月的时间来研究丰田代码。最终,他们都形容丰田代码库为“面条式代码”(Spaghetticode),法式的流向就像一盘面条一般扭曲纠结在一路。
软件专家演示了大量丰田软件或者导请安外加快的情形。最终,丰田被迫召回 900 多万辆汽车,赔付款子高达 30 多亿美元。


面条式代码有什么问题?


然而,丰田并不是独一一家有面条式代码问题的公司。曾经有两架波音 737 Max 飞机坠毁,造成 346 人灭亡,损失跨越 600 亿美元。这两起事件的原因也出在了软件 bug 上,并且都是由面条式代码引起的。
面条式代码困扰着全世界上许很多多的代码库,包罗飞机、医疗设备以及核电站上运行的代码。
法式代码不是为机械编写的,而是为人类编写的。Martin Fowler 曾说过:“任何傻瓜都能够编写较量机可以懂得的代码。但只有精良的法式员能够编写人类可以懂得的代码。
若是代码不克正常运行,那解说出了问题。然则,若是人们不睬解代码,那么它一定会出问题。迟早的事儿。
此处,我们来谈论一下人类的大脑。人脑是世界上最壮大的机械。然则,它有其自身的局限性。我们的工作记忆是有限的,人脑一次最多只能思虑 5 件事。这意味着,法式代码的编写体式不该该超出人脑的局限。
然而,面条式代码导致人类无法懂得代码库。这就会埋下深远的祸胎,因为我们不清楚某些代码更改是否会激发问题。我们无法运行详尽的测试,找出所出缺陷,甚至没有人知道如许的系统是否能正常工作。尽量系统可以正常工作,我们也不领略为什么。


面条式代码的原由


为什么经由一段时间的成长之后,代码库会显现面条式代码?因为熵。宇宙中的一切都变得杂沓无序。就像电缆终将乱如一团麻,我们的代码最终也将变得杂沓不胜。除非我们施加充沛的约束。
为什么高速公路有时速限制?这是为了防止我们撞车。为什么道路上有交通旌旗?为了防止人们走错路,为了防止事变发生。
编程也一般。如许的约束不该让法式员来决意,应该经由对象主动实现,或许幻想情形下经由编程范例自己来实现。


为什么面向对象是万恶之源?


我们如何才能施加充沛的约束,防止面条式代码的显现?两个法子:手动或主动。手动很轻易失足,人类不免会犯错。是以,我们理应主动执行此类约束。
然而,面向对象编程并不是我们一向在寻找的解决方案。它没有供应任何约束来帮助解决代码扭曲纠缠的问题。一小我能够精晓各类面向对象编程的最佳实践,例如依靠注入、测试驱动的斥地、范畴驱动的设计等(这些实践的确有匡助)。然则,这些都不是由编程范例自己来强制执行的(并且也没有响应的对象来强制执行最佳实践)。
面向对象编程内部没有任何功能能够匡助我们预防面条式代码,封装只是隐藏和打乱了法式的状况,只会让情形变得更糟。继续带来了更多的杂沓。面向对象编程的多态性更是推波助澜,我们基本不知道法式运行时会采用哪种切实的执行路径。稀奇是在涉及多个继续级别时。

面向对象进一步加剧了面条式代码的问题
然而,面向对象的瑕玷可不止缺乏适当的约束。
在大多数面向对象编程说话中,默认情形下一切都是经由引用共享的。这实际大将一个法式酿成了一个宏大的全局状况。这与面向对象原本的思惟南辕北辙。面向对象的建立者 Alan Kay 拥有生物学的配景。他想到了一种说话(Simula),能够让我们按照生物细胞的组织体式编写较量机法式。他进展有自力的法式(细胞)经由互相发送新闻进行通信。自力法式的状况永远不会与外界共享(封装)。
AlanKay 从来也没想过让“细胞”直接进入其他细胞的内部做任何点窜。但现代面向对象编程就这么干了,因为在现代面向对象编程中,默认情形下,一切都是经由引用共享的。这也意味着损坏正常功能的错误无法避免。点窜法式的某一部门就会损坏其他功能(这在函数式编程等其他编程范例中很少见。)
我们能够清楚地看到,现代面向对象编程素质上就存在很大的缺陷。它不光会让你在平常工作中疼痛不胜,并且还会让你夜不成寐。


可展望性


面条式代码是一个重大的问题。面向对象的代码稀奇轻易形成面条式。
面条式代码导致软件无法维护,但这只是问题的一部门。此外,我们还进展软件具有靠得住性,以及可展望性。
任何系统的用户都应该享受沟通的、可展望的体验。踩下油门,汽车就会加快;相反,踩刹车,汽车就会减速。用较量机科学术语来说,我们进展汽车的行为是确定的。
我们非常不进展汽车示意出随机行为,例如加快器无法加快,或制动器不克减速(丰田的问题)。即使此类问题发生的概率非常低。
然而,大多数软件工程师的心态都是“我们的软件要充沛好,才能让客户持续使用。”我们能做的只有这么多吗?当然不是,我们应该做得更好!然而,首先最起码应该解决法式的不确定性。


不确定性


在较量机科学中,确定性算法指的是针对沟通的输入,算法始终可以示意出沟通的行为。而不确定性算法恰恰相反,尽量输入沟通,每次运行算法也会示意出分歧的行为。
举个例子:
console.log( 'result', computea(2) );console.log( 'result', computea(2) );console.log( 'result', computea(2) ); // output:// result 4// result 4// result 4
无需在意上述函数的具体功能,你只需要知道对于沟通的输入,它老是会返回沟通的输出。下面,我们看一看另一个函数 computeb:
console.log( 'result', computeb(2) );console.log( 'result', computeb(2) );console.log( 'result', computeb(2) );console.log( 'result', computeb(2) ); // output:// result 4// result 4// result 4// result 2    <=  not good
这一次,这个函数在面临沟通的输入时,却给了分歧的输出。这两个函数之间有什么区别?前者针对沟通的输入,老是能给出沟通的输出,就像数学函数一般。换句话说,这个函数是确定的。尔后者则纷歧定会输出预期的值,换句话说,这个函数是不确定的。
若何判断某个函数是确定的,照样不确定的?
  • 不依靠外部状况的函数百分百都是确定的。

  • 只挪用其他确定的函数的函数也是确定的。

function computea(x) {  return x * x;} function computeb(x) {  return Math.random()< 0.9          ? x * x          : x;}
在上述示例中,computea 是确定的,它老是可以针对沟通的输入给出沟通的输出。因为它的输入只取决于参数x。
而 computeb 是不确定的,因为它挪用了另一个不确定的函数Math.random()。我们怎么知道 Math.random()是不确定的?因为这个函数会凭据系统时间(外部状况)来较量随机值。并且,它也没有参数,只取决于外部状况。
确定性与可展望性之间有什么关联?确定的代码就是可展望的代码。不确定的代码就是弗成展望的代码。


从确定的到不确定的
 
我们再来看一个函数。
function add(a, b) {  return a + b;};
我们能够确定,输入(2,2)的究竟老是等于 4。我们为什么能确定?在大多数编程说话中,加法把持都是经由硬件实现的,换句话说,CPU 会负责较量究竟始终连结不变。除非我们需要处理浮点数的对照(但这是另一个话题,与不确定性问题无关)。这里,我们只商议整数。硬件非常靠得住,是以我们能够宁神加法的究竟准确无误。
下面,我们给 2 加一个处理:
const box = value => ({ value }); const two = box(2);const twoPrime = box(2); function add(a, b) {  return a.value +b.value;} console.log("2 + 2' == " + add(two, twoPrime));console.log("2 + 2' == " + add(two, twoPrime));console.log("2 + 2' == " + add(two, twoPrime)); // output:// 2 + 2' == 4// 2 + 2' == 4// 2 + 2' == 4
到这里,这个函数依然是确定的!
下面,我们来稍微点窜一下函数自己:
function add(a, b) {  a.value += b.value;  return a.value;} console.log("2 + 2' == " + add(two, twoPrime));console.log("2 + 2' == " + add(two, twoPrime));console.log("2 + 2' == " + add(two, twoPrime)); // output:// 2 + 2' == 4// 2 + 2' == 6// 2 + 2' == 8
发生了什么?倏忽间,函数的究竟就弗成展望了!第一次运行没有问题,然则后背每次运行获得的究竟都是弗成展望的。换句话说,这个函数不再具备确定性。
为什么倏忽酿成不确定的?这是因为我们点窜了函数感化域之外的一个值,函数显现了副感化。

总结一下
确定的法式可确保 2 + 2 == 4。换句话说,给定输入(2, 2),函数 add 必然会输出 4。无论这个函数被挪用几多次,无论是否并行挪用该函数,也无论函数外部是什么状况,它必然会输出 4。
不确定的法式则正好相反,在大多数情形下,add(2, 2)将返回 4。但有时,该函数或者会返回 3、5,甚至 1004。法式中切切不克显现不确定性,我进展你领略为什么。
不确定的代码有什么后果?它们会激发软件缺陷,也就是常说的 bug。碰到 bug,斥地人员需要虚耗大量贵重的时间来调试代码,若是将这类代码投入生产,则会大大降低客户体验。
为了让我们的法式更靠得住,首先应该解决不确定性的问题。


副感化
 
这里,我们不得不谈一谈副感化。
什么是副感化?平日意义的副感化是指若是你因头痛而服用药物,但这种药物让你感应恶心,那么恶心就是一种副感化。简而言之,副感化就是不良回响。
想象一下,你买了一台较量器。带回家后却发现这不是一台简洁的较量器。你输入 10 * 11,而它却输出了 110,同时在你耳边大喊“一百一十”。这就是副感化。接着,你输入 41+ 1,它输出了 42,但又喊道“四十二,死掉。”这也是副感化。你带着满脸的迷惑,打德律叫外卖,究竟这台较量器偷听到了你的德律,高声说“好的”,然后还帮你下了订单。这也是副感化。
下面,我们持续来说 add 函数:
function add(a, b) {  a.value += b.value;  return a.value;}
这个函数执行了预期的把持,即 a 加 b。然则,它也有副感化。因为在执行a.value+ = b.value 后,对象 a 会发生转变。假设刚起头的是 a.value=1,则第一次挪用完成后,a.value=2。并且第二次挪用后,它的值会再次转变。


纯粹
 
在商议了确定性和副感化后,我们再来看一看纯粹。纯函数是确定的,并且没有副感化。
纯函数有什么长处?它们是可展望的。是以,非常易于测试(无需编写模拟函数和桩函数)。懂得纯函数非常轻易,不需要将整个应用法式状况都装入大脑。你只需要考虑面前的函数。
编写纯函数也很轻易(因为它们不会点窜任何局限之外的数据)。纯函数非常适归并发,因为函数之间没有共享状况。此外,重构纯函数也很简洁,只需复制和粘贴,无需复杂的 IDE 对象。
简而言之,纯函数能够让我们康乐地编程。

面向对象编程是否是纯粹的?
为了举例解说,我们看两个面向对象的特征:getter和setter。
getter 的究竟取决于外部状况,也就是对象状况。每次挪用 getter,获得的究竟都不沟通,具体取决于系统的状况。是以,getter 素质上是不确定的。
setter会点窜对象的状况,是以它们素质上就带有副感化。
这意味着面向对象所有的方式(除静态方式外)或许是不确定的,或许会带来副感化。是以,面向对象编程并不纯粹,它与纯粹南辕北辙。

银弹
蒙昧并不值得惭愧,蒙昧又不学才让人惭愧。
—— 本杰明·富兰克林
固然软件世界里难题重重,但我们仍存一线进展,尽量无法解决所有的问题,至少也能够解决大多数问题。然则,只有当你甘愿进修和应用,才能成功。
银弹的界说是什么?就是能够解决所有问题的灵丹妙药。经由千百年的起劲,数学界也有银弹。
若是不确定性(即弗成展望)成为现代科学的支柱,那你感觉我们的世界能走多远?或者不会太远,或许我们还停留在中世纪。医学界就履历过如许的情形,曩昔我们没有严厉的试验来证实特定的治疗方式或药物的功能。
不幸的是,现在的软件行业与曩昔的医学太相似了。现代软件行业的根蒂非常懦弱,也就是所谓的面向对象编程。我们进展软件也可以像医学一般,找到坚韧的根蒂。


坚韧的根蒂
 
在编程世界中,我们也能够拥有像数学一般靠得住的根蒂吗?能够!我们能够将很多数学概念直接转化为编程,并以此为根蒂,也就是我们所说的函数式编程。
函数式编程是编程界的数学,它是非常牢靠且壮大的根蒂,可用于构建靠得住且坚固的法式。是什么让函数式编程如斯壮大?这种编程体式的根蒂是数学,尤其是 Lambda 演算。
做个对照,现代面向对象编程的根蒂是什么?Alan Kay 的面向对象编程基于的是生物细胞。然则,现代 Java/C#的根蒂是一套荒谬的思惟,好比类、继续和封装等,这些并非源自 Alan Kay 最初的思惟。
反观函数式编程,它的焦点构件是函数,并且在大多数情形下是纯函数。纯函数是确定性的,是以它们是可展望的。这意味着由纯函数构成的法式将是可展望的。这倒不是说函数式编程没有 bug,然则若是法式中存在 bug,那也是确定的,即对于沟通的输入始终会激发沟通的 bug,是以非常轻易修复。


代码是若何执行到这一步的?


以前,在过程式编程和函数式编程显现之前,goto 语句普遍用于编程说话中。goto 语句许可法式在执行的过程中跳至代码的任何部门。是以,斥地人员很难回覆:“代码是若何执行到这里的?”并且 goto 语句激发了大量 bug。
现在,面向对象编程也有这个问题。在面向对象编程中,一切都是经由引用传递的。从理论上讲,这意味着任何对象都有或者被其他对象点窜(面向对象编程对此没有任何约束)。封装基本没有匡助,它只不外是挪用一种方式来更改某些对象的字段。这意味着,法式中的依靠关系很快就会乱成一锅粥,整个法式都邑成为一个大型的全局状况。
有什么法子能够解决这个问题吗?没错,就是采用函数式编程。
曩昔曾经很多人对于住手使用 goto 的建议都有触犯,就像现在好多人会否决函数式编程和弗成变状况的思惟。


面条式代码怎么办?
 
在面向对象编程中,“组合优于继续”被视为最佳实践。从理论上讲,这类的最佳实践有助于改善面条式代码。然而,这只是“最佳实践”,面向对象的编程范例自己没有任何约束,强制人们遵守这类最佳实践。团队中的初级斥地人员是否遵循这类最佳实践,完全看小我,或许你在代码审查中强制实施。
函数式编程若何?在函数式编程中,函数组合(和分化)是构建法式的独一方式。这意味着编程范例自己会强制执行组合。这恰是我们一向在寻找的解决方案。
函数挪用其他函数,大函数始终由小函数构成。组合在函数式编程中是很天然的选择。此外,在这种体式下,重构的难度也会降低,只需剪切代码,然后将其粘贴到新函数中即可。无需治理复杂的对象依靠项,也不需要复杂的对象(例如Resharper)。
我们能够看出,要想更好地组织代码,选择面向对象编程并不明智,函数式编程显着更胜一筹。


如今就起头动作


面向对象编程自己就是一个伟大的错误。
若是我知道我乘坐的汽车运行的软件是由面向对象编程说话编写的,我会感应害怕;知道我和家人乘坐的飞机使用了面向对象的代码,也会让我感应不安。
我们应该接纳动作,熟悉到面向对象编程的危险,并起劲进修函数式编程。我知道这个过程很漫长,至少需要十年才能做出改变。
但我相信在不久的未来,终有一天面向对象编程会退出这个舞台,就像现在的 COBOL 一般。
参考链接:https://suzdalnitski.medium.com/oop-will-make-you-suffer-846d072b4dce

☞ 乐视视频 App 图标改为“欠 122 亿”,网友:我在别家分..,却在你家随份子!

较量机科学界至今未解决的四浩劫题

万字长文爆肝 DNS 和谈!

标签:面向对象 错误

热门文章

  1. 浙能电力:煤炭价格下降、发电量增加,一季度归母净利润同比增79.62%至18.15亿元2024-04-29
  2. 特斯拉、百度美股盘前上涨2024-04-29
  3. 中国石化:聘任赵东为总裁,聘任万涛、喻宝才为高级副总裁2024-04-29
  4. 港股收评:恒指涨0.54%,恒生科技指数跌0.13%,房地产、医药、内险股走高,航空、电信股低迷2024-04-29
  5. 中国交建:一季度归母净利润61.41亿元,同比增长10%2024-04-29
  6. 万安科技:一季度归母净利润同比增长1890.93%2024-04-29
  7. 同仁堂:产品销量提升,一季度归母净利润5.76亿元,同比增长10.04%2024-04-29
  8. 大北农:一季度净亏损2.09亿元,同比减亏2024-04-29
  9. 掌阅科技:第三大股东量子跃动拟减持不超1%公司股份2024-04-29
  10. 上港集团:一季度归母净利润36.96亿元,同比增长4.1%2024-04-29
  11. 龙虎榜 | 万科A今日涨停,深股通买入2.27亿元并卖出1.99亿元2024-04-29
  12. 龙虎榜 | 万丰奥威今日涨停,深股通买入1.74亿元并卖出3.92亿元2024-04-29
  13. 万华化学:福建工业园MDI装置完成技改扩能,已具备试生产条件2024-04-29
  14. 厨师证怎么查询(厨师证怎么查询办理进度)2024-04-29
  15. 海尔智家:一季度归母净利润47.73亿元,同比增长20.16%2024-04-29
  16. 中国人保:一季度归母净利润89.63亿元,同比下降23.5%2024-04-29
  17. 农业银行:一季度归母净利润703.86亿元,同比下降1.63%2024-04-29
  18. 零跑汽车:2023年权益持有人应占年内全面亏损总额42.25亿元2024-04-29
  19. 中国石油股份:一季度归母净利润456.83亿元,同比增长4.7%2024-04-29
  20. 浪潮信息:一季度归母净利润3.06亿元,同比增长64.39%2024-04-29
自媒体 微信号:ii77 扫描二维码关注公众号
爱八卦,爱爆料。

小编推荐

  1. 1 收购 | 鸿辉光通将斥资1500万美元收购上海光联100%股权

    新 闻 导 读 鸿辉光通拟以支出现金体式收购美国光联通信手艺有限责任公司(Oplink)持有上海光联通信手艺有限公司100%股权,初始让渡对价为1,500万美元。此次收购资产将优化鸿辉光通

  2. 2 微软将删除老版Edge;缅甸切断互联网;Joomla集成Bootstrap5

    微软将彻底删除旧版本Edge浏览器 在住手对旧版(微软自研的内核,也称经典版)Edge浏览器的平安性更新一个月后,微软还将在4月份发布补丁在用户的Windows 10较量机系统中删除。 早期

  3. 3 【前瞻】与美的合作,华为靠鸿蒙OS在物联网领域迈出重要一步

    据人民日报2月5日新闻, 美的集体与华为 的合作,将在智能家居范畴有大动作—— 2021年年内,实现合作规模化,从运营和营销角度睁开更多合作 。 具体而言,就是在物联网范畴美的

  4. 4 3G 时代真香的定制机,运营商做不出来了?

    你用过运营商的手机吗? 从中华酷联到华米 OV,再到现在的大集体 + 副牌并行,十多年来,手机行业经由了一轮又一轮洗牌,竞争日趋激烈,产物也越做越好。在这过程中,几大头部手

  5. 5 迈入流程自动化时代,RPA呈燎燃之势

    导 读 ( 文/ e-works熊东旭 孙亚婷) 对准企业流程主动化,让员工从 反复单调 的流程性工作中解脱出来。 玩游戏的同伙大多知道“按键精灵”这款软件, 能经由建造剧本主动执行一系列

  6. 6 全球5G测速启示:运营商能否摆脱同质化竞争?

    同样的笼盖,同样的带宽,同样的手机,同样的5G KPI……运营商若何解脱同质化竞争?依然清楚记得早在2017年5G降生前就有行业专家对5G时代提出了如许的疑问。 回首4G时代,统一的尺

  7. 7 闻泰科技拟收购欧菲光摄像头业务资产,或将进入苹果供应链!

    1月25日晚间,欧菲光发布通知,公布拟出售旗下向苹果供给摄像头模组的子公司——广州得尔塔影像手艺有限公司(以下简称“广州得尔塔”)及江西慧光微电子有限公司(以下简称“

  8. 8 本周大新闻|苹果VR售价或达3000美元,Beat Saber卖出400万份

    hi188|编纂 本周大新闻,AR方面,ARK投资申报重点提到虚拟游戏;Magic Leap 2或本年四时度发布;Valve、OpenBCI、Tobii联手斥地AR/VR脑机设备;HoloLens 2工业版发售,4950美元;苹果经由瞳孔巨

  9. 9 打好“数字底座”,联通数字科技有限公司今日成立

    今日,联通数字科技有限公司(以下简称“联通数科”)揭牌典礼在京举办。中国联通董事长王晓初、总司理陈忠岳、党组副书记李福申、副总司理买彦州、副总司理梁宝俊、总管帐师

  10. 10 英国缘何要给中国留学生划定“学术圈”?

    据《泰晤士报》1月30日报道, 为了珍爱本国常识产权和国度平安 ,英国将进一步限制中国留学生在高校的学术局限。 英当局将于2月15日对 44个范畴的外国粹者与研究人员实施新一轮平

本文内容来自网友供稿,如有信息侵犯了您的权益,请联系反馈核实

Copyright 2024.爱妻自媒体,让大家了解更多图文资讯!