如何理解《Unix 編程藝術》中所說,「提供機制,而不是策略」?
另外,更進一步的問題是:如何知道提供哪種機制,提供到什麼程度呢?比如一個介面,需要給外部暴露的東西,有哪些?到哪一步就足夠了?
最好能有具體項目,實例一次講解吧.
0. 管道是機制,應用管道處理各種數據是策略;
1. AWK的讀入行循環是機制,各種正則式與後附的處理操作是策略;2. 輸入法是機制,碼錶是策略;3. 樂高積木的凸點與凹槽是機制,各種拼接方式是策略;
……等等等等。機制是泥坯,策略是可以定製的各種細節。更抽象一點,機制是介面,策略是數據流。它的意思是說多抽象出一些適用性廣的規則來,這樣當具體情況有變時不用重新改規則。我認為理解成這樣就差不多了。不用去深究具體怎樣才算機制怎樣才算策略,一個機制被具體化到怎樣的程度就成了策略之類的。就跟「做一件事並做好」一樣,不要去深究到底怎樣才算「一件事」。
我覺得書里的說法就是系統要留有充分的可配置性,不要替用戶自作主張(水果中槍)
微軟的Group Policy配置系統這點倒是很符合書上的說法要理解「提供機制,而不是策略」關鍵要理解什麼是機制,什麼是策略。
我們從軟體開發的角度來思考。
機制,可以理解為實現某個功能需要的原語操作和結構;策略,可以理解為某個功能的直接實現。
「提供機制,而不是策略」意味著我們應該提供實現某個功能需要的原語操作,而不是直接去實現這個功能。這樣的好處是,這個「機制」的用戶可以根據自己的需要去定製這個「機制」的表現形式,即自己的「策略」,並且我們很容易去更換一個「策略」,而不用修改「機制」。
如果用OOP的思想來說的話,可以理解為多態。具體來說,Linux內核的虛擬文件系統(VFS),提供了文件系統需要的原語操作(open, close, read, wirte, mount...)和結構(superblock, vnode...),基於虛擬文件系統這個「機制」之上,提供了ext2, ext3, ext4, btrfs等「策略」。這樣的好處是我們可以根據需要選擇不同的文件系統,不同文件系統的更新換代並不會影響「機制」之上的結構。另外我們也可以在不了解文件系統實現的情況下使用虛擬文件系統提供的原語操作來完成我們想要的功能。
另外一個例子,Linux內核的調度器(scheduler),提供了任務調度需要的原語操作和結構,並且實現了多種調度演算法。
最後一個例子,POSIX標準,不解釋。
我們可以從優秀的開源項目身上見證到這些Unix哲學是如何被用於實踐的,但是並不是explicit的,而是implicit的,在代碼結構中體現出來的,它的可能以我們更熟悉的方式體現出來(比如OOP的繼承,多態.....)。
至於「機制」要做到哪一步,就是需要提供足夠的原語操作和結構信息,這就需要有足夠的經驗和眼光,以及不斷的實踐......我想額外提供一個視角:可以參考 Linux 的動態鏈接機制。
它為它所推薦的動態鏈接方式提供了機制(/etc/ld.so.conf配置文件和ld.so文件),但是具體怎麼實施動態鏈接由程序自己決定。Windows也是一個明顯的機制與策略分離的系統:內核分為微內核與執行體2層,由微內核提供機制,執行體提供策略。
就Windows詳細講解一下吧。比如我們要創建一個進程,那具體分配基本的頁表(也就是建立一個內存空間)這樣的任務就由微內核實現。但是進程有哪些模塊,進程的父子關係、進程有哪些啟動參數,這些就由執行體負責維護。也就是說,機制只提供最基礎的東西,策略的話在版本更新時變化更頻繁一些。這是Windows的情況。以上可能會有我記錯的或者來源就錯了的情況,請各位多指教。一個例子是 fork/exec 和 CreateProcess。前者是 Unix 創建進程的函數,後者是 Windows 的。
fork 為什麼要和 exec 分離?因為創建進程,並不意味著一定要從文件系統中調入一個 executable。而 Windows 顯然沒有意識到這一點。這就是 enforce policy。
另一個例子是虛擬內存管理。Page-fault 是機制,而何時 page-fault,swap in/out 哪些 page 是 policy。在 OS X 中,負責 policy 的部分是可以放到 user-space 的。
但是,機制和策略的界限並不是靜止的。所以,Unix 還有另一個編程藝術:模塊應該是可替換的。比如當年高度考慮策略靈活的 X,在今天的環境下(遠程登陸已經被 VNC 等基於 pixel 的協議代替,顯卡的加速能力提高)已經不適用。所以 X 被策略更少但是效率更高的模塊替代。這真的是一個很難回答的問題呀。我嘗試一下吧。
這和unix的設計哲學有著莫大的關係,很多早期的unix程序員都是系統程序員,長期和底層系統打交道,所以他們對於系統的穩定性尤為的看重,那麼怎麼寫程序才能算是穩定的呢?在unix的程序員們看來,首先應該是儘可能的小,一個程序儘可能的做一件事情,只有這樣程序犯錯的概率才會變小,最後組合起來的系統才會足夠穩定,它們親切的稱為--KISS原則。這個時候你會驚奇的發現,如果程序真的足夠小且開放出來的話,它們就會就會提供一種機制讓你去完成你想讓計算機完成的任務,而不是變成完成某一樣任務所提供的一種必須策略。
好啦,按照我的理解寫完了,我知道有些晦澀,回頭有時間我在來改改。「機制」 回答的是 what,「策略」 回答的是 how。暴露給外部的是 what,具體的實現是 how。
機制就像是編程語言中提供的原生功能,策略則像是一個第三方的庫。一門語言提供的功能是有限的,不同的庫利用不同的抽象手段,按照不同的策略來組裝這些原始的功能,得到不同的結果。或者說,機制屬於實現,策略屬於設計。
拿人來比喻,機制是肉體,策略是靈魂。
///////////風騷的分割線///////////
看了一下(包括其他地方)要不就是沒有說到點子上,要不就是說的很複雜,其實大道至簡。搜了一下還看到這句話,本來不想多說啥,沒想到看一下作者居然是相關的教育工作者,心好涼。大部分的編程問題都可以被切割成兩個部分:「需要提供什麼功能」(機制)和「怎樣實現這些功能」(策略)。
「調用介面給你了,怎麼造輪子是你的事,造不出輪子也是你水平不夠」 我是這麼理解的
機制是流程,而策略則是流程中各節點的處理方法,但如何處理節點並不影響流程,帶來的好處大概就是將變化的東西延後處理,提供靈活性。
機制是提供做什麼的方法,策略就是利用這些方法來實現具體的實例;
1. Unix提供各種系統調用就是機制,而通過這些系統調用可以實現各種shell就是策略;
2. X window也是機制的實現,而Kde,xfce等各種桌面就是策略;
機制是可以長存的,而策略會隨著時間的推移和用戶喜好而變化;這也是Unix長久不衰的原因。
個人理解機制:我們是餐廳,可以讓你吃飽肚子策略:你是要吃拉麵、米線、還是雞翅呢
試著用發燒看病的例子來說明一下。
機制是what一個人發燒去看病,醫生開藥,葯就是「what」。當然這麼講過於簡單了,一個略微詳細一點的描述可能是這樣的:一天三次,飯後服用,每次5mg,服用一個療程可減輕發燒癥狀,另外可能有頭暈嘔吐副作用,等等。簡而言之,「機制」定義了what is the expected behavior。策略是how
青黴素,羅紅霉素,……這些都可以實現機制裡面描述的效果,但是具體的實現方式(化學式,製藥流程等等)是不一樣的。所以,「策略」是how is the behavior implemented。具體到Linux裡面,一個很好例子是Richard提到的VFS。比如VFS要求具體的文件系統必須實現inode_operations.lookup,然後又用了大量代碼來定義這個lookup究竟有什麼效果(也就是如何被kernel其他部分使用的)。至於lookup是如何實現這些效果的,就交給不同的文件系統自己來搞定了。1、如果只把evernote當做一個文本記事本來用的話,就是機制策略一把抓2、可以換成:dropbox作為機制,具體todo.txt用jedit還是用sublime處理是策略
推薦閱讀:
※fish比zsh好用嗎?
※什麼環境最適合學習 UNIX ?
※為什麼提到OS X優勢和Windows劣勢的時候都要大說特說Unix血統?
※如何評價王垠的文章《unix的缺陷》?
※如何Linux入門?
TAG:編程 | Unix | UNIX編程藝術書籍 |