命令行界面设计

关键字: 编程语言生态

原文地址:《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

这两个选项你应该总是包含在你的程序中:--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年代初期。在实践中,这意味着你不该创造一个文件管理程序,而应创造一个程序用于删除文件,另一个用于移动文件,还有一个用于复制文件。

在“只做一件事”的副作用中,你更需要关注“做好一件事”这一点。

redraiment不可不->不得不
zzp-me命令行界面设计