Random Thoughts

Recent content on Random Thoughts

马上订阅 Random Thoughts RSS 更新: https://blog.joway.io/index.xml

命令行里的设计艺术

2019年1月11日 08:00

在谈论手机 App 或是网页时,我们总会谈到交互设计,但倘若涉及到面向专业用户的 CLI(Command-line interface)领域,很少有人会将它与用户交互相联系。甚至在很多人的大脑里,已经把 CLI 和「难用」画上了等号,更有甚者认为 CLI 的难用才体现了其 「专业性」。

与此同时,「RTFM」(Read The Fucking Manual) 作为一个梗在工程师群体广泛流传,也让许多作者对于其不好用的 CLI 有了一个天然的借口。

虽然我们都知道阅读文档是一个好习惯,但恐怕大部分人在用一个新命令前都不会去仔细阅读完它的文档手册,就算你今天读了,你不可能永远记得,也不可能每次记忆模凌两可的时候都去重读一遍。所以可想而知一个高度依赖文档用户才能够正常使用的 CLI 不是一个合格的 CLI。

以下是我对于命令行设计的一些个人观点与观察,所涉并不一定广泛和正确,仅作为抛砖引玉,也欢迎在评论里提出你的看法。

遵循约定俗成

例如 mv, cp, ln 这些命令都遵循 [action] [source_file] [target_file] 的格式,这不一定很有逻辑,但既然都已经约定俗成了,如果你违犯这个顺序要倒过来,其实是一件蛮缺德的事情。为什么说「缺德」?因为一个用过了你的命令的人,他很容易开始怀疑是不是还有别的命令行打破了这个约定,他会对其它命令也不放心,最后他甚至会忘了真正被广泛采用的约定用法是什么了,导致每次用类似语法的命令都胆颤心惊,这点我深有体会 😔。

所以如果你的命令有类似的约定俗成可以遵守,你应该遵守业内的这种约定,这是一种职业道德。

一致的命令组织结构

对所有和用户打交道的产品来说,「一致性」是天条。我遇到过两种被广泛采用的组织风格:

$ [cmd] [module] [flags] [args]

$ [cmd] [action] [flags] [args]

无论是按模块划分还是按行为划分本质思路其实都是一样的,有些人会认为项目大了会难以遵守这套规范,但即便是目前规模已经非常庞大的 kubectl,它依旧坚持以 [cmd] [action] [flags] [args] 为基础的设计准则。在有些较为复杂的地方,它可以用 subcmd 来进一步向外部隐藏复杂性 [cmd] [subcmd] [action] [flags] [args],例如:

$ kubectl config [action] [flags] [args]

我几乎每天都会用到 kubectl,但我的确很少去看它的文档,甚至我都想不到我是怎么就会使用它的。越是在复杂的项目面前,这种一致性带来的好处越明显。

而一个典型的反面教材是 Git。它是我用过的最复杂同时又是最混乱的 CLI,以一般人最常用的分支操作举例:

# create branch
$ git checkout -b new_branch

# delete branch
$ git branch -D new_branch

你会发现对于创建和删除分支这种最基本的命令,它 checkout 是一个动词,branch 又是一个名词,前者 -b 来代表 branch 这个名词,后者 -D 来代表 delete 这个动词。短短两行命令,还是最常用的两行就让我们看到这种设计是多么没有逻辑。更别说还有 git pullgit fetch 这种了。