2013年8月30日 星期五

理解基本原理,才不致踩到地雷

電腦科學基礎與程式設計 第2回在黑盒子的包裝下,不了解電腦原理的人也可以寫程式,但防護罩會有漏洞,小心踏入陷阱而不自知

大眾普遍認知電腦科學是程式設計的本門學科,但我們時常可以看到許多程式設計高手,都不是修讀電腦相關科系畢業的,這其實是一個共通的疑問。也就是說,如 果你是一名程式人,或是有志於程式設計領域的人,該不該修讀電腦科學呢?在課堂上所修讀的電腦科學,和實務的程式設計工作,又存在什麼關聯性呢?我將在本 文中試著繼續相關的分析。

了解電腦底層運作的原理,有助於找到問題所在
雖然說,現代的程式設計環境,已經包裝出一個十分高階的黑盒子,讓不是很了解電腦實際運作方式的程式人,只要懂得程式語言的語法,就可以輕易地寫出程式,而且在大多數情況之下,也不會遇到太大的麻煩。

但是,正如之前所提到的資料對齊(Data Alignment)問題,如果你不知道處理器存取主記憶體資料會有這樣子的特性,那遇到問題時,可能想破頭也想不出來。

當你使用的是十分高階的程式語言時,這種情況可能比較少見,一旦得使用像C/C++這類較不那麼高階的程式語言時,對於電腦底層運作的原理若有一定程度的了解,在遇到比較特殊的情境時,絕對有助於找到問題所在。

同樣的道理,作業系統是應用程式執行的環境。作業系統允許應用程式更輕易地存取各項硬體週邊,例如檔案系統、鍵盤輸入、滑鼠輸入等。作業系統也負責硬體資源的分配,例如在分時多工的作業系統上,作業系統必須透過排程機制來分配不同應用程式的處理器資源。

作業系統的運作行為,和應用程式的執行息息相關。如果你不明白作業系統分時多工的方式,那麼身為一名Windows程式人,你可能無法明白為什麼 呼叫Sleep(100);的動作,不會恰好停止執行100毫秒。你也就搞不懂,當你寫出一個具有忙碌迴圈(Busy Loop)的程式時,應用程式會盡全力地把處理器時間全部吃光(或者說,作業系統會盡可能讓應用程式占用處理器時間)。

缺乏對作業系統的認識,可能踏中陷阱而不自知
大多時候,程式語言、應用程式框架,以及程式庫,會把程式人保護得很好,使他們有如身處溫室,不知溫室外的寒暖。

但是,這一層防護罩有時也會有漏洞,此時,程式人就必須仰賴自己的力量。倘若程式人知道電腦硬體如何運作,也知道作業系統如何運作,便更有機會因應這些特性,避免奇怪的問題發生,同時也更有機會寫出有效率的程式碼。

舉個例子吧!我有滿多經驗,看到應用系統在單一目錄下塞滿了數萬個檔案,而應用系統的使用者,反映系統的速度越來越慢。應用系統的開發者在開發之 初,由於單一目錄下的檔案個數並不多,所以並沒有發現會有效能問題。但隨著系統上線使用,該目錄下的檔案個數越來越多,系統也越來越慢。有些應用系統的開 發者沒有找到系統變慢的根本原因,有些應用系統的開發者找到了,但並不明白為什麼單一目錄下置放如此多的檔案,系統效能就會變得如此之差。

倘若開發者對於作業系統中的「檔案系統」有一定的了解,就會明白不管是Windows早期的FAT類檔案系統,或者Unix基於inode結構的 檔案系統,存取效能都和單一目錄下的檔案數有關,檔案超過一定的個數後,數量越多,存取速度越慢(當然,在不同的檔案系統下,效能變差的趨勢會不同)。

倘若明白這樣的特性,就不會在應用系統中做出這樣子的設計,或者,即使做出這樣子的設計後,也能在問題浮現時,迅速地找到問題所在,並且改善設計。

上述只是一個簡單的例子,但說明了,當程式人僅從高階的角度來理解所寫下的程式碼,因為缺乏對作業系統行為的認識,有可能因此而踏中陷阱甚至不自知,這便是程式語言防護罩的漏洞。

程式語言以及編譯器也是基礎電腦科學的一環
或許你可以不懂作業系統,依然能在大多數時候撰寫程式,但有時你會遭遇到麻煩,而且更糟的是,你還不知道如何解決所碰到的麻煩。

除了作業系統之外,程式語言及編譯器也是基礎電腦科學的一環。程式語言並不同於程式設計,這門學問並不在探討特定程式語言的特性以及撰寫的技巧,而是一門關於程式語言的通論。

在這門通論裡,你會明白所有程式語言所共通以及相異的部分。你也會知道現代程式語言的大致分類(例如程序式程式語言、物件導向程式語言、函數式程式語言、邏輯程式語言……等),以及它們的特性、優缺點。

從某個角度來看,一名優秀的程式人,多半都能同時使用多種程式語言撰寫程式。了解程式語言的一般性理論,有助於對程式語言有一個更全面的認識,而 不會單從特定一種或數種程式語言來片面的理解。例如,我曾經讀過一些評論,這些文章認為所有的程式語言大同小異,像C++、Java、C#都很相像,學會 一種程式語言之後,便能夠輕易地學會其他種。

殊不知,這幾種常見的程式語言,本來就是血統十分相近的程式語言,也都屬於程序式及物件導向混合的程式語言。倘若有此評論者知道像函數式或邏輯式程式語言的存在,也就不會如此下斷語了。

學習語法容易,程式語言的思維模式才是難的地方
程式語言就像是一張能提供全貌的地圖,透過這張地圖的導引,你可以明白程式語言的歷史演進、程式語言的分類、每類程式語言的特性、優缺點、程式語言間的血統關係等。

了解這些事情之後,當你在學習特定的程式語言時,便能夠加快學習的速度,因為它就像總綱,講述了最主要的精神。以這份總綱為基礎,再了解各種程式語言的細節語法以及性質,便能更快速地掌握特定程式語言的運用。

就拿最近漸露頭角的Scala程式語言為例,它是綜合物件導向及函數式程式語言特性的程式語言,倘若你已經明白物件導向及函數式程式語言的特性,那麼只需要再針對Scala的語法,以及其中的物件導向、函數式性質深入了解,便能夠很快上手。

如果你對程式語言缺乏一般性的認識,你的思維模式很有可能只停留在程序式或物件導向式程式語言的模式。對你來說,函數式程式語言的那種模式,是之 前完全沒有想像過的,或許你熟悉Java,但你要進一步了解Scala,便會需要先打通函數式程式語言觀念的這個關節,才有可能讓自己進入到Scala的 核心地帶。

不過,學習一個程式語言的語法容易,學習一個程式語言的思維模式才是難的地方。像C++這樣子的物件導向程式語言,它剛開始流行的時候,可以看到 許多程式人在程式碼中大量地使用繼承、虛擬、多型等語法,卻不容易看到程式人把這幾個特性運用得巧妙,這是因為語法只是表面,語言的思維模式才是核心。

而程式語言如此具有一般性的總綱,則有助於我們站在高處,全面地理解各種類型程式語言思考、表達、解決問題的模式。這是這一門學問,對程式人來說之所以重要的原因。

沒有留言:

張貼留言