April 25, 2025
By: Kevin

代码之上: 编程的真正核心

above

你有没有过这样的经历: 面对技术文档或者一个的代码库, 感觉就像在迷雾中航行? 你拼命想抓住顿悟时刻, 结果却发现自己比开始时更加迷茫. 我们常常觉得, 只要代码能跑, 文档齐全, 这事儿就算成了. 但如果这种想法本身就错了呢?

我们习惯于把软件看作是代码, 界面, 文档这些 "看得见摸得着" 的东西的总和. 就像工厂生产线, 写代码, 写文档, 打包发布, 搞定. 但这种 "生产视角" 常常无法解释一些令人头疼的现实: 为什么有些 bug 如此诡异, 难以捉摸?

为什么修改看似简单的功能会牵一发而动全身, 成本高得吓人? 为什么精心编写的文档有时并不能真正帮到后来者?

计算机科学界的先驱人物 Peter Naur(图灵奖得主 BNF 范式的发明人)早在 1985 年就提出了一个颇具颠覆性的观点, 收录在他那篇影响深远的论文(编程即理论构建)中.

他的核心洞见是: 编程的本质, 并非主要是生产代码和文档这些"产出物" , 而是程序员在头脑中构建关于问题和解决方案的"理论".

这里的"理论", 不是指像爱因斯坦相对论那样宏大的科学理论. 它更接近哲学家 Gilbert Ryle 所说的"knowing how"(知道如何做). 它是一种深度的, 内化的理解, 一种直觉, 一种关于 "为什么" 这样做而不是那样做的融会贯通.

它包含了对现实世界问题如何在程序中被映射, 被处理的深刻把握. 这种" 理论" 才是软件开发中最宝贵, 最核心的资产, 它存在于程序员的大脑里, 而不是纸上或屏幕上.

Naur 用了两个案例来说明这一点:

  1. 编译器的故事(Compiler): A 团队构建了一个编译器. B 团队接手, 试图在其基础上增加功能, 即使他们拥有 A 团队所有的代码, 详尽的文档, 甚至可以直接和 A 团队成员交流, 他们仍然举步维艰. 为什么? 因为 B 团队缺乏 A 团队在构建过程中形成的内在" 理论" ------那些关键的设计决策背后的深层原因和权衡. 他们提出的修改方案, 在 A 团队看来像是笨拙的" 补丁" , 破坏了原有设计的优雅和一致性. 多年后, 当这个编译器再传给与 A 团队完全无关的新团队维护时, 尽管最初的健壮结构依稀可见, 但整个系统已经变得臃肿, 脆弱, 充满了" 无定形的附加物" ------因为后来的修改者没有掌握最初的"理论".

  2. 工业监控系统的故事(Scada): 一个复杂的大型实时系统, 在每个工厂都需要定制. 有一个核心团队, 从项目初期就深度参与设计, 安装和后期的故障排查. 这个团队高度依赖他们长期积累形成的直觉和对代码(有注释)的直接理解来解决问题, 甚至觉得额外的正式文档在排错时没什么用. 而其他只接受了正规培训和文档, 但缺乏这种长期深度参与的团队, 在面对同样的问题时却常常束手无策. 核心团队拥有的, 正是那份通过实践和持续投入建立起来的"理论" .

这些案例揭示了什么? 代码和文档本身, 就像菜谱和食材, 它们很重要, 但并不能完全传递大厨脑子里对火候, 调味, 技巧的精妙理解和直觉判断. 真正的知识, 尤其是那种"知道如何做" 以及"为什么这么做" 的隐性知识(tacit knowledge), 很难仅仅通过文字完全传递.

这个"理论构建" 的视角, 能帮我们理解很多事情:

  1. 为什么文档会失败? 因为它们很难捕捉和传递程序员头脑中的完整"理论" .
  2. 为什么知识传递这么难? 因为真正的理解不仅仅是信息, 更是通过构建过程获得的经验和直觉.
  3. 为什么修改代码常常代价高昂? " 修改代码" 听起来比" 修改文字" 容易, 但这忽略了修改必须与底层" 理论" 保持一致. 如果你不理解这个理论, 你的修改很可能变成破坏性的" 补丁" , 即使它表面上能通过测试. 这就像给一栋设计精良的建筑随意加盖, 很容易破坏整体结构.
  4. "程序生命, 死亡与复活":
    • 生命: 掌握理论的团队在积极维护和控制修改.
    • 死亡: 掌握理论的团队解散或失去控制. 程序也许还能运行, 但失去了被" 智能地" 修改的能力, 因为" 理论" 失传了.
    • 复活: 试图仅凭代码和文档让一个" 死亡" 的程序" 复活" 几乎是不可能的. 因为丢失的" 理论" (那些" 为什么" )无法被完全重建. Naur 甚至认为, 与其费力" 复活" , 不如让新团队从头开始, 构建属于他们自己的新理论------这往往更有效率, 也更健康.
  5. 编程方法论的局限性: 无论是敏捷, 瀑布还是 Scrum, 这些方法可以提供有用的框架和启发(帮助构建理论的工具), 但不应被视为僵化的规则. 真正的编程活动, 其核心是理论构建, 这是一个非线性的, 充满洞察的过程, 无法被一套固定的步骤完全框定. 程序员应该基于自己不断发展的理论和具体问题来选择合适的工具和技术, 而不是盲从某个"方法".
  6. 文档的真正价值: 文档的主要目的, 或许不该是追求对当前状态的完美描述(这几乎是个不可能完成的任务), 而应该是帮助下一位程序员/更快地构建他们自己的理论/. 通过清晰地阐述核心思想, 设计原理(" 为什么" ), 关键隐喻, 来触发正确的联想和理解. 这种" 催化剂" 式的文档, 远比不断过时的细节描述更有长期价值.
  7. 程序员的真正价值: 如果编程的核心是构建理论, 那么程序员就绝不是可以随意替换的"码农" 或"资源". 他们是拥有宝贵知识和判断力的专业人士. 他们的经验, 他们对系统的深度理解, 才是项目成功的关键. 这意味着, 我们需要给予程序员稳定, 尊重和与其专业性相匹配的地位, 而不是把他们当作生产线上的零件.

那么, 这对程序员意味着什么?

  1. 专注于构建你自己的理论: 学习编程或接触一个新系统时, 不要只满足于让代码跑起来或记住 API. 要努力去理解它背后的设计哲学, 核心抽象和它试图解决的现实问题. 问自己"为什么? "
  2. 重视隐喻和沟通: 在团队中, 寻找或建立清晰的共享隐喻(就像 XP 提倡的), 它可以极大地促进团队成员之间" 理论" 的对齐和传递.
  3. "尊重"活的知识": 认识到最有价值的知识往往存在于那些长期深度参与项目的人的头脑中. 文档很重要, 但与人的交流, 学习他们的思考方式同样重要, 甚至更重要.
  4. 写"催化理论"的文档: 当写文档时, 多想想如何帮助读者理解核心概念和设计思想, 而不仅仅是罗列事实.
  5. 对"复活"旧代码保持警惕: 如果一个项目的核心"理论"已经失传, 尝试在其基础上做大的修改或扩展可能会非常痛苦且低效. 有时, "推倒重来" (构建新的理论)反而是更好的选择.

归根结底, Peter Naur 提醒我们, 软件开发首先是一项 人类活动 (Human Activity). 代码和工具是重要的媒介, 但真正的魔法发生在人脑之中------在那些不断构建, 检验, 修正自身 "理论" 的程序员心中.

理解了这一点, 我们或许就能更有效地应对软件开发中的种种挑战, 也能更深刻地认识到这项工作的真正价值所在.

下次当你再面对复杂的代码或文档感到困惑时, 不妨问问自己: 这个系统背后的" 理论" 是什么? 我是否真正理解了它? 也许, 答案就藏在代码之上, 在那更深邃的人类理解之中.

Tags: essay