全部文章

职场之锤

一个没有PPT的System Design Workshop

本文另有英文译文 · 阅读英文版 →

好多朋友都知道我最近做了几场线下的System Design Workshop,其实最开始想做这个Workshop,是因为 System Design Interview。

做技术面试的人,大多绕不过这一关。

面试官给你一个问题:设计一个短链接,设计一个聊天系统,设计一个订票平台。然后在四五十分钟里,从需求开始,一步一步把整个系统搭起来。

这里面当然有很多东西可以讲。

Requirement clarification、capacity estimation、database、cache、message queue、scalability、consistency……

如果按照这些知识点往下列,三个小时很快就能排满。

但真正开始准备以后,我发现了一个问题:

这些知识,好像并不难找。

想知道 Redis 适合什么场景,网上有大量资料。想知道 Kafka 怎么工作,有书,有视频,有文章。想比较 SQL 和 NoSQL,搜一下就能找到几十种答案。现在更简单,直接问 AI 就可以。

如果我的 Workshop 只是把这些东西重新整理一遍,花三个小时讲给大家听,真没有太大意义。

这让我重新想了一遍:

System Design 到底难在哪里?


我见过不少这样的情况。Cache,知道。Message Queue,知道。Sharding,也知道。CAP,甚至可以讲得头头是道。

但是给一道没见过的 System Design 题,还是不知道从哪里开始。问题不是知识点不够,而是这些知识在脑子里还是散的。

现实中的问题不会告诉我们:

这里应该使用 Cache。

也不会在恰当的时候跳出来提醒你:

现在应该讨论 Data Consistency 了。

我们拿到的只是一个问题,剩下的事情,都得自己判断。

先想什么?什么现在不重要?什么时候应该开始考虑性能?为什么这里需要 Cache?加完 Cache 以后又会发生什么?新的问题出来以后,是现在解决,还是先放着?

真正做 System Design 的时候,我们一直在做这样的选择。

所以,System Design 真正难的,不是知道多少,而是能不能把知道的东西连起来。

从 Cache 走到 Data Consistency

Workshop 里有一个很简单的例子。

很多性能优化,本质上都绕不开时间和空间的交换。空间换时间,就是其中很常见的一种。

这个概念大多数程序员都知道。

如果我要讲空间换时间这个知识点,两分钟就够了:

为了提高读取速度,可以保存冗余数据。 有了冗余数据,需要考虑数据一致性。

但现场我没有这么讲。

我们先从一个问题开始:

如果现在读取很慢,怎么办?

大家开始想办法。能不能预计算?能不能加 Cache?能不能多保存一份更适合读取的数据?

慢慢地,我们走到了同一个地方:

用空间换时间。

我把它画出来,接着问:

现在系统和刚才有什么不一样?

我们引入了新的东西。更重要的是,原来只有一份的数据,现在有了两份。

那接下来呢?

数据流到底应该怎么走?如果其中一份变了,另外一份什么时候变?更新到一半失败了怎么办?如果两份数据不一样,哪一份算对?

到这里,我才写下:

Data Consistency

这和一开始告诉大家"使用冗余数据要注意一致性"是两种完全不同的学习过程。前者是一条知识。后者是一条走过的路。

我们没有因为课程大纲里下一项写着 Consistency,所以开始讨论 Consistency。

而是因为:

刚才做了一个选择,这个选择把一个新的问题带了出来。

这才是我真正希望大家留下来的东西。

以后遇到的可能不是 Cache。可能是 replica、search index、materialized view,也可能只是为了查询方便,在另一个地方多存了一份数据。

技术名词都可以变。但只要同一份事实开始存在于两个地方,就应该有人想到:

它们如果不一样怎么办?

当这个连接建立起来以后,知识才开始变成自己的东西。

好内容都是删出来的

这是准备过程中最明显的变化。

最开始我总觉得三个小时不够。这个也应该讲,那个也很重要,System Design Interview 经常问的概念最好都加进去。

后来想清楚以后,我开始删。

因为讲得越多,大家越容易觉得:我今天学了很多。但"学了很多"和"下次自己会用",不是一回事。

我开始更关心另外几个问题:

大家能不能看到这些知识之间的关系?做完一个选择以后,能不能想到继续往下问?碰到一个从来没有见过的题,能不能找到开始的地方?

所以 Workshop 的重点慢慢从"我要讲什么"变成了"我希望大家最后会什么"。

删到后面,我问了自己:

如果把所有技术细节都拿掉,这个 Workshop 还剩下什么?

能留存下来的才是真正的核心,最后剩下的其实是一条很简单的路:

先把问题搞清楚,找到真正的约束,做出选择,理解取舍,再把自己的判断讲清楚。

Cache、Database、Message Queue 都可能变。但这条路不会。

从这以后,整个 Workshop 的设计方向彻底变了。

但还有一个问题。

就算我想清楚了 System Design 应该怎么思考,我站在前面把这套方法完整讲一遍,也不代表别人就会了。

如果三个小时里一直是我在想、我在分析、我在给答案,听的人很容易产生自己懂了的错觉。但真正轮到自己面对一个问题,可能还是不知道下一步怎么办。

所以这时 Workshop 的问题又变了一次。

不只是:

我要教什么?

而是:

三个小时,怎么让大家保持专注,同时真的自己想过这些问题?

这个问题后来决定了整个 Workshop 的形式。

三个小时,大家在干什么?

三个小时真的很长。

尤其是在周末。

一想到如果有个人站在我面前,滔滔不绝地讲三个小时,我自己都很难保持注意力。

所以我开始设计的不是三个小时的 slides,而是:

这三个小时里,大家分别在做什么?

有时候听我讲,有时候看墙上的图,有时候回答问题,有时候一起讨论,有时候看着我在白板上把刚才讨论的东西写下来,有时候我会故意停下来,不给答案。

最后大家再拿一个实际的 case 一起做。

我希望人的状态一直在变化。听一会儿。想一会儿。说一会儿。再继续。而不是三个小时一直处于"接收"的状态。

我跟大家说,不用记笔记。

Workshop 完整的逐字稿和所有手绘稿,结束以后我都会分享。所以这三个小时就不用忙着把东西记下来。

专心听,专心想,专心参与就好。

到这里,PPT 其实已经变得不太重要了。

我觉得,手绘的白纸更合适。

我提前画了一些大幅的手写海报,通常是关键的结构和总结。随着课程的进展一张一张展示,再贴到墙上。

它们不会随着翻页消失。讲到后面的时候,前面一两个小时的东西仍然在墙上。我可以随时指回去,大家也可以随时看到。

下面就是几个例子。

System Design 定义手写海报:连接抽象业务目标与具体技术实现

软件开发几个原则手写海报:单一职责、开闭原则、关注点隔离、高内聚低耦合、保持一致性

技术名词与概念手写海报:数据保存、性能与空间换时间

但另外一些东西,我又不希望提前出现。

因为如果答案已经在墙上,问题就没有意义了。

所以这些部分我会现场写。

一个关键词。一个框。一条线。

讨论到哪里,写到哪里。

那些海报后来确实有不少人喜欢。

但如果让我自己选,我觉得这次 Workshop 最重要的并不是手绘。

而是提问

我会一直问。

为什么?如果这样会发生什么?还有其他办法吗?这个方案解决了什么?代价是什么?如果流量增加十倍呢?如果这个功能根本没有那么重要呢?

很多时候,我其实已经知道自己接下来准备讲什么。

但我会先问:

你觉得呢?

在答案出现以前,每个人至少需要先做一次自己的判断。

这个判断是否正确,并不重要。

重要的是,那几秒钟属于每个人自己的思考。

Workshop 的第三个模块是一个实际的 case。

前面两个模块,大部分是我在控制节奏。这个模块是我们一起推理。

我提出需求,大家不断提问和讨论,再根据每一步的答案继续往下走。

这一部分我很喜欢,因为:

大家开始知道自己应该问什么问题。

开始知道怎么做选择,怎么做判断,也开始知道怎么把自己的判断讲清楚。

这可能比记住任何一个具体答案都重要。

一不留神,讲了快四个小时

时间控制这件事,我显然还有进步空间。

前两个模块差不多各一个小时。中间休息十五分钟。第三个模块不知不觉就讨论了很多,只能快速带一下第四个模块。

全部结束的时候,接近四个小时了。

但有一件事情让我挺满意。

整个过程中,没人看手机。

到了最后,大家也没有越来越安静。

后来有朋友跟我说:

"好多东西感觉下周工作马上就能用上。"

还有人直接跟我说:

"你下次只要开课我就报名。"

其中有一个朋友完全没有写过代码。

她来之前还有点忐忑,不知道一个 System Design Workshop 会不会太技术。结束以后,她给我发了一大段反馈。

其中有一句:

"能感觉到所有人思路都紧紧跟着,整个三个小时,完全专注地听完了,印象里好久没有专注这么长时间了。"

她还说,她觉得不仅程序员应该来,做产品、数据分析,甚至想创业的人都可以来。

我看到的时候很高兴。

尤其是"好久没有专注这么长时间了"这一句。因为这刚好回答了我一直在想的问题:

三个小时,大家能不能一直都在?

至少这一次,可以。

同时验证了我设计 Workshop 时的一个想法:一个完全没写过代码的人,也能听懂 System Design。

如果 Workshop 的内容是怎么配置 Redis,Kafka 有哪些参数,数据库怎么做 Sharding,那没有技术背景的人当然没有必要来。

但这次大家真正花时间讨论的是:问题到底是什么?为什么做这个选择?解决了什么?又带来了什么?如果条件变了,刚才的答案还成立吗?有没有更简单的办法?什么时候应该停下来,不再继续设计?

这些问题当然会出现在 System Design 里。

但它们并不只属于 System Design。

做产品会碰到。

做数据会碰到。

做一个 business 也会碰到。

这也是准备这次 Workshop 以后,我对 System Design 本身理解发生变化的地方。

以前很容易把它理解成:

设计一个技术系统。

现在我更愿意把它看成:

面对一个复杂的问题,怎么一步一步做出有依据的选择。

技术只是这个 Workshop 用来练习这些选择的场景。

一个没写过代码的人能听懂,不是因为我把内容讲浅了。而是因为再往技术下面挖一层,讨论的其实是怎么提问、怎么选择、怎么权衡,以及怎么把自己的判断讲清楚。

这些东西本来就不只属于技术。

这个 Workshop 也是一次 System Design

我没有先决定用什么技术,再去找它能解决的问题。

而是先想清楚:

我到底希望大家学会什么?

然后再决定:

怎样才能让大家真的学会?

删内容、换形式、拿掉 PPT、增加提问、重新设计节奏——每一个决定都不是为了"不一样",而是为了回答同一个问题。

所以最后没有 PPT,并不是我一开始设计出来的特色。

只是一路做下来,PPT 没有留下来。提问留下来了,讨论留下来了,纸和笔留下来了,实际的 case 留下来了,逐字稿也留下来了。

下一次,你只需要带上纸和笔,我们一起来学 System Design。

System Design:从模糊问题到清晰方案,Clarify、Scope、Design、Evaluate、Communicate 五步法