久久久久在线观看_又色又爽又黄的免费视频播放_一区中文字幕_日韩电影在线播放

今日頭條 焦點資訊 營銷之道 企業(yè)報道 淘寶運營 網(wǎng)站建設(shè) 軟件開發(fā) 400電話
  當(dāng)前位置: 首頁 » 資訊 » 網(wǎng)站建設(shè) » 正文

編程的宗派

放大字體  縮小字體 發(fā)布日期:2018-02-18  來源:新格網(wǎng)  作者:新格網(wǎng)  瀏覽次數(shù):329  【去百度看看】
核心提示:總是有人喜歡爭論這類問題,到底是“函數(shù)式編程”(FP)好,還是“面向?qū)ο缶幊獭保∣OP)好。既然出了兩個幫派,就有人積極地做它們的幫眾,互相唾罵和鄙視。然后呢又出了一個“好好先生幫”,這個幫的人喜歡說,管它什么范式呢,能解決問題的工具就是好工具!

編程語言 函數(shù)式編程 面向?qū)ο缶幊? border=

總是有人喜歡爭論這類問題,到底是“函數(shù)式編程”(FP)好,還是“面向?qū)ο缶幊?rdquo;(OOP)好。既然出了兩個幫派,就有人積極地做它們的幫眾,互相唾罵和鄙視。然后呢又出了一個“好好先生幫”,這個幫的人喜歡說,管它什么范式呢,能解決問題的工具就是好工具!我個人其實不屬于這三幫人中的任何一個。

面向?qū)ο缶幊蹋∣bject-Oriented Programming)

如果你看透了表面現(xiàn)象就會發(fā)現(xiàn),其實“面向?qū)ο缶幊?rdquo;本身沒有引入很多新東西。所謂“面向?qū)ο笳Z言”,其實就是經(jīng)典的“過程式語言”(比如Pascal),加上一點抽象能力。所謂“類”和“對象”,基本是過程式語言里面的記錄(record,或者叫結(jié)構(gòu),structure),它本質(zhì)其實是一個從名字到數(shù)據(jù)的“映射表”(map)。你可以用名字從這個表里面提取相應(yīng)的數(shù)據(jù)。比如point.x,就是用名字x從記錄point里面提取相應(yīng)的數(shù)據(jù)。這比起數(shù)組來是一件很方便的事情,因為你不需要記住存放數(shù)據(jù)的下標(biāo)。即使你插入了新的數(shù)據(jù)成員,仍然可以用原來的名字來訪問已有的數(shù)據(jù),而不用擔(dān)心下標(biāo)錯位的問題。

所謂“對象思想”(區(qū)別于“面向?qū)ο?rdquo;),實際上就是對這種數(shù)據(jù)訪問方式的進一步抽象。一個經(jīng)典的例子就是平面點的數(shù)據(jù)結(jié)構(gòu)。如果你把一個點存儲為:

struct Point {    double x;    double y;  } 

那么你用point.x和point.y可以直接訪問它的X和Y坐標(biāo)。但你也可以把它存儲為“極坐標(biāo)”方式:

struct Point {    double r;    double angle;  } 

這樣你可以用point.r和point.angle訪問它的模和角度。可是現(xiàn)在問題來了,如果你的代碼開頭把Point定義為第一種XY的方式,使用point.x, point.y訪問X和Y坐標(biāo),可是后來你決定改變Point的存儲方式,用極坐標(biāo),你卻不想修改已有的含有point.x和point.y的代碼,怎么辦呢?

這就是“對象思想”的價值,它讓你可以通過“間接”(indirection,或者叫做“抽象”)來改變point.x和point.y的語義,從而讓使用者的代碼完全不用修改。雖然你的實際數(shù)據(jù)結(jié)構(gòu)里面根本沒有x和y這兩個成員,但由于.x和.y可以被重新定義,所以你可以通過改變.x和.y的定義來“模擬”它們。在你使用point.x和point.y的時候,系統(tǒng)內(nèi)部其實在運行兩片代碼,它們的作用是從r和angle計算出x和y的值。這樣你的代碼就感覺x和y是實際存在的成員一樣,而其實它們是被臨時算出來的。在Python之類的語言里面,你可以通過定義“property”來直接改變point.x和point.y的語義。在Java里稍微麻煩一些,你需要使用point.getX()和point.getY()這樣的寫法。然而它們最后的目的其實都是一樣的——它們?yōu)閿?shù)據(jù)訪問提供了一層“間接”(抽象)。

這種抽象有時候是個好主意,它甚至可以跟量子力學(xué)的所謂“不可觀測性”扯上關(guān)系。你覺得這個原子里面有10個電子?也許它們只是像point.x給你的幻覺一樣,也許宇宙里根本就沒有電子這種東西,也許你每次看到所謂的電子,它都是臨時生成出來逗你玩的呢?然而,對象思想的價值也就到此為止了。你見過的所謂“面向?qū)ο笏枷?rdquo;,幾乎無一例外可以從這個想法推廣出來。面向?qū)ο笳Z言的絕大部分特性,其實是過程式語言早就提供的。因此我覺得,其實沒有語言可以叫做“面向?qū)ο笳Z言”。就像一個人為一個公司貢獻了一點點代碼,并不足以讓公司以他的名字命名一樣。

“對象思想”作為數(shù)據(jù)訪問的方式,是有一定好處的。然而“面向?qū)ο?rdquo;(多了“面向”兩個字),就是把這種本來良好的思想東拉西扯,牽強附會,發(fā)揮過了頭。很多面向?qū)ο笳Z言號稱“所有東西都是對象”(Everything is an Object),把所有函數(shù)都放進所謂對象里面,叫做“方法”(method),把普通的函數(shù)叫做“靜態(tài)方法”(static method)。實際上呢,就像我之前的例子,只有極少需要抽象的時候,你需要使用內(nèi)嵌于對象之內(nèi),跟數(shù)據(jù)緊密結(jié)合的“方法”。其他的時候,你其實只是想表達數(shù)據(jù)之間的變換操作,這些完全可以用普通的函數(shù)表達,而且這樣做更加簡單和直接。這種把所有函數(shù)放進方法的做法是本末倒置的,因為函數(shù)其實并不屬于對象。絕大部分函數(shù)是獨立于對象的,它們不能被叫做“方法”。強制把所有函數(shù)放進它們本來不屬于的對象里面,把它們?nèi)甲鳛?ldquo;方法”,導(dǎo)致了面向?qū)ο蟠a邏輯過度復(fù)雜。很簡單的想法,非得繞好多道彎子才能表達清楚。很多時候這就像把自己的頭塞進屁股里面。

這就是為什么我喜歡開玩笑說,面向?qū)ο缶幊叹拖?ldquo;地平說”(Flat Earth Theory)。當(dāng)然你可以說地球是一個平面。對于局部的,小規(guī)模的現(xiàn)象,它沒有問題。然而對于通用的,大規(guī)模的情況,它卻不是自然,簡單和直接的。直到今天,你仍然可以無止境的尋找證據(jù),扭曲各種物理定律,自圓其說地平說的幻覺,然而這會讓你的理論非常復(fù)雜,經(jīng)常需要縫縫補補還難以理解。

面向?qū)ο笳Z言不僅有自身的根本性錯誤,而且由于面向?qū)ο笳Z言的設(shè)計者們常常是半路出家,沒有受到過嚴格的語言理論和設(shè)計訓(xùn)練卻又自命不凡,所以經(jīng)常搞出另外一些奇葩的東西。比如在Javascript里面,每個函數(shù)同時又可以作為構(gòu)造函數(shù)(constructor),所以每個函數(shù)里面都隱含了一個this變量,你嵌套多層對象和函數(shù)的時候就發(fā)現(xiàn)沒法訪問外層的this,非得bind一下。Python的變量定義和賦值不分,所以你需要訪問全局變量的時候得用global關(guān)鍵字,后來又發(fā)現(xiàn)如果要訪問“中間層”的變量,沒有辦法了,所以又加了個nonlocal關(guān)鍵字。Ruby先后出現(xiàn)過四種類似lambda的東西,每個都有自己的怪癖…… 有些人問我為什么有些語言設(shè)計成那個樣子,我只能說,很多語言設(shè)計者其實根本不知道自己在干什么!

軟件領(lǐng)域就是喜歡制造宗派。“面向?qū)ο?rdquo;當(dāng)年就是乘火打劫,扯著各種幌子,成為了一種宗派,給很多人洗了腦。到底什么樣的語言才算是“面向?qū)ο笳Z言”?這樣基本的問題至今沒有確切的答案,足以說明所謂面向?qū)ο螅径际浅兜C慨?dāng)你指出某個OO語言X的弊端,就會有人跟你說,其實X不是“地道的”OO語言,你應(yīng)該去看看另外一個OO語言Y。等你發(fā)現(xiàn)Y也有問題,有人又會讓你去看Z…… 直到最后,他們告訴你,只有Smalltalk才是地道的OO語言。這不是很搞笑嗎,說一個根本沒人用的語言才是地道的OO語言,這就像在說只有死人的話才是對的。這就像是一群政客在踢皮球,推卸責(zé)任。等你真正看看Smalltalk才發(fā)現(xiàn),其實面向?qū)ο笳Z言的根本毛病就是由它而來的,Smalltalk并不是很好的語言。很多人至今不知道自己所用的“面向?qū)ο笳Z言”里面的很多優(yōu)點,都是從過程式語言繼承來的。每當(dāng)發(fā)生函數(shù)式與面向?qū)ο笫秸Z言的口水戰(zhàn),都會有面向?qū)ο蟮膸捅娔贸鲞@些過程式語言早就有的優(yōu)點來進行反駁:“你說面向?qū)ο蟛缓茫此茏鲞@個……” 拿別人的優(yōu)點撐起自己的門面,卻看不到事物實質(zhì)的優(yōu)點,這樣的辯論純粹是雞同鴨講。

函數(shù)式編程(Functional Programming)

函數(shù)式語言一直以來比較低調(diào),直到最近由于并發(fā)計算編程瓶頸的出現(xiàn),以及Haskell,Scala之類語言社區(qū)的大力鼓吹,它忽然變成了一種宗派。有人盲目的相信函數(shù)式編程能夠奇跡般的解決并發(fā)計算的難題,而看不到實質(zhì)存在的,獨立于語言的問題。被函數(shù)式語言洗腦的幫眾,喜歡否定其它語言的一切,看低其它程序員。特別是有些初學(xué)編程的人,儼然把函數(shù)式編程當(dāng)成了一天瘦二十斤的減肥神藥,以為自己從函數(shù)式語言入手,就可以對經(jīng)驗超過他十年以上的老程序員說三道四,仿佛別人不用函數(shù)式語言就什么都不懂一樣。

函數(shù)式編程的優(yōu)點

函數(shù)式編程當(dāng)然提供了它自己的價值。函數(shù)式編程相對于面向?qū)ο笞畲蟮膬r值,莫過于對于函數(shù)的正確理解。在函數(shù)式語言里面,函數(shù)是“一類公民”(first-class)。它們可以像1, 2, "hello",true,對象…… 之類的“值”一樣,在任意位置誕生,通過變量,參數(shù)和數(shù)據(jù)結(jié)構(gòu)傳遞到其它地方,可以在任何位置被調(diào)用。這些是很多過程式語言和面向?qū)ο笳Z言做不到的事情。很多所謂“面向?qū)ο笤O(shè)計模式”(design pattern),都是因為面向?qū)ο笳Z言沒有first-class function,所以導(dǎo)致了每個函數(shù)必須被包在一個對象里面才能傳遞到其它地方。

函數(shù)式編程的另一個貢獻,是它們的類型系統(tǒng)。函數(shù)式語言對于類型的思維,往往非常的嚴密。函數(shù)式語言的類型系統(tǒng),往往比面向?qū)ο笳Z言來得嚴密和簡單很多,它們可以幫助你對程序進行嚴密的邏輯推理。然而類型系統(tǒng)一是把雙刃劍,如果你對它看得太重,它反而會帶來不必要的復(fù)雜性和過度工程。這個我在下面講講。

各種“白象”(white elephant)

所謂白象,“white elephant”,是指被人奉為神圣,價格昂貴,卻沒有實際用處的東西。函數(shù)式語言里面有很好的東西,然而它們里面有很多多余的特性,這些特性跟白象的性質(zhì)類似。

函數(shù)式語言的“擁護者”們,往往認為這個世界本來應(yīng)該是“純”(pure)的,不應(yīng)該有任何“副作用”。他們把一切的“賦值操作”看成低級弱智的作法。他們很在乎所謂尾遞歸,類型推導(dǎo),fold,currying,maybe type等等。他們以自己能寫出使用這些特性的代碼為豪。可是殊不知,那些東西其實除了能自我安慰,制造高人一等的幻覺,并不一定能帶來真正優(yōu)秀可靠的代碼。

純函數(shù)

半壺水都喜歡響叮當(dāng)。很多喜歡自吹為“函數(shù)式程序員”的人,往往并不真的理解函數(shù)式語言的本質(zhì)。他們一旦看到過程式語言的寫法就嗤之以鼻。比如以下這個C函數(shù):

int f(int x) {     

      int y = 0;      

      int z = 0;      

      y = 2 * x;    

      z = y + 1;

      return z / 3;

  } 

很多函數(shù)式程序員可能看到那幾個賦值操作就皺起眉頭,然而他們看不到的是,這是一個真正意義上的“純函數(shù)”,它在本質(zhì)上跟Haskell之類語言的函數(shù)是一樣的,也許還更加優(yōu)雅一些。

盲目鄙視賦值操作的人,也不理解“數(shù)據(jù)流”的概念。其實不管是對局部變量賦值還是把它們作為參數(shù)傳遞,其實本質(zhì)上都像是把一個東西放進一個管道,或者把一個電信號放在一根導(dǎo)線上,只不過這個管道或者導(dǎo)線,在不同的語言范式里放置的方向和樣式有一點不同而已!

 
 
[ 資訊搜索 ]  [ 加入收藏 ]  [ 告訴好友 ]  [ 打印本文 ]  [ 違規(guī)舉報 ]  [ 關(guān)閉窗口 ]

 
0條 [查看全部]  相關(guān)評論

 
網(wǎng)站首頁 | 關(guān)于我們 | 聯(lián)系方式 | 使用協(xié)議 | 版權(quán)隱私 | 網(wǎng)站地圖 | 排名推廣 | 廣告服務(wù) | 積分換禮 | 網(wǎng)站留言 | RSS訂閱 | 吉ICP備11001726號-6
企業(yè)800網(wǎng) · 提供技術(shù)支持