安德斯·海尔斯伯格的原则:可扩展与持久软件架构的经验教训
安德斯·海尔斯伯格(Anders Hejlsberg),这位C#和TypeScript等标志性编程语言的首席架构师,以及Turbo Pascal和Delphi的缔造者,数十年来一直在塑造着软件开发的方法论。他的职业生涯不仅仅是创造成功的产品,更是一段持续反思如何构建经久不衰、可灵活扩展的系统原则的旅程。深入分析他的工作,我们能发现一些普适性的模式,它们适用于设计任何能够长期演进的复杂系统。这些经验教训,通过为数百万开发者打造和发展关键工具而锤炼而成,在瞬息万变的技术格局中依然具有重要的现实意义,涵盖了从反馈速度到人工智能的作用,再到开放协作的重要性等诸多方面。
1. 快速反馈——生产力的基石
安德斯·海尔斯伯格的早期经历是在严苛的限制下形成的。在内存仅有64KB的计算机时代,任何不必要的抽象都无立锥之地。他回忆说,在那种条件下,开发者能够“将所有东西都装在脑子里”,而核心需求是代码编写后能立即执行。
“当你敲完代码,你希望它能立刻运行起来。”——安德斯·海尔斯伯格。
Google AdInline article slot
Turbo Pascal的巨大影响力,与其说在于Pascal语言本身,不如说在于它极大地缩短了反馈循环:编辑、编译、运行、调试、重复——所有这些操作都无需磁盘访问和漫长等待。这种方法节省了开发者的时间和精力,让他们能够更高效地工作。
同样的理念,尽管形式不同,却在几十年后于TypeScript中得到了体现。语言本身只是其价值的一部分。TypeScript的很大一部分优势在于其强大的工具链:增量类型检查、快速的部分结果以及即使在超大型代码库上也能即时响应的语言服务。
这里的实际启示至关重要:开发者在选择工具时可以直接应用这一原则。快速反馈从根本上改变了行为。当错误迅速浮现时,开发者更愿意尝试,对重构更有信心,并且能在问题发生时更早地发现它们。反之,当反馈缓慢时,团队不得不通过复杂的约定、变通方案和繁琐的流程来弥补。无论是选择语言、框架还是内部工具,反馈速度都至关重要。那些能缩短编写代码与理解其后果之间距离的工具会赢得信任。而那些即使功能强大却增加延迟的工具,往往会被淘汰。
2. 软件规模化意味着放弃个人偏好
当海尔斯伯格从个人工作转向领导团队,尤其是在Delphi时代,最具挑战性的并非技术变革,而是需要放弃个人偏好。他意识到,在团队开发中,“你必须接受事情不会按照你喜欢的方式完成。即使去修正它,也无法改变其行为。”
这种方法远不止适用于语言开发。任何需要在团队间扩展的系统,都要求从个人偏好转向共享标准。目标不再是“你愿意编写的代码”,而是“许多人都能理解、维护和演进的代码”。
C#并非作为一个理想的“白纸”概念而诞生,而是各种冲突需求妥协的产物。Visual Basic开发者需要简洁性,C++开发者需要强大功能,而Windows则要求实用主义。最终结果并非一个理论上完美的系统,而是一种人们能够有效使用的语言。编程语言的成功,并非因为它设计得完美无缺,而是因为它能适应团队实际的工作方式,并使他们能够高效协作。
3. TypeScript为何选择扩展而非取代JavaScript
TypeScript的出现,是因为JavaScript达到了极少数语言才能企及的规模。随着浏览器成为真正的跨平台运行时,团队开始开发远超动态类型有效支持水平的应用程序。早期解决这一问题的方法往往相当激进:一些团队将其他语言编译成JavaScript,以获得静态分析和重构工具。
这种做法从未让海尔斯伯格满意。告诉开发者放弃他们已经投入甚深的生态系统是不现实的。在2012年创建一个全新的语言,不仅需要一个编译器,还需要数年时间投入到编辑器、调试器、重构工具,以及最重要的是,社区的采纳。
相反,TypeScript选择了一条不同的道路——它扩展了JavaScript,在继承其缺点的同时,显著简化了大型项目的开发。这不是一个意识形态上的决定,而是一个纯粹实用的选择。TypeScript之所以成功,是因为它在开发者已经面临的限制下工作,而不是强迫他们放弃现有的工具、库和思维模式。
归根结底,主要的教训是妥协的必要性。适应现有工作流程的改进更容易推广,而需要完全替换的增强功能则很少能获得广泛关注。实际上,重大的进步往往是通过演进你已经依赖的现有系统来实现的,而不是试图从头开始。
开放性与适应变化
4. 透明度是开源成功的关键
TypeScript并非一夜成名。早期版本虽然形式上是开源的,但开发工作大多是闭门进行的。这一情况在2014年发生了改变,当时项目迁移到GitHub,开发过程变得完全公开。功能提案通过拉取请求提交,妥协方案公开讨论,任务优先级根据社区反馈确定。
这一转变使决策过程变得透明。开发者不仅能看到发布了什么,还能了解为什么做出某些决定而放弃另一些。对于团队而言,这也改变了他们确定工作优先级的方式。他们不再猜测什么最重要,而是可以直接观察到开发者真正关心的问题。
成功的开源项目不仅仅是发布代码。它们让决策过程变得可见——这样贡献者就能理解优先级和权衡,这最终能建立信任并促进更积极的社区参与。
5. 放弃JavaScript作为实现语言是必要的
多年来,TypeScript编译器是自举的:用TypeScript编写并作为JavaScript运行。这提供了强大的浏览器内工具,并简化了实验。然而,随着时间的推移,局限性变得显而易见。JavaScript是单线程的,缺乏共享内存并发,其对象模型虽然灵活,但资源密集。随着TypeScript项目的增长,编译器未能充分利用大部分可用的计算资源。
团队达到了一个点,进一步的优化已不足以解决问题。他们需要一种不同的执行模型。一个有争议的决定是将编译器移植到Go语言。这并非从头重写。目标是语义保真。新编译器必须与旧编译器行为完全一致,包括其怪癖和边缘情况。Rust尽管很受欢迎,但由于所有权约束和循环数据结构的普遍使用,将需要进行大量的重新架构。Go的垃圾回收机制及其与TypeScript的结构相似性,使他们能够在增强性能和并行性的同时,保留原有行为。
结果是性能的显著提升,无论是在原生执行还是并行性方面。更重要的是,社区不必重新学习编译器的行为。有时,最负责任的选择并非最雄心勃勃的选择,而是那个能保留原有行为、将干扰降到最低,并消除任何增量优化都无法克服的硬性约束的选择。
开发的未来与协作的作用
6. 在AI时代,约束比生成更重要
安德斯·海尔斯伯格对主要为AI设计的编程语言持怀疑态度。他指出,大型语言模型在它们已经广泛接触过的语言上表现最佳,这自然有利于JavaScript、Python和TypeScript等庞大的生态系统。
然而,在工具方面,AI确实改变了游戏规则。传统的IDE模型假设开发者编写代码并使用工具辅助此过程。现在,这种关系正日益逆转:AI系统生成代码,而开发者负责审查和修正。类型检查器和重构引擎等确定性工具充当“护栏”,防止细微错误。这类工具的价值在于其精确性和约束性:它们必须提供准确的语义信息,以便AI系统能够提出有意义的问题并获得可靠的答案。
风险并非AI系统会生成糟糕的代码,而是它们会生成看似合理但未能考虑到项目代码库所有细微之处的代码。对于开发者而言,这改变了关注的焦点。最终,在AI辅助工作流程中最有价值的工具是那些能够适当施加约束的工具。强大的类型系统、健壮的重构工具和准确的语义模型成为不可或缺的推动者。它们提供了结构,使得AI系统的输出能够被有效检查、验证和纠正,而不是被盲目信任。
7. 开放协作的至关重要性
尽管面临资金和维护的挑战,海尔斯伯格对开放协作依然保持乐观。一个关键原因是“机构记忆”(institutional memory)。多年的讨论、做出的决策和达成的妥协都保留下来,可供搜索和查看。
这段历史并没有消失在私人邮件链或内部系统中。任何想了解系统如何以及为何演进的人都可以访问它。“我们的项目记录了12年的历史,”他解释道,“如果有人记得某次讨论发生过,我们通常都能找到。上下文不会消失在电子邮件或私人系统中。”这种可访问性改变了系统的演进方式。设计讨论、被否决的想法和妥协方案在个体决策做出很久之后仍然可用。对于后来加入项目的开发者来说,这种共享的上下文往往与代码本身一样宝贵。
核心要点
- 快速反馈是提高生产力和开发质量的关键因素,它能促进实验并迅速发现问题。
- 规模化要求放弃个人偏好,转而采用共享的、易于理解的规则和满足团队实际需求的实用解决方案。
- 演进式开发(如TypeScript对JavaScript的扩展)通常比革命性的替换更有效,因为它尊重现有的工作流程和生态系统。
- 过程开放性在开源项目中能建立信任,确保决策透明,并保留宝贵的机构记忆。
- 将AI集成到开发中时,重点应放在提供精确性和约束的工具上(例如,强大的类型系统),它们充当生成代码的“护栏”。
结论:数十载不变的模式
在四十年的编程语言开发历程中,相同的主题始终如一地浮现:
- 快速反馈比架构的优雅性更为重要。
- 系统必须考虑到由多人编写的不完美代码。
- 行为兼容性往往比架构的纯粹性和理论理想更为关键。
- 可见的妥协和过程透明度能增强社区信任。
这些并非细枝末节。它们是决定一个工具能否随着用户群体的增长而适应,并经受住现实世界考验的根本性决策。此外,它们也为创新奠定了基础,确保新思想的引入不会破坏已有的良好运作。对于那些希望自己构建的工具能够经久不衰的人来说,这些基本原则与任何革命性功能同样重要。而这,或许正是安德斯·海尔斯伯格最重要的教训。
— Editorial Team
暂无评论。