做可能最简单的事情纽带X科技

做可能最简单的事情

22分钟 ·
播放数0
·
评论数0

节目简介: 欢迎收听本期节目,我们将深入探讨 Sean Goedecke 在软件设计领域提出的核心哲学——“做可能最简单的事情”。这不仅是解决 bug、维护现有系统的方法,更是一种构建新系统架构的指导原则。我们将挑战传统上对“理想”系统的追求,并发现为什么真正的精通往往意味着减少而非增加复杂性。

本期节目要点:

“做可能最简单的事情”的核心原则

◦ 在设计软件系统时,建议始终选择可能最简单的解决方案

◦ 这一原则适用于修复 bug、维护现有系统,以及架构新系统。

◦ 作者认为,许多工程师倾向于设计“理想”系统(例如,结构良好、几乎无限伸缩、优雅分布式),但他认为这是一种错误的方法。相反,我们应该花时间深入理解当前系统,然后选择最简单的方案。

简单为何常被低估

◦ 系统设计涉及多种工具(应用服务器、代理、数据库等),初级工程师在使用这些工具构建复杂系统时会感到乐趣和满足。

◦ 然而,真正的精通往往体现在“少做”而非“多做”。

伟大的软件设计常常显得“平淡无奇”。当看到这种设计时,你可能会觉得“这个问题原来这么简单”或“哦,根本不需要做任何困难的事情”。

Unicorn 就是一个极佳的例子,它通过利用 Unix 原语提供 Web 服务器的关键保障(请求隔离、水平伸缩、崩溃恢复)。行业标准的 Rails REST API 也是如此,它以最“无聊”的方式提供了 CRUD 应用所需的一切。这些系统本身可能不“令人印象深刻”,但它们是设计上的壮举,因为它们做了可能最简单的事情

实践案例:限速功能设计

◦ 假设你需要为一个 Golang 应用添加限速功能。你可能首先想到引入像 Redis 这样的持久化存储来跟踪用户请求。

◦ 但作者建议先问:“可能最简单的事情是什么?”

▪ 能否在内存中保留每用户的请求计数?即使应用重启会丢失数据,这真的重要吗?

▪ 你的边缘代理是否已经支持限速?或许只需在配置文件中添加几行代码即可,根本无需实现该功能。

◦ 只有当这些更简单的方案确实无法满足需求(例如,因为服务器实例过多导致内存限速不精确,或数据丢失不可接受)时,才应考虑引入更复杂的持久化存储。

如何以此方式构建完整应用

◦ 从绝对最简单的事情开始,只有在新需求强制要求时才进行扩展

◦ 将 YAGNI (You Ain't Gonna Need It) 原则作为最高设计原则,甚至超越单一职责、选择最佳工具或“良好设计”。

对“做可能最简单的事情”的常见反驳及回应

1. “会导致系统成为大泥球(Big Ball of Mud)?”

▪ 一些工程师认为,这听起来像是让他们停止真正的工程,而仅仅进行“临时凑合(quick kludge)”。

▪ 作者反驳道,临时凑合并不简单;它通过引入需要额外记忆的复杂性,反而增加了代码库的复杂性。

▪ 寻找最简单的解决方案需要考虑多种方法,这本身就是一项困难的工程工作,但通常真正的修复方案反而比临时凑合简单得多

2. “什么是简单?”

▪ 工程师对“简单代码”的定义常常存在分歧。

▪ 作者提供了一个直观的定义:

活动部件更少:当处理系统时,需要考虑的东西更少。

内部连接更少:系统由具有清晰、直接接口的组件组成。

• 例如,Unix 进程比线程更简单,因为它们不共享内存,内部连接更少。

▪ 当不确定哪个更“简单”时,可以使用一个决胜标准:简单系统是稳定的。如果两个系统状态中,一个在需求不变的情况下需要更多的持续维护工作,那么另一个就更简单。例如,内存限速就比 Redis 更简单,因为它不需要部署、维护、监控一个单独的服务。

3. “系统无法伸缩?”

▪ 持这种观点的工程师会质疑内存限速无法伸缩。做可能最简单的事情,确实无法提供“web 级”的系统,但它能提供在当前规模下运行良好的系统。

▪ 作者认为,对“伸缩性”的痴迷是大型科技 SaaS 工程的主要罪过

预测瓶颈几乎不可能:对于非琐碎的代码库,你无法提前预测在流量增加几个数量级后所有瓶颈在哪里。最多只能为 2 倍或 5 倍的流量做好准备,然后随时解决问题。

导致代码库不灵活:为了所谓的伸缩性而解耦服务,反而可能让某些功能实现起来异常困难,因为需要跨线协调,甚至涉及复杂的事务处理。大多数情况下,这些复杂性都是不必要的。

作者的最终思考

◦ 作者认为,随着在技术领域工作的时间越长,对预测系统未来走向的能力越不乐观。

◦ 理解系统当前状态的难度已经足够大,而大多数设计都缺乏这种理解,因此设计质量不佳。

◦ 软件开发有两种主要方式:一是预测未来需求并为此设计系统;二是根据当前需求设计最佳系统,即做可能最简单的事情。

评论区亮点

◦ 有评论认为架构简单性在大规模下不重要,但作者不同意,指出功能交互越复杂,简单架构越重要。

◦ 作者向 Ward Cunningham 和 Kent Beck 致谢,指出是他们创造了“do the simplest thing that could possibly work”这一表达。

关键收获:

拥抱核心简单性:刻意寻找最简单、最直接的解决方案,即使它看起来不那么“炫酷”或“高大上”。

专注于当前需求:避免为未经证实或遥远的未来需求进行过度设计,而是根据系统当前的真实需求进行设计。

重新审视“简单”:衡量简单性时,关注更少的活动部件、更少的内部连接,并将系统的长期稳定性作为重要的判断标准。

警惕过度工程:认识到对无限伸缩性的盲目追求,可能导致不必要的复杂性、僵化,并阻碍系统的快速迭代和适应。