命令列介面設計

發表於2013-12-27

雖然已存在大量關於圖形使用者介面(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年代初期。在實踐中,這意味著你不該創造一個檔案管理程式,而應創造一個程式用於刪除檔案,另一個用於移動檔案,還有一個用於複製檔案。

在“只做一件事”的副作用中,你更需要關注“做好一件事”這一點。

相關文章