Unix程式設計藝術,Unix哲學

發表於2011-08-22

注:轉載自 leezhong 的部落格

UNIX程式設計藝術》主要介紹了Unix系統領域中的設計和開發哲學、思想文化體系、原則與經驗。此文大致摘錄了Unix的哲學。

web開發人員也應該看看此書,軟體開發和web開發很多地方都是相通的。看完之後,我甚至覺得Unix哲學對於做人也有很大的參考價值。

模組原則 (使用簡潔的介面拼合簡單的部件)

計算機程式設計的本質就是控制複雜度

要編寫複雜軟體而又不至於一敗塗地的唯一方法就是降低其整體複雜度——用清晰的介面把若干簡單的模組組合成一個複雜的軟體。如此一來,多數問題只會侷限於某個區域性,那麼就還有希望對區域性進行改進而不至牽動全身。

清晰原則 (清晰勝於技巧)

維護成本是高昂的,在寫程式時,要想到你不是寫給執行程式碼的計算機看的,而是給人——將來閱讀維護原始碼的人,包括你自己看的。

在Unix傳統中,這個建議不僅意味著程式碼註釋。良好的Unix實踐同樣信奉在選擇演算法和實現時就應該考慮到將來的可擴充套件性。為了取得程式一丁點效能的提升就大幅增加技術的複雜性和晦澀性,這個買賣做不得——這不僅僅是因為複雜的程式碼容易滋生bug,也因為它會使日後的閱讀和維護工作更加艱難。

組合原則 (設計時考慮拼接組合)

如果程式彼此之間不能有效通訊,那麼軟體就難免會陷入複雜度的泥淖。

在輸入方面,Unix傳統極力提倡採用簡單、文字化、面向流、裝置無關的格式。在經典的Unix下,多數程式都儘可能採用簡單過濾器的形式,即將一個簡單的文字輸入流處理為一個簡單的文字流輸出。

Unix程式設計師偏愛這種做法並不是因為它們仇視檢視介面,而是因為如果程式不採用簡單的文字輸入輸出流,它們就極難銜接。

要想讓程式具有組合性,就要使程式彼此獨立。在文字流這一端的程式應該儘可能不要考慮到文字流另一端的程式。

分離原則 (策略同機制分離,介面同引擎分離)

把策略同機制揉成一團有兩個負面影響:一來會使策略變得死板,難以適應使用者需求的改變,二來也意味著任何策略的改變都可能會動搖機制。

可以將應用程式分成可以協作的前端和後端程式,通過socket專用應用協議進行通訊。這種雙端設計方法大大降低了整體複雜度,bug有望減少。

簡潔原則 (設計要簡潔,複雜度能低就低)

來自多方面的壓力常常會讓程式變得複雜(bug更多),其中一種壓力就是來自技術上的虛榮心理。Unix程式設計師相互比的是誰能夠做到”簡潔而漂亮”並以此為榮。

更為常見的是,過度的複雜性往往來自於專案的需求,要避免這種狀況,就需要鼓勵一種軟體文化,以簡潔為美,人人對龐大複雜的東西群起而攻之。

吝嗇原則 (除非確無它法,不要編寫龐大的程式)

“大”有兩重含義:體積大,複雜程度高。程式大了,維護起來就困難。由於人們對花費了大量精力才做出來的東西難以割捨,結果導致在龐大的程式中把投資浪費的註定要失敗或者並非最佳的方案上。

透明原則 (設計要可見,以便審查和除錯)

軟體系統的透明性是指你一眼就能夠看出軟體是在做什麼以及怎樣做的。顯示性是指程式帶有監視和顯示內部狀態的功能。

設計時如果充分考慮到這些要求會給整個專案全過程都帶來好處。至少,除錯選項的設定應該儘量不要在事後,而應該在設計之初便考慮進去。這是考慮到程式不但應該能夠展示其正確性,也應該能夠把原開發者解決問題的思維模型告訴後來者。

程式如果要展示其正確性,應該使用足夠簡單的輸入輸出格式,這樣才能保證很容易地檢驗有效輸入和正確輸出之間的關係是否正確。

出於充分考慮透明性和顯見性的目的,還應該提倡介面簡潔,以方便其他程式對它進行操作。

健壯原則 (健壯源於透明與簡潔)

軟體的健壯性指軟體不僅能在正常情況下執行良好,而且在超出設計者設想的意外條件下也能夠執行良好。

大多數軟體禁不起磕碰,毛病很多,就是因為過於複雜,很難通盤考慮。如果不能夠正確理解一個程式的邏輯,就不能確信其是否正確,也就不能在出錯時修復它。

這也就帶來了讓程式健壯的方法,就是讓程式的內部邏輯更易於理解。要做到這一點主要有兩種方法:透明化和簡潔化。

上面曾說過,軟體的透明性就是指一眼就能夠看出是怎麼回事,即人們不需要絞盡腦汁就能夠推斷出所有可能的情況,那麼這個程式就是簡潔的。程式越簡潔,越透明,也就越健壯。

表示原則 (把知識代入資料以求邏輯質樸而健壯)

資料要比程式邏輯更容易駕馭。所以如果要在複雜資料和複雜程式碼中選擇一個,寧願選擇前者。更進一步:在設計中,應該主動將程式碼的複雜度轉移到資料中去。

通俗原則 (介面避免標新立異)

最易用的程式就是使用者需要學習新東西最少的程式,換句話說最易用的程式就是最切合使用者已有知識的程式。

緘默原則 (無話可說?那就沉默)

行為良好的程式應該默默工作,絕不嘮嘮叨叨,礙手礙腳。沉默是金。

簡潔是Unix程式的核心風格。一旦程式的輸出成為另一個程式的輸入,就要很容易把需要的資料挑出來。站在人的角度上來說,重要的資訊不應該混雜在冗長的程式內部行為資訊中。

補救原則 (出現異常時,馬上退出並給出足夠錯誤資訊)

軟體在發生錯誤時也應該與在正常操作的情況下一樣,有透明的邏輯。最理想的情況當然是軟體能夠適應和應付非正常操作;而如果補救措施明明沒有成功,卻悄無聲息地埋下崩潰的隱患,這就是最壞的情況了。

寬容地收,謹慎地發。就算輸入的資料很不規範,一個設計良好的程式也會盡量領會其中的意義,以儘量與別的程式協作。然後要麼丟擲異常,要麼為工作鏈的下一環程式輸出一個嚴謹乾淨正確的資料。

經濟原則 (寧花機器一分,不花程式設計師一秒)

隨著技術的發展,開發公司和大多數使用者都能得到廉價的機器,所以這一準則的合理性就顯然不用多說了。

如果我們在軟體開發中嚴格遵循這條原則的話,大多數的應用場合應該使用高階語言,如Perl,Python,Java,Php,甚至Shell——這些語言可以將程式設計師從自行管理記憶體的負擔中釋放出來。

生成原則 (避免手工hack,儘量編寫程式去生成程式)

人類很不善於幹辛苦的細節工作。因此程式中任何手工hacking都是滋生錯誤和延誤的溫床。程式規格越簡單越抽象,設計者就越容易做對。

優化原則 (過早優化是萬惡之源)

還不知道瓶頸所在就匆忙進行優化,這可能是唯一一個比亂加功能更加損害設計的錯誤。從畸形的程式碼到雜亂無章的資料佈局,犧牲透明性和簡潔性而片面追求速度、記憶體或者磁碟使用的後果隨處可見。

先製作原型,再精雕細琢。優化之前先確保能用。”極限程式設計”宗師Kent Beck從另一種不同的文化將這點有效地擴充套件為:先求執行,再求正確,最後求快。

藉助原型化找出哪些功能不必實現,有助於對效能進行優化;那些不用寫的程式碼顯然無須優化。

多樣原則 (絕不相信所謂”不二法門”的斷言)

Unix傳統有一點很好,即從不相信任何所謂的”不二法門”。Unix奉行的是廣泛採用多種語言、開放的可擴充套件系統和使用者定製機制。

擴充套件原則 (設計著眼未來,未來總比預想來得快)

要為資料格式和程式碼留下擴充套件的空間,否則就會發現自己常常被原先不明智選擇捆住了手腳,因為你無法既要改變它們又要維持對原來的相容性。

設計協議或是文字格式時,應使其具有充分的自描述性以便可以擴充套件。要麼包含進一個版本號,要麼採用獨立、自描述的語句、按照可以隨時插入新的而不會搞亂格式讀取程式碼的方法組織格式。

Unix哲學一言以蔽之

 

相關文章