「面向對象就是一個錯誤!」

2021-03-04 算法愛好者

面向對象編程的流行是計算機科學領域的不幸,它對現代經濟造成了極大的破壞,造成了數萬億美元的間接損失。在過去的三十年中,幾乎所有行業都因潛在的面向對象編程危機而受到影響。

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

相關焦點

  • 面向對象的特徵和原則
    面向對象中的三個基本特徵:封裝、繼承和多態1、封裝,將現實中事物抽象成計算機領域中的對象,對象同時具有屬性和行為,這就是封裝。在封裝中,數據隱藏,對象只對外提供與其他對象交互的接口,把自身的一些屬性和實現細節對外是隱藏的。
  • Python面向對象編程的基本概念
    面向對象程序設計(OOP)與面向過程程序設計(POP)OOP的主要概念什麼是課程?對象和對象實例化類方法Python類中的繼承封裝形式多態性數據抽象什麼是面向對象的編程?面向對象編程(OOP)就是創建「對象」。對象是一組相互關聯的變量和函數。這些變量通常稱為對象的屬性,而功能則稱為對象的行為。這些對象為程序提供了更好,更清晰的結構。例如,汽車可以是物體。
  • 《深入淺出面向對象分析與設計》讀後感|王鵬
    2、運用基本的OO即面向對象設計原則來增加軟體的靈活性告訴我們要用面向對象而非面向過程的思想去實現我們的系統,在軟體設計的過程中儘量的使用像封裝、繼承、多態等面向對象的技術,使我們的程序更加靈活,良好的設計等於靈活的軟體。為了使軟體靈活可擴展,要學會利用面向對象的設計原則降低應用程式的耦合度。
  • 一個老程式設計師寫的:《面向對象的JavaScript編程:原理與實踐》
    (更不用說它是前臺開發的唯一正式語言),但是還是有人詬病其不夠嚴謹,爭論它是不是完全符合面向對象(Object-Oriented)語言的特徵。本書並不想參與任何無謂的或者純理論的討論,只想理清JS的對象到底是怎麼回事,以及怎麼使用JS最有效地面向對象編程,和它的局限性在哪兒。感謝非常感謝 Jiang Hao 提供的寶貴意見。
  • 再談JavaScript面向對象編程
    導讀:陳皓曾發表過一篇文章《Javascript 面向對象編程》,珠玉在前,作者還是忍不住再畫蛇添足的補上一篇文章,主要是因為JavaScript這門語言魅力。另外這篇文章是一篇入門文章,是作者才開始學習Javascript,有一點心得,才想寫一篇這樣文章,文章中難免有錯誤的地方,還請各位不吝吐槽指正。
  • Java面向對象程序設計的基本概念
    在面向對象程序設計中,類是一個獨立的單位,它有一個類名,其內部包括成員變量,用於描述對象的屬性;還包括類的成員方法,用於描述對象的行為。在 Java 程 序設計中,類被認為是一種抽象數據類型,這種數據類型,不但包括數據,還包括方法。這大大地擴充了數據類型的概念。
  • TIA Portal面向對象編程入門
    我們完全可以跳過這個過程,直接以面向對象的思想來編寫PLC程序。一旦熟悉了面向對象編程,相信你再也不願意回到面向過程這種方式。面向對象編程的三大特徵是封裝、繼承和多態。以TIA Portal為例,儘管對這三個特性支持的不徹底(比如無法禁止訪問實例的私有變量),但是這並不妨礙我們在S7-1200/1500中使用面向對象來編程。
  • 你真的知道面向過程和面向對象的區別嗎?
    面向對象在日常生活或編程中,簡單的問題可以用面向過程的思路來解決,直接有效,但是當問題的規模變得更大時,用面向過程的思想是遠遠不夠的。所以慢慢就出現了面向對象的編程思想。世界上有很多人和事物,每一個都可以看做一個對象,而每個對象都有自己的屬性和行為,對象與對象之間通過方法來交互。
  • 如何使用JavaScript -面向對象編程
    面向對象編程 —— Object Oriented Programming,簡稱 OOP ,是一種編程開發思想。它將真實世界各種複雜的關係,抽象為一個個對象,然後由對象之間的分工與合作,完成對真實世界的模擬。在面向對象程序開發思想中,每一個對象都是功能中心,具有明確分工,可以完成接受信息、處理數據、發出信息等任務。
  • R 的面向對象編程系統(S3、S4系統介紹)
    藉助面向對象的編程風格,我們通過定義對象的類以描述對象,通過定義對象的方法以抽象完成實際中的某種具體實現,以這樣的方式,我們可以模仿對象的重要特性。S3 系統在 R 中,S3 對象系統是一個簡單且寬鬆的面向對象系統。每個基本對象的類型都有一個 S3 類名稱,如 integer、numeric、character、logical、list 和 data.frame 等都屬於 S3 類。
  • C風格的面向對象編程
    面向對象編程(OOP),最早是C++、java等面向對象語言的一個核心特點,之後發展成了一種編程思想。面向對象編程的主要特點是,把屬性(數據)與方法(函數)按照類型綁定,並按照類型之間的關係分層分模塊設計,通過基類指針和虛函數實現多態。
  • 面向對象編程
    面向對象編程(OOP)對於初學者來說可能是一個很難理解的概念。很多書籍都是從解釋OOP開始,討論三大術語:封裝、繼承和多態性,但是解釋的效果往往讓人失望。本文希望讓程式設計師、數據科學家和python愛好者們更容易理解這個概念。我們去掉所有的行話,通過一些例子來做解說。這篇文章是關於解釋OOP的外行方式。
  • 面向對象聖經
    有人寫了一個程序,用一個數據結構和函數實現了一個簡單的棧。上帝說:「要有Class!把這些重複的方法代碼從對象中剝離出來,放到一個公共的Class中!void push(Stack *s,int data)」上帝告誡說:「雖然本質相同,但是表達形式不同,之前你在語法層面必須傳遞一個Stack 對象到函數,現在在語法層面不用加了。我會在編譯後的代碼,或者運行時自動給你們加上。」Guido說:「我還是喜歡把self加到方法上!」上帝沒有說話,應該是默認了。
  • C語言實現面向對象的原理
    雖然我們的教材有這麼一個結論:C語言是面向過程的語言,C++是面向對象的程式語言,但面向對象的概念是在C語言階段就有了,而且應用到了很多地方,比如某些作業系統內核、通信協議等。面向對象編程,也就是大家說的OOP(Object Oriented Programming)並不是一種特定的語言或者工具,它只是一種設計方法、設計思想,它表現出來的三個最基本的特性就是封裝、繼承與多態。閱讀文本之前肯定有讀者會問這樣的問題:我們有C++面向對象的語言,為什麼還要用C語言實現面向對象呢?
  • 高級篇PLC的面向對象編程
    繼承」,甚至於它根本就不具備面向對象程式語言的特點,但面向對象編程的基本概念就是類和類的實例(即對象),我們只需要使用這種概念就可以了。「FB塊」被看 成「類」,它可以被看成是對相似的控制對象的代碼歸納,如對MM440的變頻器可以編寫FB塊:MtrMM440,這在面向對象編程中稱為「類」,當需要 編程控制具體的電機時,可以給它分配一個背景DB塊,在面向對象編程中稱為類的實現(即創建類的實例:對象),當需要控制多個電機時,可以分配不同的背景 DB到這個FB塊,即創建類的多個實例。
  • RT-Thread面向對象編程思路淺析
    在寫這篇文章前,我們需要理解面向對象與面向過程的思想。面向過程就是遇到一個問題,將這個問題解決辦法一步一步的列出來,就想下棋一樣,一步一步走,根據具體情況調整思路。而面向過程就是將邏輯抽象化,就是抽象成一個物體或者對象。
  • 面向對象的六原則一法則,而現實中只需要一個原則:老婆,我錯了
    所謂的高內聚就是一個代碼模塊只完成一項功能,在面向對象中,如果只讓一個類完成它該做的事,而不涉及與它無關的領域就是踐行了高內聚的原則,這個類就只有單一職責。我們都知道一句話叫」因為專注,所以專業」,一個對象如果承擔太多的職責,那麼註定它什麼都做不好。
  • 史上最全 Python 面向對象編程
    面向過程編程:1. 導入各種外部庫2. 設計各種全局變量3. 寫一個函數完成某個功能4. 寫一個函數完成某個功能5. 寫一個函數完成某個功能6. 寫一個函數完成某個功能7. 寫一個函數完成某個功能8. .9.
  • 一篇非常全的Python 面向對象編程
    .html面向對象編程和函數式編程(面向過程編程)都是程序設計的方法,不過稍有區別。寫一個main函數作為程序入口在多函數程序中,許多重要的數據被放置在全局數據區,這樣它們可以被所有的函數訪問。每個函數都可以具有它們自己的局部數據,將某些功能代碼封裝到函數中,日後便無需重複編寫,僅調用函數即可。從代碼的組織形式來看就是根據業務邏輯從上到下壘代碼 。面向對象編程:1.
  • Java基礎教學之面向對象概述
    面向對象概述尹成課程資料及演示AAAjiaoyuwang面向對象是一種符合人類思維習慣的編程思想。現實生活中存在各種形態不同的事物,這些事物之間存在著各種各樣的聯繫。在程序中使用對象來映射現實中的事物,使用對象的關係來描述事物之間的聯繫,這種思想就是面向對象。