学习软件架构指南Learning Software Architecture
针对物理学家转型软件开发者的疑问,作者系统梳理了软件架构的学习路径:从理解基础抽象(如模块、接口)入手,逐步掌握分层设计、解耦原则和演进式架构思想。强调实践比理论更重要,建议通过重构真实项目来内化概念。同时指出,物理建模思维可迁移至系统复杂度管理,但需注意软件工程特有的权衡取舍。
回复一封关于研究物理学家如何学习软件设计技能的邮件:
我职业生涯早期曾加入一个生物信息学实验室,因此我认为自己理解你所说的“科学代码”现象!我的看法如下:
第一个核心观察是:“软件设计”这种东西最好是通过实践来学习。虽然我在大学时上过一些正式的“设计”课程,甚至还在课程项目中担任“架构师”,但那些内容大多只是纸上谈兵,就像幼儿园小朋友在玩消防员游戏。真正教会我如何做事的,是我职业生涯中的一个偶然——我的第二个重要项目(IntelliJ Rust)让我进入了软件领导岗位,设计从此成了我的责任。我在 IntelliJ Rust 中确实犯过一些错误,但不算太糟,而且我学到了很多。所以这是个好消息——软件工程足够简单,一个有求知欲的人完全可以从基本原理出发(再辅以阅读各种博客文章)把它搞明白。
第二个核心观察,坏消息来了:康威定律很重要。软件诞生的过程会不断复制其开发组织的社会结构。或者,用 neugierig 的话说得更精彩些:
如果我要用一句话总结我所学到的东西,那就是:我们谈论编程时总以为是在写代码,但实际上代码的重要性远不如架构,而架构的重要性又远不如社会因素。
我怀疑你感受到的工业界与科学界软件之间的差异,与其说是关于构建软件的知识不同,不如说是激励人们去生产软件的领域不同。“我的博士论文需要在三个月内发表一篇论文”这类目标,或许就是关键解释?
这里有两个你可以做的事。第一,有时你会遇到机会去设计或引导某个项目的激励机制。这种情况千载难逢,但影响巨大。这正是 TIGER_STYLE 背后的精髓所在——不是规则本身,而是让这套规则成为好主意的那种社会语境。
第二,你可以加速经历悲伤四阶段,最终达到接受。激励机制几乎从来都不是你理想中的样子,但如果你无法改变它,至少可以学会适应它。大多数工业级软件项目也是如此——永远没有“合适的时间”把事情做对,你只能在约束条件下做到最好。
让我以 rust-analyzer 为例。该项目的物理现实是:它既非常深奥(它是一个编译器!太棒了!)又非常广泛(与 LLM 相反,传统 IDE 包含大量为特定用途定制的功能)。社会现实则是:“深度编译器”能吸引少数才华横溢且专注的贡献者,而“广度功能”则适合一大群周末战士——他们学习 Rust,没有持续参与项目的能力,但愿意花一两个小时来解决自己的问题。
我坚持认为 rust-analyzer 不需要构建 rustc,它基于稳定版 Rust 开发,没有任何 C 依赖,且整个测试套件只需几秒钟——这些主张都是为了吸引高影响力贡献者的目标服务。我努力优化构建系统,确保人们可以在不操心其他事情的情况下直接参与借用检查器的开发。
为了吸引那些只在周末投入时间的开发者,rust-analyzer 的内部被拆分为多个独立的功能模块,每个功能在运行时都通过 catch_unwind 进行保护。我的想法是:我不必在这些地方过度追求质量,只要“正常路径能工作并经过测试”,就可以接受 PR。代码崩溃也没关系,只要它能吸引更多后续贡献者即可,前提是:
相比之下,在核心基础架构(即支撑各功能的主干)上工作时,我对质量的要求则相对更为严苛。
关于适应而非修复激励结构的一点警示——未来往往以最不方便的方式降临。最初设计 rust-analyzer 的动机正是为了避免编写一个并行编译器(如 IntelliJ Rust 中的那个),并尝试为 LSP 打造一个更优的架构原型,以便将经验反哺回 rustc。因此,即使在核心模块中,代码本身也极具实验性质。唉,如今看来,我们似乎真的被困在一个额外的编译器里了?
我猜测 uutils 项目可能经历了类似的过程:它起初是学习 Rust 的主要入口,最终却演变为 Ubuntu coreutils 的实现。
第三,接下来是一些具体的建议。遗憾的是,目前我找不到一本可以推荐、能涵盖所有这些真理的书。我怀疑这类书只存在于 Borges 某个伪经短篇故事中:实践似乎是关键所在。不过以下几点值得留意:
Gary Bernhardt 的《边界对话》(Boundaries talk)是我永恒的最爱。它提供了扎实的技术层面指导,更重要的是,它触发了我对更高层次问题的思考。
《如何测试》(How to Test)是我一直希望拥有的一本书。我立刻理解测试的重要性,但花了很长时间才足够自信地承认:大多数广为流传的测试建议不过是江湖骗术般的玄学,并真正弄明白什么才是行之有效的做法。
∅MQ 指南,以及更广泛地说 Pieter Hintjens 的著作,让我接触到了康威定律(Conway’s Law)的思考方式。rust-analyzer 那种“功能开发”式的架构——乐观合并(optimistic merging)的应用——正是这种思想的具体体现。
Jamii 所写的《十年编程反思》(Reflections on a decade of coding)极为出色,内容非常元化(meta)。我特意将其列为第一条链接,因其立意明确。
Ted Kaminski 的博客是目前最接近完整软件开发理论的存在,恰如其分地被表述为一部尚未成书的一系列笔记!
至于实际书籍,《Google 软件工程》和 Ousterhout 的《软件设计哲学》常被推荐。它们确实不错。尤其是《Google 软件工程》,帮助我记住了几个重要术语。但对我而言,这些书并未带来颠覆性的启发。
需要完整排版与评论请前往来源站点阅读。