像维护软件一样维护效率系统
标题可能会让人误以为我要介绍精密复杂的 PKM 体系,但实际上我 我不混“知识管理圈” 很久了。我想我数次安装和卸载 Emacs,仍然用 Neovim 写代码和写文,一部分原因是 Org Mode 对我毫无吸引力,甚至有可能会害了我。
好的软件不总是精巧复杂的,甚至大部分时候是简单的,或者说清晰明了,而且可拓展、可组合,在需要的时候不会因其形式或接口而派不上用场。比方说 grep 作为命令行工具,可以搜文件里的文本、可以搜目录里的文件名、可以搜终端历史里输入过的命令,也可以很轻易地集成到其他软件里搜别的东西。
这其实也不是我想谈的重点。实际上,即便是 grep 这样小巧简明的软件,在某些情况下也难以施展拳脚,比如面对完全不了解命令行界面的用户时。对他们而言,Raycast 和 Vicinae 等全局搜索框可能更好用,按下 ⌘ + 空格 就可以搜索应用、文件和各种快捷命令并执行。把两个关联不大的软件放在一起比较可能不恰当,但至少能证明我下面要抛出的观点:
好的软件应该是符合需求的软件。
想象你年迈的奶奶一点也看不清楚手机上的小字,而你却在一旁抱怨软件开发者没能统一设计语言,竟然在界面上放这么大的字儿和这么老派的配色,还给了这么多乱七八糟的设置项,一点也不优雅——这可不是好事。
用户画像和需求获取
我有点不太理解为什么有人喜欢浏览各种花哨的 Notion 模板,就像我用不了现成的 Neovim 和 Emacs 配置一样,噪音太多了。有人试图说服我一点一点来,有些功能放在那里不用就好。然而「不管某些小细节」对我来说很难,我需要在大脑里自己起一个垃圾收集器,持续不断地消耗 CPU,就为了释放内存。貌似许多人的 GC 是编程语言自带的,甚至可能 像 Java 一样 ,大部分时候都不运行。
最近我意识到这可能是我的神经特异性导致的。我今年才开始正视自己的孤独症(Autism)特质。神经多样性好像已经变成玩笑话了,大家说「自己没点病都不好意思上网」,我厌恶甚至指责这种说辞。要指责的一方面是把神经特异当作「神经反常」「精神病」的陈旧思想,另一方面是,这种说辞看似在攻击无病呻吟者,实际上加剧了神经特异者的边缘化,因为这话背后的意思是:大部分说自己是 ADHD 或 ASD 的人都在装酷。那真正的 ADHD 和 ASD 还怎么敢站在公共面前呢?而且他们本来就更不善社交。
我跑题了。我想说的是,我的确有很多孤独症人群常见的特质,而且这些特质影响了我的日常生活,也影响了我对自我管理体系的需求。
首先,我对感官信号过于敏感,我希望系统本身的感官刺激可控且令我安心。这几天看了一期讲 孤独症人群感官体验 的视频,频道主说自己睡觉的时候会觉得自己的心跳声像摇滚演唱会一样吵,我也是!我时常在半夜起身反复确认有没有地震,因为我的心跳好像震得我全身都在动一样。我和频道主一样,也会忧虑是不是自己的心脏有问题,然后为此辗转反侧。实际上就是我对某些信号太敏感了。
不只是自己的心跳,环境噪音也是。我不喜欢去酒吧这种吵的地方(清吧会好很多),因为要主动屏蔽杂乱的环境信息很累。就算是相对安静的环境,我也时常听到其他人没注意到的声响和小细节——这是一体两面的,对细节的关注在某些情况下是优势,但也是需要正视的劣势。
如果我的效率工具有太多不可控的感官刺激,我用起来会觉得很累。飞书的多维表格就是反例,它大体上是即时通信工具,我很难不被侧边栏的消息和表格各种花里胡哨的浮窗、工具栏分心。即便我并没有点击那些东西的欲望,我也会觉得要感官过载了。
我的情况可能还要再极端一点,我去年 全面抛弃了数字记录 ,因为电子设备本身就是极大的感官干扰。即便全屏打开笔记编辑器,只运行一个应用,我的脑海中也会冒出数种可能性——这就不是感官刺激的范畴了,和注意力机制的关联更大。
之所以 Doom Emacs 里提前配置好的各种插件让我坐立难安,而 Clojure 标准库里丰富的函数并不会对我造成困扰,是因为函数在形式上是单一且确定的,只要当作接收参数然后返回特定值的黑箱就好,而 Emacs Mode 千千万,有的能收发邮件,有的能看 RSS 和 Hacker News,有的还能在 Matrix 上发消息,我永远也不知道下一个会以什么形式出现。
我希望系统的形式足够简单,简单到用几种甚至一种要素就能表示我想要表示的所有东西。就像 Lisp 只需要用 s-expr 就能表示所有的语言单元一样,我希望我在管理待办事项和备忘的时候,不需要频繁切换思维方式。
下一个需求有点矫情:我不喜欢有人教我做事。我至今没办法在别人看着我的情况下工作(不久前我的同事跟我交流工作的时候,盯着我写 Agent 的提示词,我感觉自己要爆炸了,原因很复杂)。我能接收批评指正,我不会把情绪带到工作上来,我也很少让情绪影响周围的人,但这意味着我要在大脑里另起一个线程,处理自己的胡思乱想。我当然不希望我自己的系统过于严格,让我没有喘息的机会,我希望我使用它的时候,心情是愉悦的,能立马感受到事情在我的掌控之内。
系统又不是主体,它怎么会教你做事?怎么会审判你?可很多时候就是这样。我错过了自己设置的截止日期,或者在安排要做某件事情的时间里提不起劲儿,我会责备自己太拖延、太懒惰。某个待办上写的事情我只做了一半,但当天已经结束了,我只能推迟到下一天——我知道给框框画勾很爽,但划掉框框再移动到下一页,糟糕的感觉也程度相当。
我还常常有这样的体验:做了某些事情之后(往往是逼自己做的),感觉身体很沉重,就算是做自己喜欢的事情也觉得累,根本不想动。这件事情有可能仅仅是跟指导老师发信息等回复而已。之前提到的那个视频里,频道主把这种现象比作「清醒的宿醉」。在这种情况下,若还有个严格的系统管制我,让我在自己的空间里也不得安宁,我只会想逃。效率系统的效果不应该是让人想逃避做事。
简单来说,我希望,就算我完全精神崩溃,生活糟糕得不能再糟,沉闷地过了几周甚至一个月之后,只要我决定再爬起来,我就可以立马打开我的笔记本,像什么事情都没发生一样做自己该做的事情。
所以,这样一套效率系统的业务需求是:帮助易受感官刺激影响、注意力容易分散、精力波动大的用户,建立简单直接且容易管理的生活和工作计划,并且不会在执行过程中感到压力山大。
需求分析和系统建模
业务需求已经确定,那么现在应该分析用户需求了。上个阶段的产物是对业务需求的整体描述,这个阶段的产物是具体的用例(Use cases)。
用例既描述了具体的用户需求,还界定了系统与外部实体的边界。谁在系统之内?谁在系统之外?谁与系统交互?做什么交互?系统最终要实现哪些交互背后的功能?这些问题都会通过规定用例得到解答。看起来做需求分析就该写用例呢。
但是我不。
软件需求工程的各种理论在我看来既有新学科的不成熟,又十分老派。比方说下面这个需求层次图,把软件需求分成业务需求、用户需求和功能需求(以及非功能需求和约束条件)的做法,其实相当局限。
这张图片来自 这篇论文 ,是有关为中小型企业开发的电商网站的需求分析方法的案例研究。很多需求工程方法论都是针对大型软件的,因为这些软件的需求很复杂、变动大,需要工程化的方法管理和维护。
这就是老派的点。至于为什么说不成熟,是因为这类方法论不仅实际应用不广,学究气息很重,而且很快就被新的软件开发模式替代了。比方说敏捷开发就可能认为,在前期制定过大的需求规格很有可能造成浪费,默认需求是持续变动的。还有不少软件团队不交付用例,而是交付用户故事(User story)。还有一种系统建模方式就叫作 故事驱动建模 ,系统建模也是需求工程的一个环节。
话说回那些简单的软件工具。你要如何想象 grep 的需求规格说明书呢?如果现在有人要开发一个新的 Vim 编辑器,他们会怎么收集和整理需求呢?在用例里写这种东西吗?——“1. 用户输入文本;2. 用户保存文件;3. 用户查看文件。”
总之,应该根据实际需要开发的软件的类型和特质选定需求分析方法,我决定描述类似用户故事的使用场景来分析用户需求:
- 用户需要规划一天的计划。
- 将前一天尚未完成或者主动推迟的事项移动到这一天;
- 从一个大的待办清单里挑选一些这天可以做的,放到这一天;
- 添加一些临时发生或一时兴起的事项;
- 如何减轻第一步的心理压力?
- 用户在一天的某个时刻,需要确定接下来做什么。
- 打开当天的计划并浏览未完成事项;
- 逐项评估用户当下做这件事情的意愿;
- 选择意愿最高的事项执行;
- 如何评估意愿?
- 所有事项的执行意愿都低下的边界情况怎么处理?
- 用户突然收到通知、回忆起某件事情、产生了灵机一动的想法,或者发现了新鲜事物,需要处理。
- 评估事项的紧迫性和执行意愿:
- 如果必须或十分想要立刻完成,先做记录,然后执行;
- 如果不必立刻执行,先记录到当天的计划中但不执行;
- 继续之前的事项;
- 评估事项的紧迫性和执行意愿:
- 用户在一天结束时需要回顾计划完成情况。
- 观察所有被记录但尚未执行完毕的计划;
- 评估短期内的执行意愿和执行的必要性:
- 如果必须做,且执行意愿较高,标记为需要移动到下一天(等到情景 1 发生时处理);
- 如果必须做,但执行意愿不高,标记为搁置,移动到未定时间的大待办清单里;
- 如果不必做,但执行意愿较高,标记为搁置,移动到未定时间的大待办清单里;
- 如果不必做,且执行意愿不高,直接删除。
- 同场景 1,如何减轻这个过程的心理压力?
- 用户需要定期回顾不定日期的大待办清单,对于每个事项:
- 评估执行意愿和必要性,删除执行意愿不高且不必做的事项,留下其他事项;
- 评估事项的紧急性,将紧急事项插入到当天或者第二天的计划中;
- 对于余下的事项,如果有新的想法和细节补充,可以做备注。
- 长期滞留在大待办清单里的事项要怎么办?
不难发现,在上述描述中,用户与系统的边界很模糊,有很多事情是需要用户参与决策的。用户也是系统的一部分,甚至说制定系统就难以避免教育用户以某种方式做事。再者,这些场景中也有些模糊和疑惑的点。
无妨,需求本身就难以捉摸。需求工程中还有一个步骤叫作需求验证,常见的方法是追踪需求的跟踪关系(也就是能不能通过功能需求倒推到具体的用户需求,用户需求能不能推到最初的业务需求)、同行评审和…… 找用户确认。
那么就让我问问自己,这些用户需求是否合理,其中的疑惑应该如何解决。
- 如何减轻处理推迟计划的心理压力?
- “如果能专注「怎么把所有的未完成事项都通过某种方式消除」,不管是做完的、推迟的还是取消的都一视同仁,就能减轻负担。就像消消乐一样,无论是连线消除的还是用道具消除的,消完了都会觉得爽。”
- “不过这的确把责任交给用户了,是不是好事,大概要按情况评估。上述做法对不少用户可能无用,如果能接受用户群体缩小或部分用户不满,也是可以做这个取舍的。我认为这个体现在项目理念和用户手册里就好了。”
- 如何评估意愿?
- “啊,真是个刁钻的问题。想做就是想做,不想做就是不想做,这是很主观的体验欸。我认为主要问题是用户可能不会主动评估自己的意愿,习惯纠结事项本身的难易程度、紧急程度和重要程度,而很少听自己的想法。这类用户就是我们用户画像和业务需求里描述的那一类。”
- “所以,与其尝试用另一个外在的指标量化「意愿」,不如在流程上引导用户自己做出判断。比如提问用户「从 0~5 打分,你觉得你自己有多想做这件事情?」或者「在事项 A 和 B 当中,你宁愿做哪个?」”
- 所有事项的执行意愿都低下的边界情况怎么处理?
- “同理,总能选出更愿意做的事情。我想系统本身也提供了一个有限的选项池,让用户不至于在一两件不想做的事情和一大堆未知、模糊的可能性里做选择,在少数事项里选择更不讨厌的,可能更容易把执行意愿提上来一点。”
- “另外,之前业务需求的分析里还提到,目标用户容易出现精力骤降的情况。如果执行意愿都很低,可能是临时的精力问题。我们的业务需求之一就是不让用户在执行过程中感到压力,这种情况下要允许用户不做某些事情。我认为这些事情都可以通过已有的回收和推迟机制解决,也就是把事项挪到第二天或者大清单里。”
- 长期滞留在大待办清单里的事项要怎么办?
- “滞留会带来什么风险吗?我认为是没有的,就像系统回收站不清理,除了占用磁盘空间之外也没别的害处了,而磁盘空间可能并没有那么重要。”
- “如果出现大量想做但短期内执行意愿不高的事项滞留,这确实是先前没有考虑过的场景,值得后续讨论。不过因为风险较低,现阶段可以先搁置,实现已有的需求就好。”
好了,已经收集完一波同行评审和用户反馈了——奇怪,回答问题这人怎么既是需求分析师,又是目标用户呢? 不过,现有的方案如果贸然投入成本开发,可能不会满足需求,因为仍有不少待定的点。然而,这些点即便是在内部反复讨论,可能也不会有突破,貌似只有投入开发才能够收集到真实的数据和反馈啊。
那就投入较小成本,做个原型产品试试看吧!
原型开发和迭代
我们其实还没有完成系统建模,这也是需求分析的一部分,但是一直纠结某个活动属于生命周期的哪个部分实在是太无聊了。不多言,直接来画状态机吧。(机什么?)
前文反复提到「记录」和「标记」的概念,一条记录可以被标记为「搁置」,可以被「移动」,还可以被「删除」。状态的变更也是规则的。简单来说,可以给系统中的记录或者说事项规定以下状态:
这张图里的方框代表待办(todo),画了一捺的方框代表正在进行(doing),打勾自然表示完成(done),删除或者说取消(cancelled)也应该是不言自明的。值得注意的是推迟(postponed)和搁置(suspended)的区别,推迟表示这件事情已经被移动到之后具体的某一天的计划里了,有了明确的去处,而搁置则与古希腊哲学的悬隔(Epoché,或者 suspension of judgement)有些关联,表示这件事情还没有去处,当下也不打算做出判断,不删也不做,应该移动到不定时间的大待办清单上。
此外,还有两个不是方框的标记,分别是事项(item)和笔记(note),前者记录那些没有计划(也不需要计划)但是做了的事情,留档记录;后者记录需要今天或这周晚些时候回顾的事情,其实更像是备忘(memo)。这看似是方框和非方框的两种形式,但其实都是对记录(record)的标记(mark)而已。一条记录由标记和描述组成,就只有这么一种直观的形式。
嗯?你问我这么设计的依据是什么?是这样的,我们观察目标用户很久了,他的笔记本上用的就是这些记号。他以前也有过别的标记体系,但最终留下来的是这么一套,对他而言足够简单直观。这难道不比花里胡哨的理论和看似严密的逻辑,更具说服力吗?
噢等等,等等,架构师先生,请您冷静一下。我知道您的函数式技术倾向让您认为状态是邪恶的,但难道您不认为我们要开发的这套系统是事件驱动的,必须要关心状态变更吗?难道你要让任务一开始就单线地递归执行到底,就为了维持清晰的数据流吗?你不觉得我们的目标用户其实并没有像猴子一样多的精力吗?嗯?你问我为什么要像英美文学里的小说人物一样说话?好吧,先生,我想我只能告诉你,写这段话的人最近不务正业,看小说看得有点太多了。
如此一来功能需求其实也比较清晰了,那么来选择技术栈吧!架构师先生,您别纠结要用 Emacs Lisp 还是 Lua 写了,客户点名儿要用 Spring Boot。唉?唉唉唉!我开玩笑的,您别掐自己人中啊!害,您瞧瞧这事儿办的。其实业务需求里写得已经很清楚了,目标用户需要感官刺激可控的,也不喜欢电子设备,我觉得呀,纸和笔就够啦。至于尺寸,咱也就别用那 A4 大夹板,也别用 A5 大活页了,客户反馈说他连 A5Slim 都写不满,还嫌重呢!A6!A6 就够啦!哎呀,您就别问我说话为什么这么像北京人啦,你又不是不知道这写字儿的人整天都在发什么神经。
我们先来看看 MVP 的效果怎么样吧。
恕我直言,女士,这就是两页非常普通,谁都能涂涂画画写出来的纸!
可先生,客户反馈他用这套方法感觉自己比以前任何时候都觉得轻松,完成的事情也不少,这难道我不是更符合需求的系统吗?先生,恕我直言,我觉得是时候拿出这张图了。
可是你看,那两页纸上还有很多不规范的地方,比如星号明明是用来标记笔记和备忘的,却也被用来给待办事项分区。笔记中间还有各种飘来飘去的箭头,根本不知道是什么意思!这系统未免有点混乱。
好问题,可这不正是让我们了解到了之前没能发现的需求吗?显然只定义记录和标记并没能解决目标用户的所有问题,他还有先前未发现的,给记录分区、分类的需求。至于那些箭头,很有可能也是我们需要建模在系统里的新要素。至于这会不会让系统变得过于复杂,难以拓展,留下技术债务,就是要进一步讨论的话题了。
CI/CD 和文档
还记得软件装在盒子里售卖的年代吗?我没经历过那个年代,我开始接触编程的时候,人们就已经完全拥抱 Web 了(如今反倒有逐渐抛弃 Web 的趋势),一切都部署在服务器上。我记得不久前还有好多人说 PHP 是最好的语言呢,如今…… 呃,PHP2Shell 的确让整个互联网都见识到了 PHP 的强悍。
再新一点的概念应该是 CI/CD,也就是持续集成,持续部署,把软件的生命周期变得更灵活了一些。软件没必要打磨到完美才发售,因为软件不再装在盒子里了,更新的成本很低。如果完全部署在云上,配合自动化工作流,也能很快把新的版本编译、打包、部署到服务器上。我认为,速度并不是 CI/CD 以及与之相关的软件开发模式的最大优势,而是能够一边开发一边收集反馈,可以快速收集和验证需求,及时调整开发方向,避免在前期投入大量成本。
效率系统也是,即便是纸笔,也可以很灵活。前期可以用易于调整的活页本运行原型系统,试验一两周之后收集和整理反馈(自己问自己也是很重要的),发现问题后一条条列出来,然后一条条找到解决方案。而且,别忘了,有问题的大概率不会是用户,而是系统。所以,用到难用的软件要大大方方(但清楚有条理)地指出问题,效率系统执行不下去也不该责备自己。这种时候应该迭代一个新版本,编译后部署到自己的笔记本或者别的什么载体上。
文档是软件的一部分,大的架构决策应该要有 ADR(架构决策记录)背书,也方便后来者理解「为什么要这么做?」,系统的各个组件应该要有文档描述其内部结构。我还听过一个说法,每一行代码都是有文档的,因为每行代码提交时都有写 commit 信息(前提是你真的有好好写这个东西)。即便是自己一个人的项目,我也喜欢手写 Issues 和 Pull Request 信息,设置以计划发布的版本号命名的里程碑(Milestone),这能帮助我思考和规划,也能帮我在后来追溯当时的想法。
单独在本子的某个地方,或者别的载体(比如博客)上写清楚系统这么设计的前因后果,也有助于自己梳理思路。此外,无论是描述效率系统还是开发软件,写文档都能让我对自己的系统有新的认识,偶尔也会因此蹦出新的想法来。
当然,也要警惕,无论是沉溺与架构决策还是挖掘新需求,都有可能系统偏离原本的需求和目的,最重要的是,这样一定会忽略大量的细节问题,而细节与全局同样重要。我想 Vibe-coder 们是没有想过这些问题的,他们的软件大多是做完就丢的东西,持续时间不会很长。一上来就把系统设计得庞大又复杂,就跟跑马拉松一上来就把配速拉到极限一样。除非你根本就不打算跑马拉松,否则我建议你认真对待细节,尽可能消除危险的模糊性。
最后
嗯?你问我这套系统怎么检索?怎么和其他系统集成在一起?怎么一键导入 Anki 制作成记忆卡片,一键扫描归档进 Zettelkasten,怎么把涂画变成 Mermaid 流程图?——为什么需要那些东西?
不过话说回来,数字笔记的确有很多好处,我会在我真的需要检索、回顾和快速捕捉的场景下使用数字笔记,比方说我最近干运维的活儿比较多,为了帮助我记住自己在哪台服务器上改了哪个配置,把哪个文件放在了哪台机子上,某个服务应该用哪个端口访问,这个端口有没有被 ufw 或者 fp 挡住等等,我会在做了某些操作之后立刻在 Logseq 里留下一条记录。
选择 Logseq 的原因也很简单,写标签很快,后续索引也方便,大纲式笔记也很适合做事件记录。更何况 Logseq 自带日记功能,我要记录只需要打开界面,直接把某条记录写进日记页,打上标签以后就能检索到。另外,它是用 Clojure 写的,我已经不知道是第几次提到这点了。
就这样吧,祝你也迭代出适合自己的系统。
- 这仅仅是针对我自己的情况而言,详情请阅读后文。我真的好害怕有 Emacs 用户跑过来教我 Emacs 和 Org Mode 的正确打开方式啊。
- Garbage collector(垃圾收集器),指代清理废旧、过期数据的机制,一般指编程语言的内存回收。
- 另称「自闭症」,也叫孤独症光谱障碍(Autism Spectrum Disorder, ASD)
- 求求 Emacs 用户不要过来告诉我很多 Emacs Mode 都可以把数据写成 Org Mode,放在一个
.org文件里管理,形式上也很统一。 One man’s meat is another man’s poison. - 我至今不能原谅 cl-annot ……
- 并不是公司的活儿,而是管理我自己的 VPS,我也把升级自己个人电脑的软件包当作运维工作。
- 分别是 Ubuntu 的 Uncomplicated Firewall,和 OpenBSD 的 Packet Filter。
- 至于缺点…… 他们仍然没有支持 XDG 基本目录规范,并且现在也包含 LLM 生成的代码,再者,ClojureScript 的性能真的不算好。