2020-05-17 面向對象編程的興衰

轉載自CSDN

不锰悼,面向對象編程(OOP)并沒有消亡。但它遠沒有以前那么流行了团赏。

我記得當時在90年代箕般,關于面向對象編程的教科書和計算機科學課程很多。當時那就是“風口”舔清,下一波潮流丝里。如果你沒有以那種方式編程,你就不是一個優(yōu)秀的程序員体谒,或者至少是可悲地落后于時代發(fā)展潮流了杯聚。

當時,CS專業(yè)的學生以非常嚴格和教條化的方式學習OOP抒痒。從業(yè)者們不僅被鼓勵以對象和類的形式構建他們的應用程序幌绍,甚至被認為應該根據對象和類來考慮問題空間。這樣的做法被稱為“面向對象的分析和設計”故响。

然而傀广,隨著時間的推進,人們開始意識到嚴格的面向對象方法會帶來許多問題彩届。這些問題往往會使代碼復雜化伪冰,難以理解而且難以測試。

事實證明樟蠕,OOP在某些問題領域確實比其他方法更出色贮聂。例如,OOP仍然是構建用戶界面(窗口和按鈕)的最自然的方式坯墨。但是寂汇,試圖使面向對象適應關系數據庫一直以來都簡直是一場災難。

以下是我所觀察到的一些問題:

“鴨嘴獸”效應

現實世界并不總是能被整潔地劃分為具有明確屬性定義的類(class)捣染。

例如骄瓣,假設你創(chuàng)建了一個代表動物王國的類層次結構。有爬行動物——冷血,有鱗片榕栏,卵生等等畔勤。還有哺乳動物——溫血,有絨毛扒磁,胎生庆揪。以及鳥類,兩棲動物妨托,無脊椎動物等等

然后鴨嘴獸出現了缸榛,它似乎不適合你的任何類別。你該怎么做呢兰伤?

你是創(chuàng)建一個全新的類別呢内颗,還是重新考慮整個分類方案?這兩種方法在工作量和程序復雜性方面都會產生巨大的成本敦腔。

深層次結構

我記得我在谷歌工作時均澳,當時我們有一個JavaScript庫叫goog.ui,它被用于創(chuàng)建基于Web的用戶界面符衔。以下是此庫中某個UI組件的繼承層次結構示例:

class ToolbarColorMenuButton* inheritsfrom ColorMenuButton?* inheritsfrom MenuButton?* inheritsfrom Button?* inheritsfrom Control?* inheritsfrom Component?* inheritsfrom EventTarget?* inheritsfrom Disposable?* inheritsfromObject

九個級別的類找前。太多了。

但情況會變得更糟判族。

許多高級類被只與少數子類相關的方法和屬性“污染”躺盛。例如,“Control”類有超過90種方法(method)形帮。它具有設置狀態(tài)的方法颗品,即使特定的子類是無狀態(tài)的; 它有添加和刪除子元素的方法,即使對control來說子元素沒有意義沃缘。

這種復雜性的一個重要原因是,該庫的作者試圖組織組件的不同方面——例如組件是按鈕還是滑塊则吟,或者它是否有顏色——并通過將它們放入類的不同層次來實現這一點槐臀。

但實際上,這些不同方面彼此之間無關氓仲∷咖啡杯是紅色的,和它是由陶瓷制成的敬扛,這是兩個獨立的特性晰洒。將紅色咖啡杯劃入“紅色物品”類別,還是將其放入“陶瓷制品”甚至“家居用品”類別中都是同樣正確的啥箭。任何一個選擇都是任意的谍珊,因為類別是由人頭腦中的反映和社會結構決定的。

在Google工作的最后幾年里急侥,我創(chuàng)建了一個名為“Quantum Wiz”的新用戶界面工具包砌滞,旨在替代goog.ui侮邀。我們采用的規(guī)則之一(以典型的Google風格,以方程式編寫)是:

composition > inheritance

用直白的英語解釋的話贝润,這說的是:

“更偏向于采用組合的思路——也就是說绊茧,能夠用更小的構建塊來組裝組件的功能——而不是繼承作為代碼重用的手段〈蚓颍”

因此华畏,舉個栗子,如果按鈕有顏色尊蚁,你將采用常規(guī)的“Button”對象(object)并向其添加“Color”方面(aspect)亡笑,作為屬性或子對象,而不是創(chuàng)建一個新的“Color Button”類枝誊。

作為這項任務的結果况芒,新工具包的類層次結構相對較淺,如果我沒記錯的話叶撒,只有兩三個級別绝骚。而且更容易理解和使用,也更強大祠够。

(感謝Malte Ubl向我介紹了組合大于繼承的概念压汪。)

對象不是真實的

Buckminster Fuller曾經說過:“事物并不存在”。他的意思是古瓤,事物之間的區(qū)別主要由人的偏見導致止剖。

例如,我坐的沙發(fā)是由分子力束縛在一起的原子的集合落君。然而穿香,這些原子也會受到房間內其他物體的影響——地毯,茶幾绎速,甚至是房間內的空氣皮获。沙發(fā)本身由各種部件組成——織物,木材纹冤,金屬彈簧等等——它們也受到分子力的約束洒宝。那么沙發(fā)是一個對象,還是很多對象萌京?也許世上只有一個對象——即我們所在的這個宇宙雁歌。

因為人類的視覺和觸覺在很大程度上只對表面屬性有響應——比如顏色和質感——我們傾向于基于表面現象對世界進行分類。相反知残,想象一下靠瞎,如果我們能夠直接感知周圍物體內的分子組成。我們可能會看到一個“銅”對象,代表著房屋中的所有布線和管道较坛,一個“氮”對象印蔗,代表著房間的氣體,一個“水”對象丑勤,一個“木頭”對象华嘹,等等。

Fuller的觀點是法竞,我們將世界“解析”為離散的“事物”的能力是任意的耙厚,這更多地反映了我們的人類心理而不是物理現實。

因為面向對象的繼承涉及將事物組織成類岔霸,所以它不能很好地模擬現實世界; 但它能很好地模擬人類思考現實世界的方式薛躬。

方法(method)也不真實

我記得大約二十年前的一段小插曲,一位軟件供應商的技術代表試圖向我司的工程人員解釋OOP呆细。他試圖爭辯說型宝,面向對象是一種模擬現實世界的方式,他給出的例子就像上面說的咖啡杯那種絮爷。他說杯子可能有個“drink()”的方法趴酣。

我記得的是,我對此有一個非常強烈的反應——我認為他所說的完全是胡說八道坑夯。除了它的特定目的之外岖寞,一個物理對象可以有許多用途。我可以用咖啡杯作為鎮(zhèn)紙或門擋; 這是否意味著它有一個“holdDownPapers()”或“keepDoorOpen()”方法柜蜈?我可以將它用作武器仗谆,玩具或藝術品。我甚至可以將杯子碎成碎片淑履,或將其研磨成粉末隶垮,并以創(chuàng)造性的方式使用其殘余物。

內部邏輯與外部邏輯

嚴格的OOP風格的一個原則是秘噪,永遠不可能從外部改變對象的內部狀態(tài)岁疼。任何改變對象狀態(tài)的業(yè)務或應用程序邏輯都必須作為對象本身的方法實現。因此缆娃,舉個栗子,如果要刪除文本字段中的所有文本瑰排,則不能簡單地進行:

textField.value = ""; // Settoemptystring

這將違背規(guī)則贯要。相反,你不得不這樣:

textField.clear(); // Clear the content of the field

對于簡單的操作椭住,這沒關系崇渗。但是這很容易過火,特別是正在進行的操作處理的是不同對象之間的復雜關系時。

有時候宅广,如果算法獨立于任何對象之外葫掉,反而更好。這真的是一個重要的問題:對于這個問題集跟狱,你更關心名詞還是動詞俭厚?

下面這是一個具體的例子:最近我開始研究編譯器(編寫編譯器是我的一個愛好; 在我做游戲開發(fā)的時候,我發(fā)明了許多腳本語言)驶臊。在過去挪挤,當我編寫編譯器時,我會采用非常嚴格的OOP方法來設計內部數據結構关翎。有各種類層次結構表示抽象語法樹扛门,表達式圖,類型等纵寝。

通常论寨,編譯器通過一系列階段或“傳遞”來處理這些數據結構,每一步的輸出被送到下一步的輸入中爽茴。

在過去葬凳,我傾向于按照推薦的OOP樣式為每個操作中的每個對象設置一些邏輯。這帶來不好的后果闹啦,當我添加更多步驟時沮明,對象變得越來越復雜。

更糟糕的是窍奋,這使得給這些對象寫單元測試異常困難荐健。這些復雜的對象在被創(chuàng)建出來之前就需要大量的基礎結構。這意味著為了測試一個對象琳袄,我必須創(chuàng)建大量的腳手架來滿足所有先決條件江场。

結果,我的測試覆蓋率往往很差窖逗,因為編寫測試是一項耗費大量精力的工作址否。

最近,我采取了另一種方法碎紊。在我最新的編譯器中佑附,所有這些內部數據結構都是“傻瓜型”的,意思是說它們所做的只是保存數據而已仗考,沒有別的音同。用于操作和轉換對象的所有代碼都在這些對象的外部。

這對代碼的組織有很大的好處秃嗜。每個算法都集中在一個地方权均,而不是分散在一堆源文件中顿膨。當我想測試一個特定的編譯器操作時,我可以輕松地創(chuàng)建一些示例對象并將其提供給該操作叽赊。因此恋沃,我的測試寫起來更容易了,所以我就能寫更多的測試了必指,從而就能有比以前更好的測試覆蓋率了囊咏。

關系數據庫

前面我提到過,以面向對象的方式處理關系數據庫會有問題取劫。對象關系映射(ORM)被一位評論家稱為計算機科學領域的越戰(zhàn)匆笤。(警告——那篇文章很長,很深奧谱邪,而且有點傾向性炮捧。)

我的大致感覺是,在處理大數據時惦银,你不應將你的記錄視為“對象”咆课。關系數據庫非常強大,但它們提供的強大功能并不是非吵毒悖“類似對象”书蚪。我傾向于認為關系數據流更像流體,你可以使用代數運算的方式來劃分迅栅,轉換和組合數據殊校。

函數式編程

在過去十年左右的時間里,人們越來越關注函數式編程(FP)读存。與OOP一樣为流,函數式編程不僅僅是單純的一件事物,而是一套整體的風格上的原則让簿。然而敬察,它的要點是,雖然OOP專注于與對象進行交互或通信尔当,但在FP中莲祸,重點在于對它們的轉換。這里的“轉換”椭迎,意思是你獲取一些對象锐帜,將它傳遞給一個函數,結果是一個全新的對象畜号,代表著對輸入內容所做的一些轉換缴阎。原始對象要么被保留,要么被丟棄弄兜,但不會以任何方式被更改或修飾药蜻。

在我自己的編程過程中,我更喜歡“混合”方法替饿,在某些地方使用FP技術语泽,而在其他地方使用OOP技術。在解決某些問題上FP確實能大放異彩视卢,但也有另一些問題上OOP是更明智的選擇踱卵。

我知道很多FP愛好者都熱衷于“純粹”的函數式語言,其中所有對象都是不可變的据过,并且只能被轉換惋砂,而不能被修改。然而绳锅,我發(fā)現純粹的方法傾向于把某些相對簡單的編程實踐變成謎題西饵。我的意思是一些聰明的,但不那么顯而易見的技巧鳞芙,這能吸引那種喜歡腦筋急轉彎的人眷柔,但是對其他人來說卻是完全無法理解的。

因此原朝,我傾向于在合理的范圍內使用FP驯嘱,使閱讀我代碼的普通程序員都能理解。如果我想做任何抖機靈的事情喳坠,我會寫一篇長篇評論來解釋我所做的事情鞠评,以及它是如何work的(這滿足了我炫耀的心理——我經常認為編程應該是一種表演藝術。)

所以壕鹉,面向對象編程不再有昔日的輝煌了剃幌。它仍然是一個很好的工具,仍然值得學習御板。但它已跌下神壇锥忿,你很難再看到有人能像 25 年前那樣,以宗教般的狂熱來吹捧它了怠肋。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末敬鬓,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子笙各,更是在濱河造成了極大的恐慌钉答,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杈抢,死亡現場離奇詭異数尿,居然都是意外死亡,警方通過查閱死者的電腦和手機惶楼,發(fā)現死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門右蹦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诊杆,“玉大人,你說我怎么就攤上這事何陆〕啃冢” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵贷盲,是天一觀的道長淘这。 經常有香客問我,道長巩剖,這世上最難降的妖魔是什么铝穷? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮佳魔,結果婚禮上曙聂,老公的妹妹穿的比我還像新娘。我一直安慰自己吃引,他們只是感情好筹陵,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著镊尺,像睡著了一般朦佩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庐氮,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天语稠,我揣著相機與錄音,去河邊找鬼弄砍。 笑死仙畦,一個胖子當著我的面吹牛,可吹牛的內容都是我干的音婶。 我是一名探鬼主播慨畸,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼衣式!你這毒婦竟也來了寸士?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碴卧,失蹤者是張志新(化名)和其女友劉穎弱卡,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體住册,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡婶博,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了荧飞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凡人。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡名党,死狀恐怖,靈堂內的尸體忽然破棺而出挠轴,到底是詐尸還是另有隱情兑巾,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布忠荞,位于F島的核電站,受9級特大地震影響帅掘,放射性物質發(fā)生泄漏委煤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一修档、第九天 我趴在偏房一處隱蔽的房頂上張望碧绞。 院中可真熱鬧,春花似錦吱窝、人聲如沸讥邻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兴使。三九已至,卻和暖如春照激,著一層夾襖步出監(jiān)牢的瞬間发魄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工俩垃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留励幼,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓口柳,卻偏偏與公主長得像苹粟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子跃闹,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359