1. 程式人生 > >一點小感受:介面和程式的分離

一點小感受:介面和程式的分離

1 Windows桌面程式,介面和程式是原始碼級混合

Windows系統下的GUI程式,介面(GUI)與程式其他部分邏輯上是分離的,但是原始碼上直接互動,介面功能直接通過呼叫Win32 API來實現。

例:CreateWindow()。
寫Windows桌面程式,必須呼叫GUI32.dll匯出的API,無他可選。

甚至執行緒模型很多功能都和GUI視窗繫結到了一起,如訊息佇列。

2 Linux程式,介面和程式是通過協議通訊

2.1 CUI程式和文字終端通過終端協議互動

對於CUI的程式來說,文字終端是通過標準的終端協議(行行程協議)來提供介面功能的。文字終端和主機完全可以執行在不同架構的機器上,只要彼此都遵守同樣的終端通訊協議,程式和終端就能完美互動,而不受通訊媒介的限制。

正因為如此,才使得SSH等遠端終端等方便的遠端連線方式很容易被理解和實現。

這種徹底的分離,帶來了設計上的完美感。

讓每一個程式設計師都去了解使用終端協議是非常費時(個人認為非常有意義)的事情,而且更可怕的是終端協議並不是只有一個,各終端裝置廠家有自己的協議擴充套件,如VT100。

為了便於使用,人們開發了封裝終端協議的函式庫。最基本的就是C標準函式庫裡的printf(),scanf()了。功能更強大的就是著名的curses庫了。當我們編寫Linux程式使用這些庫函式的時候,最好能想到其底下支撐它的終端協議。

2.2 GUI程式和XWindow Server通過X協議互動

與文字終端的概念一脈相承,XWindow提供了圖形終端的功能。程式通過標準的X協議與圖形終端XWindow Server互動。

圖形終端的功能要比文字終端強大的多,也複雜很多,其通訊資料量更是大幅增加。這些都導致了X協議的複雜性。所以直接通過X協議來呼叫GUI功能,顯然過於繁瑣。於是,人們開發出了封裝X協議的XLib庫,為了更加簡單的使用,基於XLib庫有開發出了各種高階封裝庫,如GTK,Qt等。

當我們使用這些庫函式的時候,別忘了其底層最終是使用X協議與圖形終端進行了通訊。

2.3 直接操作的顯示卡不是終端

Linux支援直接操作顯示卡裝置,特別是對framebuffer的支援使得直接讀寫顯示卡非常方便。然而這樣的讀寫與介面的操作是兩個完全不同的概念。Linux程式的介面就是終端,至於終端如何利用顯示卡那是終端的具體實現,對Linux程式不可見。就算是最簡單的printf(),Linux程式也是寫到終端上去,而不是直接寫到顯示卡上。對於本地終端來說,終端和程式運行於同一臺機器上,很容易讓人混淆終端和顯示卡裝置。要記住,本地終端只是終端中特殊的一種,理解終端概念的時候,最好想象遠端終端的情形。

3 Web程式,介面(HTML)和後端程式通過標準HTTP協議進行通訊

雖然Web程式也是圖形介面程式,但是其後端程式對介面的控制粒度很大,而且程式不能主動發起到介面的通訊,這些限制導致HTTP協議非常簡單,通訊資料量也很小。

越簡單的事情往往越容易取得成功,Web程式最終取得了輝煌,成為了程式模型的主流,越來越多的桌面程式被同功能的Web版本程式取代。

當然了,由於Web後端程式對介面的操作功能有限,所以大量的圖形影象程式不會被Web取代。

4 分離還是混合?

介面和程式邏輯是分離好,還是混合好?邏輯上,介面功能算是一個非常成熟獨立的模組,從模組化設計的角度來說,分離是最完美的選擇。然而,對於圖形密集型程式和頻繁互動的程式(比如Photoshop,3D Max)來說,介面功能佔據了程式邏輯的大部分,此時互動的流暢性就成為關鍵。介面分離的程式互動效率必然受到影響,所以Windows和Mac的圖形介面互動流暢度要大大高於XWindow。

然而畢竟圖形密集和互動密集型程式只佔據軟體市場的很小一部分,對於廣大的其他型別程式來說,介面的分離無疑會帶來設計上的美感和簡潔,執行上的穩定。看看大多數的伺服器、嵌入式裝置吧。

再者,硬體技術的提升往往比軟體設計的改良更加容易,所以隨著硬體水平的提高,介面的分離必將是最終的勝利者。

5 協議還是API?

程式不同模組的互動方式按照耦合程度由高到底可以分為:(1)原始碼級別混合;(2)API函式;(3)協議。

原始碼級別混合指的是彼此暴露資料結構實現細節,除非是非常簡單的程式,否則這種設計基本是不合適的;

API函式級別,指的是把一個模組當成庫來設計,對外之暴露有限的函式,使用透明資料結構指標作為函式引數,所有模組必須執行與同一個機器,同一個程序。

協議級別,指的是對外暴露通訊標準,模組間通過標準的協議來互動。此時,不同模組可以運行於不同機器。

在(2)和(3)之間還有一個多程序程式設計的方式,各個模組被當作獨立的程序來執行,模組之間通過本機IPC進行通訊。

程式設計時,要根據程式的規模,具體的業務邏輯、擴充套件需求來確定模組間互動的方式。