從 API、UI、結構到商業產品設計精髓

GitChat技術雜談發表於2017-11-21

本文來自作者 范蠡 在 GitChat 上分享「Windows 程式設計精髓:從 API、UI、結構到商業產品」,閱讀原文」檢視交流實錄

文末高能

更多同類話題

檢視全部話題

編輯 | 朝偉

當下,Android、Linux、Mac 等裝置也大行其道,PC 軟體似乎已經日薄西山。

然而,我們大多數人平常工作、學習、娛樂的環境都是Windows平臺,仍然在使用 PC 機器上各種軟體,即使從事 linux 開發的技術人員,也很多使用像 xshell/SecureCRT 這類支援 SSH 協議 pc 軟體遠端登入到 linux 機器上來操作,實際工作的平臺仍然是 Windows,使用的軟體仍然是pc軟體。

我接觸 Windows 開發有十多年了,先後擔任過像股票行情資訊系統、手機助手等多 款 PC 軟體的主程工作,也“客串”過 PC 端軟體的產品經理,對使用者使用 PC 端軟體的行為習慣和使用者心理有一定程度的瞭解。

本文 將 PC 軟體開發中涉及到的 Windows API 程式設計技術、介面庫、程式庫、框架結構設計以及商業 PC 產品設計思路等方面來分享我的經驗。

內容包括 Windows 軟體開發需要掌握的技術和產品理念,希望對從事 Windows 軟體工作的開發人員和產品人員有一定的幫助和啟示。

這裡說明一下,這篇文章討論的內容不是 Windows 程式的具體編碼細節,而是 Windows 平臺上從程式設計到產出一款商業軟體的方法和思想理念,當然這種思路也適合移動端等其他客戶端軟體。

一、Windows程式的特點

1. 嚴謹的介面設計

按作業系統的技術棧發展來看,相比較類unix作業系統比較短小精悍的命名風格,Windows 作業系統提供的函式介面以及各種函式引數的命名都是很清晰而已容易看懂的。

雖然古怪的匈牙利命名法(下文將介紹)讓 Windows 程式看起來有點“中世紀風格”,但這種命名方法增加了 Windows 程式的可讀性和可理解性,後來者也不斷模仿之。

首先,Windows 提供的函式名稱、結構體型別風格都非常統一,諸如CreateProcess、CreateThread、CreateMutex、CreateSemaphore等。

當然也有例外,比如堆建立函式 HeapCreate,這個據《The Old Things of Windows》(中文名《Windows程式設計啟示錄》)的作者Raymond Chen說,當時設計這個堆系列的介面函式的是微軟另外一個部門,所以風格出現了不一致- -!

擴充套件的函式和結構體在原有的基礎上使用 Ex,例如從 CreateWindow 到CreateWindowEx,RegisterClass 到 RegisterClassExWNDCLASS 到 WNDCLASSEX。

新的擴充套件的介面不僅相容舊的介面的功能,還增加了另外一些新功能新特性,如果您用不到新的功能和特性,仍然可以使用舊的介面函式。

Windows 在新舊系統相容性方面做的也非常優秀,即使在最新的 Windows 作業系統上使用很老的 Windows api 仍然沒什麼問題。

雖然很多api或者做法不推薦在新版系統中使用,但是你使用它們仍然不會有什麼大問題。

反觀,現在的一些作業系統比如 Android,低版本使用的API一個個被棄用,原來老的做法在新的系統上可能會導致程式直接crash掉。

再者,Windows 將大多數資源抽象成控制程式碼(HANDLE),例如socket、程式物件、執行緒物件、畫筆畫刷物件,甚至連像Windows服務這樣的東西也抽象成物件。

這種抽象帶來的好處就是可以用同一套邏輯去處理,比如操作一個物件必須先開啟或者建立,然後使用,使用完了之後然後關閉。當許可權不足時也不會因為越權而帶來安全隱患。

2. 匈牙利命名法

在駝峰式(例如myBestFriend)、帕斯卡(例如MyBestFriend)或者連字元式(例如my_best_friend)等諸多命名法當中,匈牙利命名法是Windows程式的一大特色。

雖然顯得很奇怪,但是帶來的便捷性和可讀性不得不提。匈牙利命名法是比爾蓋茲僱傭的第一代程式設計師查爾斯·西蒙尼發明的(Excel的主要開發者),這是一個傳奇性的人物。

匈牙利命名法的主要思想是給程式變數加上它的型別資訊,例如一個表示數值的整形變數,可以叫 nNum或 iNum,表示螢幕尺寸的整型變數可以叫 cxScreen、cyScreen,以 NULL 結束的字串指標叫pszStr(sz的意思是String terminated with Zero,以0結束的字串)。

當我們在程式碼中看到這樣的變數時我們無需檢視其型別定義。網上有很多論調說這種命名法已經過時。但筆者以為,這些觀點難免有點以偏概全。

在後來的很多系統設計上,很多地方可以看到匈牙利命名法的影子。這種命名法雖然看起來很拖沓,但是表達意思卻是非常清晰。

尤其是在閱讀別人的專案程式碼或者維護一些舊的專案時,能讀懂是維護的前提。

3. 訊息機制

之所以把Windows訊息機制單獨列出來是因為基本上可以認為它是以後所有的作業系統介面的模型的先驅,同時也是我們普通程式開發者應該學習和模仿的典範。

它本質上就是一個訊息佇列,Windows訊息佇列的實現可以參考開源版本的”Windows”——ReactOS。

ReactOS開發團隊立志要做一個與微軟 Windows 一模一樣的作業系統,這裡說的“一模一樣”不僅指的是 ReactOS 的介面和使用習慣與 Windows一模一樣。

甚至連提供的作業系統介面函式的名稱、簽名都必須一模一樣,而且參與開發的人員必須沒有閱讀過任何 Windows 原始碼哪怕是微軟洩露出來的程式碼也不行,如果發現這種情況,立馬開除,並且立即重寫被開除的人的所有程式碼。

所有關於 ReactOS 的實現都必須通過逆向 Windows 來獲得。所以ReactOS這個專案最大程度地模擬了 Windows,並可以免費開源。

回到正題上來,這裡要提一下的是,訊息佇列是軟體產品中非常常用的技術,所以如何設計出一個好的訊息佇列屬於開發者的基本功了。

Windows可以參考,現在流行的很多專門的訊息佇列框架(如RabbitMQ)都是不錯的學習資料。

4. 統一的使用者介面使用習慣

Windows 程式除了一些自繪的介面以外,大多數介面風格、選單位置、使用習慣等都是一致的,例如如果某個選單項後面有…(三個點),點選該選單項一般都會彈出一個對話方塊;

對於文字的編輯操作(例如複製、剪下、貼上)等一般統一放在”編輯”選單下面。

這也是 Windows 和linux的不同,Windows 的哲學是假設你不會操作,Windows教你如何操作;而linux是假設你會操作。

所以,廣大產品人員在設計UI的時候千萬不要違背這種微軟培養出來的多年使用者習慣,否則您的使用者很可能因為覺得您的產品操作非主流而放棄使用。

二、Windows下的介面庫與自繪技術

一些應用軟體為了追求一些特殊的介面效果,需要展現出不同於傳統的Windows程式介面的樣子(比如遊戲介面)。由於Windows作業系統提供了最大化的介面自繪介面,所以市面上出現了很多開源的或非開源的、收費的或非收費的介面庫。

核心思想其實就是呼叫Windows GDI或GDI+函式進行自繪,GDI提供的自繪介面在一些追求介面細節的精細程度上做的不夠且GDI介面都是C介面不符合現在開發軟體使用的物件導向模型的理念,所以後來微軟又專門推出來一套基於GDI的純物件導向的繪製介面GDI+(GDI Plus),更不用說專門用於圖形要求更高的領域的opengl、direct3D了。

比較著名的開源的介面庫像DUILIB,這個庫最先由一位德國人開發,後面中國的一些開發者接手,產生了種類繁多的分支。

微信和百度雲盤的pc客戶端都是基於DUILIB。收費的介面庫像迅雷的bolt。這裡不再列舉各種介面庫的名字了,無論哪種介面庫其核心技術都是自繪。

這裡不得不說一下這裡的DUI思想,做Windows介面開發,這是一種必須理解的介面繪製思想。

所謂DUI,即Directly Draw on Parent,即子控制元件物件直接繪製在父視窗上,也就是相當於只有父視窗一個視窗控制程式碼。

原來可能每個子控制元件都是視窗,windows訊息機制決定,視窗越多,視窗的訊息泵也就越多。

為了減少這些訊息泵,子視窗直接繪製在父視窗上,然後利用PtInRect這類API函式去檢測滑鼠是否位於這些繪製出來的控制元件上,然後利用PostMessage/SendMessage等API產生訊息,交給父視窗處理,以此模擬這些無視窗控制程式碼(hwndless)的控制元件可以響應訊息的效果。

衡量一個介面庫的優劣不僅要看這個介面庫的功能,也要看它的流暢性(效能)和使用者友好性程度。

騰訊QQ從2009版本開始,採用了這種思想,到今天的2017版本,其介面的設計是一個經典的範例,而2009版本也是QQ應用DUI思想,UI產生質的飛躍的一個轉折點。

當然個人覺得介面庫就該做好介面庫自己的工作,現在一些介面庫的作者因為一些利益的驅使,在其釋出的介面庫裡面包含了方方面面的功能,核心的介面功能不去優化,一些與介面有關的類物件,因為繼承鏈的關係,體積已經達到幾十k甚至更大,並號稱“旗艦版”。

這很容易對一些初學windows介面開發的新手造成誤導。介面是客戶端軟體的臉蛋,也是使用者體驗好與差的第一衡量標準,一個使用者體驗好的軟體介面是開發人員、產品人員和美工人員共同努力的結果。

三、Windows 上的程式庫

Windows上的程式庫最經典的當屬mfc(Microsoft Foundation Class)。網上有大量的言論說 mfc 已經過時,mfc 很臃腫。

這裡我有必要澄清一下,根據我個人的學習成長曆程來看,學習Windows程式設計正確的順序是先學習 Win32 API,然後學習 mfc 框架。

mfc 可能不是一個最好的框架,但一定是最好用的框架。當然學好mfc是一個先易後難再易的過程。

mfc 的很多設計理念和思想都是非常優秀的,比如訊息路由、C++物件的序列化與反序列化、動態建立、檢視/文件物件模型等等。

在後來者的各種軟體框架當中都能看到似曾相識的影子。從另一個角度來講,每個開發者可能都想成為程式架構師,而一般都是從學習模仿別人的框架開始,也就是說你的腦中應該有一些經典的框架設計。

那麼mfc可能是你學習成本最低、收穫最大的框架。君不見Qt為啥也要抽象出QtApplication這樣的物件?桃李不言,下自成蹊。

有人說mfc很臃腫,這點mfc真的很冤枉。mfc之所以臃腫是因為它是作為一個面面俱到功能型的程式框架,最大程度的去讓使用框架的人減少重複勞動並快速生成一套可以使用的軟體。

功能多了,生成的庫檔案也就相對來說大一點。當然在現今的磁碟容量、記憶體容量、網路頻寬條件下,mfc那幾兆的庫檔案其實已經微不足道了。

當然,如果你不需要mfc這種重量型的框架,你可以使用WTL。WTL是基於C++模版的,程式庫都是一些標頭檔案,嵌入到你的程式中進行編譯,本身沒有任何二進位制庫檔案。

WTL沒有mfc那樣的方方面面的功能,只是將一些與視窗(包括控制元件)相關的東西封裝起來(當然也包括一些常用的工具類)。

市面上有很多軟體都是基於 WTL 做的擴充套件,例如360安全衛士、金山衛士等等,我的開源即時通訊軟體 flamingo pc 客戶端也是基於WTL做的一套自繪介面庫。

近些年,隨著移動裝置安卓、IOS的流行,Mac機器和linux平臺也開始受到很多使用者的歡迎。

很多軟體開發商為了減少開發成本、縮短開發週期,一套程式可以同時執行在多個平臺上,Qt這樣的跨平臺框架流行起來。但是Qt這種龐然大物以及它的學習成本,筆者實在不敢恭維。

總結起來,不管哪種程式庫,一般適合自己的軟體專案才是最好的,沒有必要為了使用框架而使用框架。

在我帶隊的公司最近幾個pc端專案都是我仿照 mfc 的思想用 Win32 API 從底層開發的,沒有使用任何現成的框架。

鑑於此,廣大開發者或者公司決策人員,在做產品技術選型時,要綜合考慮多方面因素去選擇一款合適的程式框架。

四、PC 端軟體的組織結構、架構設計

關於PC端軟體的組織結構和框架設計,最核心的其實就是介面邏輯和資料處理,資料處理可能是一些複雜計算或者網路通訊。

最經典的也就是三層結構,即UI層、資料加工層和網路通訊層。

關於它們的具體細節,我在我的另外一篇文章《客戶端軟體的結構思考》中詳細地介紹了:。文中有具體的細節和具體的案例分析,有興趣的可以參考一下。

五、商業 PC 產品設計思路

這個話題如果展開來說,是一個非常大的話題。這裡我就具體而微的來說一下我的經驗。

一款成功的商業軟體,在開發之前要做可行性分析和競品分析。如果你的軟體目前市面還沒有,那麼你在決定開發之前要對它做可行性調研,諸如開發技術難度、開發週期、是否有市場需求、盈利點等等都應該是重要的考慮因素;

如果你的軟體目前市面上已經有了,那麼您需要做競品分析時,您要吸納采用同類軟體的優點,反思同類軟體的不足用於改進或者完善自己的產品。

我曾經帶隊開發過一款郵件採集與加工系統,使用者是某知名基金公司的研究員們,他們會將原創的各種金融研究報告彙總至指定郵箱。

這款軟體就去從該郵箱讀取這些郵件,並解析出來,然後生成對應格式的報告在金融平臺上展示,程式需要自動識別郵件的標題、發件人、分組、郵件主題等內容,還要自動處理有附件的郵件。

這款軟體的業務其實並不複雜,但是在海量資料的處理的效能上,以及自動處理和加工郵件的內容是一個重難點。

所以我在和產品人員溝通時,也會重點就這些方面的細節做好一一溝通落實,在開發人員的安排上也會往這些方面做一定的傾斜。

商業軟體的另外一個問題就是程式的釋出方式,這包括兩個方面:

1. 程式的發版問題

對於一些安裝體驗要求不是很高的軟體,目前像 NSIS 或者 InnoSetup 這樣現成的打包工具已經足夠用了,當然如果您需要獨特的安裝程式,您可能需要自己去開發。

安裝程式本質上是檢測軟體所在的執行環境、釋放程式檔案到指定位置以及寫入一些初始化資訊或配置資訊去登錄檔和配置檔案中。

2. 程式的自動升級問題

考慮到程式的bug修復和新功能的後續更新,大多數客戶端軟體都可以自動升級。

當然蘋果的App是行業內的一個奇葩。所以為了你後續的商業利益,自動升級這個功能一定是要特別重視的。

只要自動升級功能不出問題,無論您的軟體當前如何,您都有“補償”或者改進的機會。

商業軟體的另外一個需要注意的是,就是使用者體驗問題。良好的使用者體驗,能讓使用者對您的軟體產生依賴。

反觀一些軟體,一些常用的快捷鍵要麼沒有,要麼非常難記難用。這都是經典的反面教材。

限於筆者水平和經驗有限,文中難免有偏頗之處,歡迎提出批評指正意見。


近期熱文

TensorFlow 計算與智慧基礎

突破技術發展瓶頸、成功轉型的重要因素

Selenium 爬取評論資料,就是這麼簡單!

這種稀缺的測試人,好多公司都搶著要

Node 企業專案大規模實踐


GitChat 與 CSDN 聯合推出

《GitChat 達人課:AI 工程師職業指南》

「閱讀原文」看交流實錄,你想知道的都在這裡

相關文章