說明
編程的本質與未來
這一課的內容都是從Bob大叔(Robert C. Martin)的書《敏捷軟件開發原則、模式與實踐》借鑑而來。筆者也寫過Bob大叔2016年的演講,可以配合來看。【編程的未來 Java, C, Go, Swift, Dart? Uncle Bob Martin - The Future of Programming 】
講師:李智慧
架構設計回顧
上面這張圖是上課的同學分類的,詳細設計很多時候也是架構師的工作內容。筆者在阿里任職期間,實際上是要做開發設計的,比較符合阿里的分類。
李智慧老師從初級工程師到首席架構師的躍遷
李智慧老師,第一份工作是05年做日本的一個大型系統,那個時候前端是VB,服務端是用Java。剛開始的時候,一共也是幾個人。最開始進去時候發現用VB調用Java Server,還沒有辦法直接調用。那個時候高手都到日本出差去了,李智慧老師給項目經理說了這個gap。項目經理也不懂技術,項目經理就說既然你提出這個問題,你就負責做這個組件吧。李智慧老師週末就看了Struts的架構,用兩天時間畫了一些組件圖。週一就找項目經理評審,項目經理就協調了一些技術高手過來評審,覺得沒什麼大的問題。項目經理說現在項目還沒開始,剩下的幾個人就交給你分配任務,完成這個組件,並用一個業務做個Demo。最終組件就按照計劃實現了,業務Demo也跑通了。後來大業務團隊都從日本回來了,因爲時間關係,大家就用了李智慧老師的框架,200多人的大團隊都用了這個模塊組件來進行前後端通信。高手們也提出一些改進計劃,李智慧老師,後面就不斷優化這個通信模塊組件。整個團隊都要李智慧老師培訓,前端、後端如何用這個模塊,包括後面入職新員工,都是由李智慧老師培訓如何用該通信組件開發。李智慧老師從剛入職的低級新員工,到離開的時候就成了首席架構師。
第二份工作,李智慧老師跳槽到另一家日本公司,做的類似於Tomcat這種中間件,脫離了業務,專門去做技術架構。李智慧老師,覺得這兩份工作經歷爲他後來的職業生涯提供了很大的幫助。
軟件開發簡史
從編程的歷史看編程的本質和未來
請帶着以下問題觀看本節課的內容。
你還在用面向對象編程語言寫面向過程的代碼嗎?
萊布尼茲的奇思怪想
萊布尼茲就是跟牛頓打了一輩子官司,誰是微積分的發明人。二進制就是萊布尼茲發明的。一切信息都可以用二進制表示。
計算機軟件編程是個非常新興的行業,程序員這一職業的出現不過半個多世紀,但是人類從事編程的探索卻要久遠的多,在計算機出現之前,甚至蒸汽機出現之前,人類就開始探索軟件編程了。
最早開始編程探索的人是德國人萊布尼茲,早在1700年代,萊布尼茲就期望將各種事物都通過一種邏輯語言進行描述,然後用一種可執行演算規則的機器進行計算,就可以計算出事物的各種結果。這種思想其實和我們現代的軟件編程與計算機已經差不多了,萊布尼茲爲了實現這個想法,進行了大量的工作,獲得了豐碩的成果,其中就包括了微積分和二進制。
萊布尼茲是計算機思想,後來科學家布爾,用Bool實現了邏輯編程。(就是Bool變量的這個布爾。)
人類第一位程序媛
萊布尼茲製造可編程計算機的夢想沒有成功。又過了100年,法國人雅卡爾發明了一臺可編程的織布機,這種織布機讀取紙帶上的打孔,進而控制織布機織出不同的圖案。於是人們開始嘗試將打孔紙帶用於計算機編程,19世紀中葉,當英國人 Ada 利用打孔紙帶寫出人類第一個軟件程序的時候,距離能夠運行這個程序的計算機發明還有100年的時間,而這個程序已經包含了循環和子程序。 Ada 因此被認爲是人類第一個程序員, 準確來說,是程序媛。科技發明受時代的限制,天才們的想象力和聰明才智卻可以超過時代。
什麼是計算機?什麼是程序?
人類發明製造計算機器有非常悠久的歷史,但是這些計算機器都是專門進行數值計算的,加減乘除、微分積分等等。而從萊布尼茲、Ada,到圖靈、馮諾依曼,這些現代計算機的開創者們試圖創造的是一種通用的計算機,這種計算機不是讀取數值進行計算,而是讀取數據進行計算,這些數據本身包含着計算的邏輯,這個數據就是程序。
現代計算機與現代的程序
當馮諾依曼在 ENIAC 計算機上輸入第一個程序的時候,標誌着現代計算機的誕生,也意味着軟件編程這一新興行業即將出現。
最早的計算機編程非常麻煩,程序員需要將電線編來編去,作爲輸入數據,以控制計算機的執行,這也是編程這個詞的由來。不過很快人們就將打孔紙帶應用到計算機上,編程的效率極大提升。
面向電線編程的時代。
形形色色的編程語言
彙編語言(以下爲6502彙編)
2000: BMI $2009 ;若結果爲負數,那麼轉地址2009
2002: BEQ $200C ;若 = 0,轉地址 200C
2004: CLC ;這裏說明 > 0
2005: ADC #$01
2007: TAY
2008: RTS
2009: LDY #$01
200B: RTS
200C: LDY #$00
200E: RTS
每一種 CPU 都有獨特的機器語言,因而需要不同的彙編語言。
早期的 Basic 語言
10 CLS:J=1:TROFF:KEY OFF:DIM Z(30),B$(20,20),C(30),BS(22):BS=0:BS$(1)="YES":BS$(0)="NO":DIM BU$(11),PL(11),DI$(11),CH(11),SC(11),CH$(11),P2(11):P2(11)=3
11 FOR I=0 TO 7:READ B$(I,10):NEXT I
12 FOR I=1 TO 4:READ B$(I,8):NEXT I
13 FOR I=0 TO 7:READ B$(I,12):NEXT I
14 FOR I=1 TO 4:READ B$(I,14):NEXT I
15 P1=3:QF=1:L$="A":R$="D":U$="W":D$="S":P$="P":Q$="Q":M$="O" 16 FOR I=1 TO 2:READ B$(I,18):NEXT I
17 FOR I=1 TO 2:READ B$(I,20):NEXT I:FOR I=1 TO 30:C(I)=2:NEXT I:C(20)=1
20 COLOR 7,0,0:CLS:DIM NA$(11):DIM NAM$(40)
21 FOR I=1 TO 11
23 READ P2(I),BU$(I),DI$(I),CH(10),SC(I),NA$(I)
25 NEXT I:PLAY "T500"
早期 Basic 語言雖然號稱爲 “高級語言”, 但是保留了彙編語言的特性 – 地址(即行號)。
結構化的 Basic 語言(Quick Basic、Visual Basic等)
DO
SCREEN 7, , APage%, VPage% ' Draw to the active page
' while showing the visual page.
' Clear the active page.
CLS 1
' Rotate the cube "Angle%" degrees:
DRAW "TA" + STR$(Angle%) + Plot$
' Angle% is some multiple of 15 degrees:
Angle% = (Angle% + 15) MOD 360
' Drawing is complete, so make the cube visible in its
' new position by switching the active and visual pages: SWAP APage%, VPage%
LOOP WHILE INKEY$ = "" ' A keystroke ends the program.
結構化的 Basic 語言仍然兼容傳統的 Basic,而且提供了更好的集成開發環境IDE。
結構化的編程取消了 “地址” 和 Goto 語句,代之以幾種程序控制 “結構”, 如:循環、條件等。
Perl 語言
package Horse;
@ISA = qw(Animal);
sub sound { "neigh" }
sub name {
my $self = shift;
$$self;
}
sub named {
my $class = shift;
my $name = shift;
bless \$name, $class;
}
my $talking = Horse->named("Mr. Ed");
print $talking->name;
Perl 是一種腳本語言,最強大的功能是正則表達式。但 Perl 的語法比較晦澀難懂。 Perl 是一種 “僞” 的面嚮對象語言。
C 語言
#include <stdio.h>
#include <stdib.h>
int main(void) {
puts("Hello World!");
return EXIT_SUCCESS;
}
C 語言是一個結構化的語言
C++ 語言
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, world!" << endl;
return 0;
}
C++ 向後兼容 C 的所有功能,並且提供了面向對象的編程機制。
Java 語言
package zgpeace.test;
public class TestMain {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Java 是一個完全面向對象的語言,尤其是在當今的 Internet 編程領域,佔領了絕對的市場。
編程語言的實質
編程的目的是:用計算機來解決現實世界的問題。
編程的過程即:在計算機所能理解的 “模型” (解空間)和 現實世界 (問題空間)之間,建立一種聯繫。
編程語言是一種 “抽象” 的機制, 問題是對 “誰” 來抽象。
問題領域(Problem Domain)
包含與系統所要解決的問題相關的實物和概念空間。
面向對象就是面向問題領域中的對象的編程。
抽象的種類
機器代碼和彙編語言
- 對基礎機器進行抽象
非結構化的高級語言(如 Basic,Fortran等)
- 對計算處理邏輯抽象
結構化的程序設計
- 開始對問題領域進行一定程度的抽象
面向對象的程序設計
- 直達表達問題空間內的元素
編程方法的演講
編程的核心要素
面向對象是編程語言發展的最高階段,新出來的語言都是面向對象的語言。
從萊布尼茲編程開始,只要編程的認知不變,新的編程語言不會超過面向對象的語言,40多年的面嚮對象語言一直沒有變過。
面向對象編程的細分領域。最近幾年,新的語言有些變化,面向數據的語言。機器學習,AI編程的出現,Scala函數式編程語言,比較適合面向數據編程。不同的函數之間調用,是異步執行的。
什麼是面向對象編程
第一個成功的面向對象的語言 Smalltalk 描述:
- 萬物皆爲對象。
- 程序是對象的集合,它們通過發送消息來告知彼此所要做的。
- 每個對象都有自己的由其它對象所構成的存儲。
- 每個對象都擁有其類型。
- 某一特定類型的所有對象都可以接受同樣的消息。
C++ 和 Java 等後期的面嚮對象語言,都是在這個基礎上設計的。
什麼是對象
Booch 對於對象的描述:對象具有狀態、行爲和標識。
- 狀態: 表明每個對象可以有自己的數據。
- 行爲:表明每個對象可以產生行爲。
- 標識:表明每個對象都區別於其它對象。(唯一的地址)
無狀態對象,對象沒有自己的數據,對象的數據都是通過參數傳進來的,處理完後就沒有了。
面向對象編程的三要素(特徵)
封裝性(Encapsulation)
- 隱藏實現細節(訪問控制)
- 定義接口
繼承性(Inheritance)
- IS-A 關係
- HAS-A 關係(組合)
多態性(Polymorphism)
- 後期綁定(虛函數)
- 向上轉型 (Up Casting)
封裝性 - 隱藏實現
封裝並不是面嚮對象語言獨有的。
面向過程的編程語言,比如 C 語言,也可以實現封裝特性,從頭文件 .h
裏面定義方法,而在實現文件 .c
文件裏定義具體的結構體和方法實現,從而使依賴 .h
頭文件的外部程序只能夠訪問頭文件裏定義過的方法,這樣同樣實現了變量和函數的封裝,以及訪問權限的控制。
繼承性 – 接口的重用
集成也不是面向對象獨有的。
C 語言也可以實現繼承。如果 A 結構體包含 B 結構體的定義,那麼就可以理解成 A 集成了 B, 定義在 B 結構上的方法可以直接(通過強制類型轉換)執行 A 結構體的數據。
多態性 – 對象互換的魔法
多態也不是面向對象獨有的。因爲指向函數的指針,多態事實上在 C 語言中也可以實現。
但是使用指向函數的指針實現多態是非常危險的,因爲這種多態沒有語法和編譯方面的約束,只能靠程序員之間約定,一旦出現 bug,調試非常痛苦。因此在面向過程語言的開發中,這種多態並不能頻繁使用。
而在面向對象的編程語言中,多態非常簡單:子類實現父類或者接口的抽象方法,程序使用抽象父類或者接口編程,運行期注入不同的子類,程序就表現出不同的形態,是爲多態。
多態是面嚮對象語言最重要的特性,如果沒有用好多態,那就是沒有掌握好面向對象編程。
總結
面向對象是編程語言發展的最高階段,新出來的語言都是面向對象的語言。
從萊布尼茲編程開始,只要編程的認知不變,新的編程語言不會超過面向對象的語言,40多年的面嚮對象語言一直沒有變過。
面向對象編程的細分領域。最近幾年,新的語言有些變化,面向數據的語言。機器學習,AI編程的出現,Scala函數式編程語言,比較適合面向數據編程。不同的函數之間調用,是異步執行的。
注意:以上信息如有侵權,請聯繫作者刪除,謝謝。