黄东旭:写给后端程序员看的认知心理学丨Go+ 1.0 发布会干货分享
10 月 15 日,七牛云主办的「Go+ Together!Go+ 1.0 发布会暨 Go+ 开发者基金会启动仪式」在上海隆重召开。
本次大会中,PingCAP 联合创始人兼 CTO 黄东旭的分享主题独辟蹊径,题为《写给后端程序员看的认知心理学》,“可交互性的设计需要多想一步,告诉用户半步,让用户自己走半步。”黄东旭将认知心理学和最贴近物理世界的代码、软件融合到一起,分享了我们认知外部世界的模式以及需要跨越的两条鸿沟。
以下为黄东旭主题演讲的内容整理:
先介绍一下我自己,我叫黄东旭,是 PingCAP 的联合创始人兼 CTO。
我一直在看心理学的东西,作为一个程序员这么做其实很奇怪。我发现有一个特别大的问题,不知道大家有没有看过一个梗 —— 「请问怎么退出 Vim?」。这个问题让我陷入了一个深深的思考。
当年我一直觉得用不好 GDB 是我智商不行,后来想了一下这是系统软件斯德哥尔摩综合症。我用 Vim 用了很多很多年,我自己祖传的很多 Vim 配置也一直在维护。对于这件事我觉得特别自豪,花了很长的时间把这个难搞的东西搞熟了。
我觉得程序员群体,特别是后端程序员经常会有一个倾向,觉得一个东西复杂就是厉害,特别崇尚复杂的东西。但是,都 21 世纪了,为什么你们程序员就不能把软件做得好用一点?
说回我为什么会看心理学?是因为我发现好多 C 端的软件,包括很多的消费电子产品,不管是买苹果还是买安卓智能手机,没有人读说明书吧?你买一台手机回来,一拆盒子一打开,好像天然自动就知道开机键在哪儿。而对比 Vim 这种连退出都不知道怎么退出的软件,我觉得还是 VSCode 更香一点。这两个事物的对比让我觉得系统程序员再往前走一步就进入到了玄学的领域,这个玄学的领域就需要开始研究心理学了。
我在看一本认知心理学基础的课程,里面有一张图我觉得特别好,人去跟外部世界做交互的时候,大概是要通过两个链路,左边这条是我们看到一个东西之后应该怎么做,做完之后马上就要有一个执行和评估。
在美国生活过的朋友可能经常用到这种燃气灶,这个东西设计的问题在于不知道具体哪个旋钮对应哪一个灶?如果把这个旋钮错落有致的简单排列一下,就能简单的映射到。
再举第二个例子。
大家看这个门把手是不是感觉比较奇怪?明明门把手上写的是 Push,但却是一个让人拉的形状。看到门把手自然而然想去拉它,但是实际上却需要推。这个就是违背了自我意识的产品。
之前我自己总结过一些东西。比如设计了一个数据库,或者设计了一个系统软件,写得超稳定、性能超好,但用户就是用不起来该怎么办?我给大家提供理论支持:
一、跨越执行的鸿沟:可交互性
如何跨越执行的鸿沟?——在技术软件里面有一个重点叫"可交互性"。
1)可交互性的第一个关键点 —— 「NO Surprise!概念模型」
人在做一件事情的时候,脑子经常都会对接下来要做的事情有下意识的预设,如果你的行为和预设不一样,就会很奇怪。
大多数有驾照的同学,无论什么车只要上去基本都会开,因为基本所有的车都长这个样子。但凡超出了这个模式,大家就会变得非常困惑,就不会开车了。
对一个程序员来说,看到 “$” 符号和下滑线,想到的不会是挣钱也不是钱,而是会意识到这个地方可以敲东西。同样,看到一个大于号再加一个下滑线的时候,也会想到这个地方是可以敲东西的。为什么会这样?因为习惯。
再比如在设计一个基础软件的时候,通过一个特别简单的概念,或者自洽的模式,避免一个电视机出现五个遥控器类似的设计。下面我举几个概念模型设计特别好的例子。
多插一句,有很多程序员在设计软件的时候,只关注内部而忽略掉外部的人如何看这个软件。我觉得这方面写的文章和参考太少了,希望以后可以有更多人多写点类似的东西。
第一个例子是 UNIX。我现在觉得一个东西做简单其实是特别厉害的事情,就像欧几里得的书最厉害的就是那五条公理,而不是那几百个定理。UNIX 同样非常牛,一切皆是文件,数据是流,Pipe 来串联流。
第二个例子我单独要拎出来,是控制器。这个东西太重要了。
基础软件里面有一种软件使用的交互模式叫控制对象,比如大家常用的 redis。我发现一个特别奇怪的现象,问十个做基础架构的后端程序员用过最好的工具是什么工具,八九个都会说是 redis-cli,我相信用过 redis 的同学一定会对 cli 工具印象深刻。
一个好用的软件和一个难用的软件区别是什么?redis-cli 操作的重点是「一切皆是 KV」。假设 redis 本身是一个 KV,控制器也是一个 KV 的模型就很好接受,在 redis 里面修改配置也采用 KV 这种形式,开发者们不用单独去学。
MySQL 数据库也是,任何的数据库在操作、去看系统状态的时候,通过 cli 的 interface 提供交互的方式是最自然的,尽管 SQL 本身就是用来倒腾数据的语言。在操作数据库时用 SQL 去做控制很正常,但最大的忌讳就是对应关系混乱。
2)可交互性的第二个特点——对程序员来说没有人会读文档
在我看来,文档基本跟字典差不多,大家学语文肯定不是通过看新华字典学会的。
我不知道是不是普遍的现象,但至少对我来说,我在用一个新东西的时候,我会有一个相似的心理活动。比如说在 GitHub 或者 Go+ 上,打开一个虽然不知道在讲什么的页面,我的目光会一直去找能够复制粘贴的东西,如果代码不能复制粘贴就再往下拉,一直拉到出现可以复制粘贴的东西,复制到 shell 上面看看会发生什么。
对于一个项目的作者来说,这是你能够去赢得用户的有且只有的唯一一次机会。我觉得大多数国内的软件公司,都从来没有注意过这个事情。
另外,Quick start 的第一条 shell 命令至关重要,因为决定了后续还有没有后续。
这张 PPT 里我稍微总结了一下这个模式。
有一年我在布鲁塞尔开会,跟一个陌生老外聊天,后来他喝多了跟我说"一切不能用 APP Store 安装的软件,都是耍流氓。"所以官方的管理器一定是你的首选。
Docker 也是一个好选择,但你不能假设用户的机器上有 Docker,比如前端的程序员。
第一行 shell 完成后下一步该干什么?有很多人会注意到第一步,很多程序员觉得安装完就算搞定了,但其实第一行顺利成功以后,最好引导用户到一个可交互的环境,告诉用户下一步该干嘛。
这里我举一个例子。
打开 TiUP 的网站就是这样,只有两句话的介绍,我也从来没读过。我作为一个程序员,目光集中在第一行,拷贝到 shell 以后,看看会发生什么事情,然后系统马上告诉我接下来该干什么。
再执行复制粘贴,在一分钟之内便搭好了一个本地的 TiDB 集群。最后大家仔细看,下一步你可以用 MySQL 客户端连接上,或者很多其他方法,比如导点数据进来等等。
另外一个例子是 Telegram,在去做机器人的时候是很好用的。
当我们要去做生态合作开发的时候,比如要用到 GitHub,要先找到 GitHub 的开发者中心,然后在里面找到项目后再看文档,各种各样的东西非常复杂。而 Telegram 的 Botfather 非常棒,可以直接让它创建 bot,并且可以直接给 bot 起名字,全程是一个交互式的体验。
即使 telegram 有一个特别长的文档,但我从来没有读过。对此我可以非常自豪的说,而且我相信 telegram 的 botfather 也会很高兴,我从来没读过文档也可以开发机器人。
关于可交互性,下一点就是多想一步,告诉用户半步,让用户自己走半步。
有很多程序员觉得我帮你想了、再帮你做了,那是不行的。人其实是一个很奇怪的动物,刚才我提到人总是幻想着拥有自我意识,但其实我们根本就没有。但如果让人觉得自己尽在掌握的感觉,会感觉很爽。所以尽量在做操作之前提供 DryRun 的 mode。
今天是 Go+ 的场子,但我想安利一下 rust。
大家看这个 Complier,它在你出错以后会告诉你哪里错了、你应该怎么样。你肯定不喜欢一个编译器强行直接给你做修改。
另外一个关于可交互性最重要的点就是反馈。
大家为什么会觉得 Redis 的感觉特别好?因为它快,快就让人有顺滑的感觉。根据生理学理论人的反应时间大概是100-200 毫秒,如果你在操作 100-200 毫秒没有反馈的话,人就会觉得这个东西就是卡。
如何让一个软件让人有愉悦感?就是不管怎么样,不管处理完还是没处理完,在 100 毫秒内给一个 feedback,人就会觉得很顺滑。
我自己总结了一个反馈三定律:
第一,不要暴露内部概念!不要暴露内部概念!不要暴露内部概念!我觉得大多数程序员在做一个 to 用户的文档时,最容易犯的错误就是这一个。比如说内部有一个东西叫"发动机",开车的时候你告诉他发动机第三个车轮有问题,用户就蒙圈了。
第二,用精简的人话暴露进展和状态。不要说废话,更不要不说。
第三,反馈必须即时。
我自黑一下,举一个 TiDB 的例子。
这是用户写的一个问题。对于用户而言,谁能告诉他 Region 是什么?下一步应该怎么办?
再举一个好例子。
这是数据库的扫描过程,虽然跑的并不快,但因为有一个进度条在不停的动,大家就会感觉非常快。这就是认真设计过可交互性的软件应该有的行为,不是去「憋大招」,在后台慢慢扫描 30 秒,最后告诉你结果。而是会一条一条告诉你,同时设置一个进度条。
还有一个非常尴尬的问题,但我还没有想到答案。
各种各样的配置文件是一个特别体验不好的东西,尤其是对于复杂的软件来说。我们在座的各位应该没有人会喜欢配置文件,可能有些斯德哥尔摩综合症型的程序员会喜欢或者喜欢过。
从人性的角度出发,从一个普通程序员角度来说,我觉得系统不应该需要配置,就像 iPhone,我们不可能在拿到手后先改一下再用。但基于目前人类的科技还不能实现。
配置最麻烦的点是一个慢反馈的过程。比如我们要修改配置,第一步要找到配置文件,找到后进行修改,然后退出再重启。万一打错一个字,可能要到下一次重启才知道。
这个过程非常纠结,为此我写了一些原则。在目前业界普遍都不太好的情况下,能做的最好的程度了。
第一点就是放在正常人能想到的位置。我特别不喜欢配置的文件放在「当前文件夹」,当你在奇怪的环境里面跑程序的时候,你当前的文件夹到底是哪个?
最后一行是我自己的心智负担,环境变量是心智负担最小的。环境变量小于命令行参数,约等于控制器,最差最差的是配置文件。这个排列是我自己的感知,不是特别权威的顺序。
关于可交互性的最后一步,就像 Go+ 的语法里面借鉴了很多的 Go,这是挺好的方式。世界上有很多很好的例子,包括 Docker CLI、Kubectl、Redis CLI 其实都不错,抄就完了。
二、跨越评估的鸿沟:可观测性
下一个话题是可观测性。
可观测性的第一个问题是「谁在观测?」
这个问题的答案大家都知道,是程序员、开发者在观测。我不止一次听说过我们自己人包括有很多友商非常自豪的跟客户说「我们的监控里有几千个监控项」,但自从我学了心理学以后,才知道人同时能够关注的东西有四个对象数,超过了四个就不知道是什么东西了,所以千万不要搞太多。
下一个问题是「区分噪音和信息」。对于什么是有用的信息,我的经验是「跟着关键资源走」。
那什么是关键资源呢?对于一个系统来说,我基本会灵魂拷问这二十个问题。比如说突然莫名其妙给你一个完全陌生的环境,你只要把这 20 个问题搞清楚,大概就知道这个系统的状态。
可观测性做得好的软件,一定会有一个特别厉害的特点,就是会去「利用人的直觉」。
比如说人看到红色就会意识到 STOP,绿色就是 GO。
相信大家都用过 htop,我觉得它最巧妙的一点就是利用了进度条,红绿相间让人直接对系统 CPU 的使用率有一个直观的认知。
这些火焰图的形状便是生产环境中一小块数据被访问的频度,我不画这些框,大概能看到下面肯定有点问题,只有一个热点在里面工作。这样一看便能发现有问题,出现了自增主键。
以前我也觉得用 BCC 这些东西不熟练是因为我智商不行,直到我用了 Go,我觉得 Go 用户体验这块做得太完美了,会去利用人认知的一些心理学的技巧,让人去关注到一些系统异常的东西。
我再举一个例子,也是一个小练习。
这是 TiDB 马上会推出的 TopSQL,不告诉大家这是什么功能,相信大家也能发现左边和右边有什么不一样,那一片绿的东西有点不对劲。纵轴是 CPU 的使用率,横轴是时间,里面不同的色块对应这个时间内发生的语句。绿色部分指的就是这条语句在这个时间内占了 CPU 的多少,我们不用精确到数字就知道能分辨出来。
可观测性还有特别重要的一个点,就是周期。
一个老司机和一个新人分别去看系统,我总结了一个最大的区别。老司机会在心中自动画一个时间轴,关注整个业务在周期内的状态,而新人只会关注到离散的一些点。
还有一个经常被人忽视的点是事后观测。最近接到一个用户的骚扰电话,挂了是因为 CPU 出现了问题,但我看各种的监控都没问题,因为所有设置都是预先设定好的。但是我发现那个问题实在太诡异了,相当于你去做体检,体检项目包含了耳鼻喉,但其实是内脏之类的地方出了问题,所以看不出来。这时候便需要靠直觉找到,这是很吓人的。
我以后一定要做一个功能,这个系统每隔一分钟做一个 Profile,这就是可观测性救命的时刻。我觉得是人写的东西都会有问题,只要有问题就必须有人去抢险救灾,这个时候用户的体验是最有价值的。
今天分享的这个话题我觉得还是挺重要的。谢谢大家。