代码简洁之道:推理与选择
作者:Max Kanat-Alexander | 2020年8月7日
任何软件系统最重要的特性之一,是无需运行就能理解其行为的能力。这个概念通常被称为系统的"可推理性"。本质上,你希望在不实际观察系统运行的情况下,就能对系统的结构、行为和结果做出判断。
系统可理解性的价值
想象一个由百个部件组成的系统。为简化理解,假设这是个实体系统而非计算机系统——比如从原材料到成品汽车需要100道工序的自动化工厂。每个部件都对输入材料进行加工并输出产品。这个系统的配置方式有多种可能:
-
复杂交互模式
每个部件执行多重操作,且根据操作类型决定下一工序的走向。例如金属棒加工机需要根据时间、车型需求等动态因素,在5种金属类型和不同规格间做出选择,并将半成品导向5台不同的后续机器。当系统中每个部件都采用这种复杂决策模式时,人类既无法推断整体系统行为,甚至难以理解单个部件的运作逻辑。 -
简单线性模式
每个部件只有单一输入输出,且仅与特定前驱/后继部件交互。虽然整体系统仍由100个部件构成,但每个部件的独立分析变得简单,从而可逐步推导出整个系统的逻辑行为。
这就是简洁性的核心——构建可推理的系统。在软件系统中查看任何代码单元时,开发者应能通过阅读代码和注释就理解其行为边界、保障机制和潜在结果。这正是许多编程语言中"私有/公有"函数概念的价值所在——它们明确了系统各部分的交互边界。良好的函数/变量命名同样重要,因为它们直接支持这种推理能力。
开发者的选择负担
当我们将汽车工厂的比喻延伸到开发场景,假设每个"机器"由人工操作(对应开发者通过IDE、编译器等工作),情况会如何?
-
复杂系统困境
每个加工环节都需要人工判断金属类型、产品规格等参数。这虽然创造了工作岗位,但会引发大量错误。类比到软件开发,当开发者需要维护的"机器"(类/函数)达数百个时,系统就会变得无法驾驭,导致开发效率骤降和团队倦怠。 -
简化系统优势
简单明确的部件让单个开发者可轻松管理多个"机器",错误率大幅降低。关键在于识别开发者真正需要做出的决策:
- 必要决策:业务逻辑实现等核心工作
- 非必要决策:基础框架选型等应标准化的部分
选择优化的实践策略
-
生命周期适配
- 初创阶段:允许选择基础技术栈(语言/框架)
- 成熟阶段:固化技术标准,避免重复决策消耗
-
生产力权衡
假设全公司每个团队都花两周评估框架,而标准化方案能节省这部分时间,其累积效益将超过绝大多数局部优化。但需警惕过度限制——例如强制使用不支持HTTPS的框架将造成安全灾难。 -
自由与效率的平衡
虽然短期内限制选择可能引发抵触,但长期看,消除非必要决策实际上解放了开发者的创造力。关键在于:- 通过约束提升系统构建能力
- 确保限制始终服务于创作自由
“你不是在扼杀生产力,而是在消除那些本不需要做出的选择带来的干扰、障碍和困惑。” —— Max
读者讨论精选
Steven Gordon博士
实践中总会存在不透明遗留系统的依赖,使得完全实现"可推理性"和"选择优化"变得困难。相比理解整个代码库,我更依赖结构良好的自动化测试来验证系统行为假设。
作者回复
开发者通常有能力使其负责的模块保持足够的可推理性。即使是错误处理场景,系统行为也应具备可预测性。虽然测试是有效工具,但我仍期望代码本身具备可读性和明确的边界设计。
Kursith
在自动化浪潮中,本文让我重新思考工程师的价值——技术发展始终需要人类的创造性思维。这种结合机械思维的软件开发视角非常有启发性。