软件工程哲学中最重要的一课
- 编程语言 Clojure 的作者 Rich Hickey:Simple Made Easy
| simple | easy |
|---|---|
| 词源:Simplex,单折、这一股 | 词源:临近(Adjacent / Lying near) |
| 反义词:Complex (复杂),词源 Complex,编织在一起 | 反义词:Hard (困难) |
| 定义:没有交织(Interleaving)。它只有一个角色,完成一个任务,关注一个概念。 | 定义:物理上的临近:触手可及。认知上的临近:熟悉(Familiar)。 |
| 客观的、原语、原子化的,组合是定义简单的关键。 | 相对的,简单的方法是完成某件事最快的方法。 |
- 构造:我们在写代码时的体验(比如:这就是几行代码,不用写分号,敲键盘很爽)。
- 产物:软件运行时的表现。
- 用户根本不在乎你写代码时有多爽,用户只在乎软件是否可靠、能否维护、能否修改。
- 我们必须基于产出的“产物”来评估我们的“构造”,而不是基于敲代码的便利性。
- 如果你关注 Easy(上手快、熟悉):起步极快(像短跑运动员),但随着项目变大,复杂度会累积
- 如果你关注 Simple(简单、解耦):起步慢,需要思考设计,学习不熟悉但简单的工具。但在长跑中,稳定
| Complex | Simple |
|---|---|
| 状态 (State):极其复杂的,它把“值”和“时间”纠缠在一起。 | 值 Values(不可变数据)是简单的。 |
| Object 纠缠了状态、标识和值 | Data(Map, List, Set)是透明且通用的。 |
| 方法纠缠了函数逻辑与状态。 | 函数 |
| 继承将类型耦合在一起,是典型的编织。 | 组合/多态 (Polymorphism à la carte) |
| 与其发明复杂的语法,不如直接用数据结构来表达逻辑。 | 数据 (Data) |
这里说说复杂。
Rich 复活了一个古词:Complect,意思是把东西编织、纠缠在一起。
模块化不等于简单:你把代码分成了很多模块,但如果它们之间逻辑紧密纠缠,那依然是一团乱麻。
真正的简单是让它们互不知道对方的细节(解耦)。
简单是一种选择(Simplicity is a choice)。
如果你构建了复杂的系统,那是你的错。不要把“易用(熟悉、顺手)”误认为是“简单”。
你需要培养对“纠缠(Entanglement)”的嗅觉,时刻警惕复杂度的产生。
设计简单系统的步骤:使用 Who, What, Where, When, Why, How 进行拆解
- What (做什么):定义接口,只通过值传递,不纠缠实现细节。
- Who (实体):组件化,尽量把子组件作为参数传进去(依赖注入),而不是硬编码。
- How (怎么做):具体的逻辑实现,不要和定义混在一起。
- When/Where (何时何地):不要直接调用(A调用B),这把A和B的空间与时间纠缠了。使用队列来解耦。
- Why (策略/规则):把业务规则从代码逻辑中抽离出来,变成配置或数据。
不要相信直觉上的“容易”,因为那通常只是“熟悉”的幻觉。
真正的软件工程需要忍受初期的“不易”,通过深度的思考和严格的解耦,去追求客观上的简单(Simple)”。
请停止编织代码,开始解耦设计。
- Convex 的 CEO Jamie Turner:Simple / Easy / AI
来源:https://jt.lol/posts/simple-vs-easy-vs-ai
Jamie Turner 刚入职场实习的时候仰慕的一位工程师给他的 2 个建议
- 别再使用 perl 了,来看看 python 吧。
- 别再用鼠标在编辑器里点来点去了,去学学 vi。
这里重点说 vi 如此成功的重要原因——它在组合方面表现出色。
一旦你学会了几个操作如“d”(删除),和移动如“w”(词),
你就会意识到你可以将它们串联起来做基本上任何事情。
你并不是在记忆所有混乱的字符组合,你仅仅是在记忆少量的原语。
对于一个新工具或想法,这里有两条截然不同的曲线在起作用:易于使用和易于学习。
- easy to use:给了最大的灵活性,使他们能够构建各种各样的东西,而不会产生复杂性或限制。
- easy to learn:从已知知识到熟练掌握新工具或新想法的距离很短。
- simple:interleaving,客观的、原语、原子化的,组合是定义简单的关键。
- easy:nearby,相对的,依赖于已知知识。简单的方法是完成某件事最快的方法。
如果我是 vim 用户而你是 Emacs 用户,对我来说在 vim 里删除一行是“easy”的,但对你来说可能不是。
然而,在两个编辑器中删除一行这个操作本身都是“simple”的。
人类倾向于容易。
人类因为受限于大脑的“工作集”大小和学习成本,往往倾向于选择 Easy 而非 Simple。
我们不愿仅仅为了可能得不到的回报去克服陡峭的学习曲线。
AI 不在意容易,因此更倾向于简单。
AI 并不在乎一个工具是否 Easy(易上手),
但它和人类一样受益于工具的 Simple(逻辑清晰、无歧义、可组合), 这减少了推理错误的概率(幻觉、Bug)。
以前,我们为了迁就人类的懒惰(追求 Easy),制造了很多泄漏的抽象。
现在,我们为了 AI(也为了最终更好的系统稳定性),设计更加 Simple 但可能学习曲线较陡峭(Not Easy)。
一个有趣的考量:
- 软件现在是否能更迅速地向更高层级的抽象迁移,因为 AI 将“学习时间”视为零?
- 这些新的抽象能否通过观察 AI 使用其设计的成功程度,而在人类采用之前就得到验证?
AI 时代的 API 设计应该回归本质上的 Simple,而无需过分妥协于 Easy。
