雖然已存在大量關於圖形使用者介面(GUIs)設計的文章,可是介紹命令列介面(CLIs)設計的卻很少。本文嘗試介紹幾個關於CLI設計最重要的準則。
本文假設該命令列工具用於 *nix 系統(例如 GUN/Linux、BSD、Mac OS X,UNIX),並且會頻繁地參考這些系統中的常用工具。
命令列介面型別
命令列介面主要有三種:
- 非互動
- 基於行的互動
- 文字使用者介面
非互動式程式在呼叫後不再需要任何使用者干預。諸如 ls、mv 和 cp。
基於行的互動式程式在執行期間經常需要與使用者互動。它們會往標準輸出中寫入文字資訊,還可能會請求使用者通過標準輸入來輸入資訊。屬於這類的程式有 ed 和 metasploit。
文字使用者介面介於 GUI 和 CLI 之間。它們在終端模擬器裡執行了一個圖形使用者介面。例如 nethack 和 vi。許多(但非全部)在 ×nix 上的文字使用者介面都是使用 curses 或較新的 ncurses。
本文重點關注非互動式程式,而文字使用者介面幾乎沒有涉及。
命令列介面的優勢
都 21 世紀了,為什麼還用命令列介面?圖形使用者介面早在十幾年前就發明了!
時至今日,許多命令列介面仍擁有幾個勝過圖形使用者介面的優勢。它們在超級使用者、程式設計師以及系統管理員中間很流行;部分原因是許多優勢很適合他們的品味:
- 易於自動化:使用指令碼,很多命令列程式都能輕鬆實現自動化;
- 快速地啟動:許多命令列程式多次在啟動時間上擊敗它們同類的 GUI 程式;
- 易於遠端呼叫:也許只是我而已,但我更喜歡通過 SSH 或 VNC 遠端控制計算機;
- 對系統要求較低:這使得 CLI 在嵌入式系統中更有用;
- 更高的效率:只需鍵入一些字元就能做很多事情,而不必在選單中搜尋,提高你的工作效率;
- 對鍵盤友好:抓著滑鼠容易分心。
命令列介面的劣勢
已經羅列了命令列介面的優勢,最好也給出它們的劣勢。最主要的缺點是學習曲線比較陡峭,很多情況下你不得不去翻手冊;而使用 GUI 產品時你能自己估計出很多東西。
在顯示和編輯圖形化資訊時 GUIs 也有優勢。包括照片處理和看電影(我總希望有個程式能將電影實時地轉換成 ASCII 字元圖片並在我的終端裡,這會非常地酷)。
避免使用互動
相較於非互動式使用者介面,互動式介面更難自動化。易於自動化是命令列介面最大的優點,如果讓你的工具採用互動式介面,就會失去這個優點。
個別情況下互動式工具會比非互動式更合理,但至少不要在這個優勢不明顯的時候這樣做。你的工具不應該要求使用者(互動式地)輸入那些很容易以引數形式傳遞給程式的東西。
命名你的工具
我想要強調給每個命令列工具取一個好名字的重要性。因為一個壞的名字很容易被忘記,意味著使用者將不可不花更多的時間去查尋。
名字要短。長的名字不方便輸入,所以別管你的版本控制程式叫“my-aswsome-version-control-program”。給它取個短一些的名字,例如 avc(Awesome Version Control)。
名字還要容易記。別取 ytzxzy 這樣的名字。
引數
對於引數有很多可以說。首先,按照標準習慣,單字母選項用一個連字號做字首,並且可以直接跟隨多個(比如 -la 和 -l -a 是一個意思)。多字母選項由兩個連字號做字首,並寫每個引數之間必須用空格隔開。參看 ls 或 cp 的引數,遵循它們的工作方式。dd 沒有遵循標準,因此常遭人詬病。
繼續標準習慣的主題,如果有一個與你的程式功能類似的工具(或者是同一分類的工具,例如都屬於檔案管理)用一些選項來做某些事情,將它的行為複製到 你的程式中會是一個不錯的主意。看看大多數 *nix 檔案管理工具,例如 mv、cp 和 rm,它們都提供了 -i 選項,並提供相同的行為:要求使用者確認操作。它們同樣都提供了 -f 選項來強制執行(這讓計算機開啟來很蠢,不過你在使用選項的時候知道自己在做什麼,不是嗎?)。
顧名思義,選項(options)應該是可選的(optional)。但它有時會被人遺忘。命令列工具應該允許不帶任何引數就可執行。比如 cd,沒有引數時返回到自己的家目錄。有些程式沒有引數的話可能沒有意義,比如 mv,但大多數情況,你都能找到有意義的標準的行為(不過請記住,只單單輸出錯誤資訊並退出也比做些使用者不期望發生的傻事要好(哦,你沒有給 rm 任何選項,那最好刪除c磁碟上所有的檔案,以保證你要刪除的檔案會被刪掉))。
在 *nix 世界裡有個習慣:任何在雙連字號之後的東西都將被看成檔名,即使名字中包含了連字號(比如 cmd — -FILE-)。如果引數列表以單個連字號結尾,就從標準輸入中讀取。
要小心使用那些只是大小寫不同的標記(比如 -R 和 -r),它們很難記。
總是提供與短引數相應的長引數。不要只提供 -i,也要一起提供 –interactive。
提供 –version 和 –help
這兩個選項你應該總是包含在你的程式中:–version 和 –help。第一個選項輸出程式的版本資訊;第二個介紹這是一個什麼程式,如何使用以及目前常用的——如果不是所有——選項。
讀取輸入
確保你的程式可以從管道或通過檔案重定向中讀取資料。
如果檔名作為引數傳遞給程式,就讀取檔案的內容作為輸入。如果沒有提供這樣的引數,就從標準輸入中讀取,一直到 CTRL+D。
此時無聲勝有聲
如果程式沒什麼重要的事情要說,就保持安靜(人也適用)。當我執行 mv 時,我不希望它告訴我它已將一個檔案移到另一個地方去了。畢竟,這不正是我讓它做的事情麼?這對我來說是確信無疑的,所以不需要顯式地告訴我。當那些並不 期望發生的事情發生了,才應該打破沉默。例如我想移動的檔案不存在,或者我在目標目錄下沒有寫的許可權。
要注意,你的程式不需要在每次呼叫的時候都輸出它的版本號、版權資訊,或作者的名字。這些只是額外的噪音,浪費空間,使用遠端會話時浪費頻寬,還可能導致輸出很難被自動處理,比如將它們通過管道轉發給其他程式。
同樣的,也不要強調這些輸出是什麼。使用者應該知道自己在用什麼程式。whoami 僅僅輸出當前使用者的名字。如果輸出“The name of the current user is: x”,那單純提取名字就會更費功夫。
很多程式提供 -v(verbose)選項讓程式變得更囉嗦;還有一個 -q(quiet)選項讓程式閉嘴(可能除了一些致命錯誤)。預設行為不應是完全沉寂,而是大多數情況下保持沉默。程式只在適當的時候輸出一些東西。
如果讓使用者輸入 yes 或 no
有時,你的程式可能出於不同的原因需要詢問 yes 或 no。最常見的是要求使用者確認(do you really want to do this?);或者可能是計算機試著提供問題的解決方法(Table USERS doesn’t exist, do you want me to create it for you?)。
當問題的答案要麼是 yes 或是 no(或者 y 和 n),你應該給問題後面給出(y/n):
- Do you really want to do this (y/n)?
多數程式要求你在鍵入字母后手工敲回車。雖然這顯得多餘,但大多數程式都這麼做,為了保持一致,讓使用者不要感到驚訝,你的程式也應該要求使用者這樣做。
告訴我你想要什麼樣的輸入
如果你的程式請求輸入一個日期,但又不告訴我該怎麼輸入,我就會很困惑:
- Enter a date:
能提示我要輸入日期的格式,就不會造成困擾了:
- Enter a date (YYYY-MM-DD):
同樣的,如果程式只是要求輸入一個長度,我就不曉得它會是千米、米、英里、英尺……?當一個東西有不同的單位時,就該把單位告訴我。
每個程式只做一件事情,並把它做好
這是 UNIX 哲學中最重要部分的其中一條,並經歷過時間的考驗。作為一條很好的建議,它的歷史可以追溯到上世紀60年代後期或70年代初期。在實踐中,這意味著你不該創造一個檔案管理程式,而應創造一個程式用於刪除檔案,另一個用於移動檔案,還有一個用於複製檔案。
在“只做一件事”的副作用中,你更需要關注“做好一件事”這一點。