Thoughts💡 數學差就不能寫程式嗎?對 Computer Science 本質的心得與思考

Jayden Lin
程式猿吃香蕉
Published in
8 min readJul 18, 2020

筆者任職於 Yahoo ,粉絲團:《程式猿吃香蕉🍌

最近在學習《計算機程序的構造和解釋》(Structure and Interpretation of Computer Programs, SICP),是一本關於計算機程序設計的總體性觀念的基礎教科書。這本書寫於1980年代,名氣至今歷久不衰,算是在計算機科學領域被捧上天的神書。

一本1980年代的書,一開始就離經叛道地跟你說,Computer Science 不算是 Science ,更像是一種工程 (Engineering) 或是藝術 (Art) ,本書的內容對我的啟發實在是過於巨大,即使是已經從事軟體開發多年,依然被書中提到的許多概念所震懾,決定寫一篇文章來記錄心得。

對計算機科學的本質有了更深地理解後,我在這裡想要釐清了一個許多人常有的迷思:數學差是不是就不能當軟體工程師?

先說結論,兩者並無高度相關,數學差還是有機會可以當軟體工程師的。

以下我會從計算機科學的本質開始說明,在了解計算機科學的本質之後,你會知道計算機科學其實並不是那麼強調數學的學科,我們一起來了解吧!

▍計算機科學是一種控制複雜度的技術 (Technique of controlling complexity)

什麼是計算機科學?

計算機科學是一種控制複雜度的技術 (Technique of controlling complexity),這裡指的「複雜度」非常重要,它並不是「現實世界」的複雜度,而是指更高維度的「複雜度」。

Computer science is like an abstract form engineering. It’s kind of engineering we ignore the constraints imposed by reality.

計算機科學像是工程中的抽象形式,在這種科學中,我們忽略現實中的限制。

「忽略現實中的限制」聽起來很玄幻,我舉一個例子可以很快地說明:

以網頁動畫效果的製作來說,「現實世界」的複雜度,是如何計算物件的位移,以及物件的幾何形狀跟角度等等。計算機科學「並不是」處理這類的「現實世界」的複雜度的學科,它甚至可以「忽略現實中的限制」。

計算機科學的控制複雜度的技術 (Technique of controlling complexity),是幫助你找到一個通則、建立模組化,讓你下次製作網頁動畫效果時,可以更容易且更快。它更像是一種「減輕我們大腦理解負擔」所使用的技術。

例如 Vue.js (網頁前端開發框架) 的作者 Evan You,就是因為當初在 Google 任職時需要處理許多網頁效果,進而開發出 Vue.js 來幫助他快速完成工作,他在這裡所處理的「複雜度」便不是計算頁面長寬等等問題所指的複雜度了,而是更高維度地、更抽象化的複雜度。

The constraints imposed in building large software systems are the limitation of our own mind.

上面這句話,很好地說明了,計算機科學要控制的複雜度是什麼。

我們人的腦袋理解能力有限,當我們在建構大型系統時,人腦有限的理解能力,會變成系統的限制因素之一。而計算機科學控制複雜度的技術 ,可以幫助我們控制複雜度,進而建立大型的軟體系統。

這種「控制複雜度的技術」,我以一個簡單的實例來說明:

假設系統需要我定義累加函數、平方和函數、立方和函數以及開根號和函數,為了控制複雜度,我可以定義一個累加函數的「通則」,讓我很方便的計平方和、立方和、開根號和等等,程式碼如下所示:

一方面,當其他人在理解這個系統的時候,可以快速從 sum 這個詞理解這個函數是在做累加,暫時忽略累加函數的實作內容,減輕大腦的負擔。另一方面,我們將「平方」和「立方」的實作獨立出來,這樣的好處在於,對於平方和函數,你可以「分別」理解「平方」和「和」這兩個概念,這種關注點分離的想法,在物件導向程式設計裡面無處不見。

簡單來說,就是將一個問題抽象化,並且拆解,找出通則來控制複雜度。

▍實務層面的案例

這種「控制複雜度的技術」在實務層面有太多例子了,例如:

  1. 大數據領域的 MapReduce,提供了一個算法通則,讓我們可以專注在更重要的事情上,減輕我們大腦理解的負擔。
  2. 演算法中,我們掌握「深度優先路徑(DFS)」跟「廣度優先路徑(BFS)」的算法通則,可以拿來算地圖探索路線,錢幣排列組合等等問題。
  3. 演算法中的動態規劃(Dynamic programming),將大問題轉化成子問題,透過計算子問題的計算結果,拼湊出最終的答案,這也是計算機科學中控制「複雜度」的技術。
  4. 在前端領域中,使用 React.js 實作時所採用的 Higher order component (HoC) 也是將頁面元件分層抽象化,來控制軟體複雜度。
  5. 程式語言中的語法糖,降低人腦的理解負擔,也是控制複雜度出現的產物。
  6. 物件導向開發方式,幫助我們將物件分門別類,使系統更容易被理解,而Event Storming 等用來釐清領域物件的技術,也是幫助我們怎麼找出 Bounded Context,將其抽象化出來實作。
  7. 設計模式裡面,定義好介面,針對介面來寫程式,做到關注點分離,也是控制複雜度的技術。

這些其實是有方法論的,在企圖控制複雜度時,要找出:

  1. PRIMITIVE ELEMENT
  2. MEANS OF COMBINATION
  3. MEANS OF ABSTRACTION

來達到控制複雜度的效果。軟體工程師每天的工作內容,其實就是對目標問題不斷進行抽象化拆解,利用各種技巧控制複雜度的過程,這些技巧其實跟數學能力並無高度相關。

▍結語

許多人以為自己數學底不好,就不能當軟體工程師,其實這樣的觀念是不對的。只要你有能力將目標問題抽象化拆解,熟悉控制複雜度的技巧,雖然可能是利用函式庫去處理掉拆解後的子問題,但這並沒有關係。其實你還是可以成為一個不錯的軟體工程師的。當然,若是你的工作是屬於 Research 、鑽研人工智慧 、資料科學、演算法改善等專精的領域,數學還是會扮演吃重的角色,但不可否認的是,以計算機科學的本質來看,控制複雜度的技巧和數學能力的關係並不是那麼強烈相關,大部分的工作,甚至掌握了高中數學能力便能完成。

我並不是否定數學在計算機科學中的價值,我自己所待的公司也是在面試時非常強調演算法的派別,我也曾以此為圭臬來判定工程師的好壞,但在我過去的職涯裡,確實遇過一些數理能力、演算法能力普普,但總是可以把交辦任務漂亮完成的好夥伴,我一直無法解釋這件事,也不斷質疑自己判斷「好」工程師的標準是不是太過狹隘,直到我看到 SCIP 這本書,才理解是原來是他們具有良好的抽象化思考跟拆解問題的能力,讓他們可以妥妥地完成任務。

我認為建造軟體就像建立一座大廈,如果有前人造好的磚頭,就可以直接拿來使用,基礎好的人造磚頭,基礎不好的人使用別人的磚頭,這樣的人們組合起來分工合作,也會是一個能夠完成產品的團隊,當別人造的磚頭不好用,有數學底的人可以解決掉問題,但數學底不好的人可能會卡關,但這種由底層「溢出」的問題,若數學底不好,也許換一塊磚頭也能解決掉,這樣的軟體工程師可能「不夠好」,但我並不會說這樣的軟體工程師是「不好」。

當然,如果有一天想要自己造磚頭,那麼離散數學等等知識還是補足的,欠的債總是要還,數學能力的高低會影響你在軟體開發這條路能走多遠,但並不妨礙你啟程,雖然可能追逐了一輩子都「不夠好」,只能用別人的磚頭,但只要對得起自己手上的工作,對得起自己目前的薪水,有個不錯的家庭生活,那又何妨呢?

對於《計算機程序的構造和解釋》(Structure and Interpretation of Computer Programs, SICP)的學習心得,下一篇想要談談計算機科學中的 Wishful Thinking

若是喜歡我分享的內容,歡迎幫我按個拍手,可拍 50下,給我一點鼓勵,或是加入我的粉絲團《程式猿吃香蕉🍌,一起分享軟體知識與心得!

--

--

Jayden Lin
程式猿吃香蕉

曾在 Yahoo 擔任 Lead Engineer,負責廣告系統,帶團隊做跨國開發,現任職區塊鏈產業。也是《程式猿吃香蕉》團隊創辦人,喜歡將實用的軟體知識以簡單生動的方式講給大家聽 😄😄😄