《designing command-line interfaces》
雖然已存在大量關于圖形使用者界面(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。第一個選項輸出程式的版本資訊;第二個介紹這是一個什麼程式,如何使用以及目前常用的——如果不是所有——選項。
確定你的程式可以從管道或通過檔案重定向中讀取資料。
如果檔案名作為參數傳遞給程式,就讀取檔案的内容作為輸入。如果沒有提供這樣的參數,就從标準輸入中讀取,一直到 ctrl+d。
如果程式沒什麼重要的事情要說,就保持安靜(人也适用)。當我執行 mv 時,我不希望它告訴我它已将一個檔案移到另一個地方去了。畢竟,這不正是我讓它做的事情麼?這對我來說是确信無疑的,是以不需要顯式地告訴我。當那些并不期望發生的事情發生了,才應該打破沉默。例如我想移動的檔案不存在,或者我在目标目錄下沒有寫的權限。
要注意,你的程式不需要在每次調用的時候都輸出它的版本号、版權資訊,或作者的名字。這些隻是額外的噪音,浪費空間,使用遠端會話時浪費帶寬,還可能導緻輸出很難被自動處理,比如将它們通過管道轉發給其他程式。
同樣的,也不要強調這些輸出是什麼。使用者應該知道自己在用什麼程式。whoami 僅僅輸出目前使用者的名字。如果輸出“the name of the current user is: x”,那單純提取名字就會更費功夫。
很多程式提供 -v(verbose)選項讓程式變得更啰嗦;還有一個 -q(quiet)選項讓程式閉嘴(可能除了一些緻命錯誤)。預設行為不應是完全沉寂,而是大多數情況下保持沉默。程式隻在适當的時候輸出一些東西。
有時,你的程式可能出于不同的原因需要詢問 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年代初期。在實踐中,這意味着你不該創造一個檔案管理程式,而應創造一個程式用于删除檔案,另一個用于移動檔案,還有一個用于複制檔案。
在“隻做一件事”的副作用中,你更需要關注“做好一件事”這一點。