欢迎收听 Hacker News 每日播报,今天我们将一同回顾科技界的最新动态,从缅怀传奇工程师到探索前沿技术,再到剖析工程实践与个人成长,内容丰富,不容错过。
缅怀传奇工程师 Bill Atkinson:Macintosh 时代的奠基者
Hacker News 社区近日沉痛缅怀了 Apple 软件工程的传奇人物 Bill Atkinson,他因胰腺癌于 74 岁辞世。Daring Fireball 的文章详细回顾了 Atkinson 在计算机历史,特别是 Apple 发展中的关键贡献。作为 Macintosh 早期团队的核心成员,他在硬件资源极为有限的条件下,将许多“不可能”变为现实。
Atkinson 的几项核心贡献包括:
- QuickDraw: Macintosh 的图形库,以其高效和优雅的代码至今仍被称赞。
- MacPaint: 一款开创性的位图图像编辑器,被认为是后来 Photoshop 等软件的概念原型。
- HyperCard: 一个革命性的用户可编程工具,其深远影响甚至被认为启发了万维网的一些理念。
- Atkinson 抖动算法 (Dithering Algorithm): 一种在有限调色板下模拟更多颜色的技术,至今仍在许多设备和应用中使用。
文章引用了 Andy Hertzfeld 的轶事,展现了 Atkinson 独特的思维方式和对代码极致优化的追求,例如他如何受到乔布斯启发发明圆角矩形,以及通过删除代码来“提高效率”的故事。许多开发者认为 Atkinson 可能是史上最优秀的程序员之一,他留下的代码和算法是给世界的宝贵礼物。
社区对 Bill Atkinson 的去世深感惋惜,并借此机会回顾了他对个人计算图形界面和用户可编程性领域的巨大贡献。HyperCard 被多人提及是他们编程生涯的起点或重要的灵感来源,有人甚至称《HyperCard Bible》是他们的“圣经”,认为 HyperCard 体现了通过创造来学习思考的哲学。大家讨论了 HyperCard 的精神如何通过 Visual Basic、Flash 甚至现代的低代码/无代码工具得以延续。
另一个重要的讨论焦点是 Atkinson 在 QuickDraw 中实现的“区域”(Regions)概念,特别是如何高效处理窗口重叠和裁剪。有开发者深入解释了 Regions 的技术细节,例如它如何使用类似 RLE 的结构来表示可见区域,以及这在内存和性能受限的早期 Mac 上的重要性,凸显了 Apple 在有限硬件上实现复杂图形界面的技术创新。
此外,一些个人化的回忆也浮现出来,例如一位曾在 Apple ColorSync 团队工作的开发者分享了拜访 Bill Atkinson 家的经历,当时 Atkinson 正专注于数字摄影,对在暗部捕捉细节充满热情。这场讨论不仅关乎一位传奇人物的离去,更是一次对现代计算基石的深刻回顾。
FAIR 包管理器:WordPress 去中心化基础设施的探索
joost.blog 的一篇文章介绍了 FAIR (Federated and Independent Repositories) 项目,旨在为 WordPress 生态系统提供一个去中心化的基础设施层,以解决当前 WordPress.org 集中式管理带来的问题。
文章指出,WordPress 生态系统长期存在权力集中、治理不透明、更新机制瓶颈以及插件主题发现困难等问题。FAIR 项目正是在此背景下诞生,它不是对 WordPress 核心的“分叉”,而是在现有核心之上增加一个新的分发层和独立的治理结构。FAIR 的主要目标是成为一个去中心化的包管理器,替代 WordPress.org 现有的插件和主题仓库功能。它通过一个 WordPress 插件实现,能够拦截并替换与 WordPress.org API 的通信,转而使用本地或由 FAIR 治理的替代服务。该项目目前由 Linux Foundation 托管,并由一个社区主导的技术指导委员会 (TSC) 负责技术治理。
社区对 FAIR 项目的出现既有希望也有疑虑。许多开发者对 FAIR 项目表示欢迎和兴奋,认为这是解决 WordPress.org 现有治理和中心化问题的必要一步,赞扬了项目团队的执行力和跨社区协作。有人认为,这种“合理得不合理”的贡献方式很聪明,即使 Automattic(WordPress.com 的母公司)试图阻挠,也能为未来可能的分叉行动赢得社区支持。
然而,也有不少开发者表达了担忧和质疑。最大的担忧在于 WordPress 核心开发者是否会采取行动破坏 FAIR 的机制。不过,有 FAIR 项目的贡献者回应说,FAIR 的工作方式与许多商业插件类似,如果核心阻止 FAIR,也会破坏大量现有商业插件,这不太可能发生。
讨论中一个反复出现的主题是对 WordPress 及其领导层的强烈批评。许多人引用了过去一年中发生的各种争议事件,认为这些事件正是 FAIR 项目出现的根本原因。一些开发者直言 WordPress 已经是一个“死胡同”或“怪物”,其陈旧的架构和管理问题使得现代开发和部署实践变得异常困难。关于许可协议(GPL)的讨论也浮现出来,有人担心 FAIR 允许非 WordPress.org 仓库可能会削弱 GPLv2 在插件生态中的主导地位。
总的来说,这场讨论不仅关乎一个新项目,更折射出 WordPress 这个庞大而复杂的开源项目当前面临的深层危机和社区分裂。
程序员关于航空业的十大误解:现实世界的复杂性
FlightAware 工程博客的一篇文章《程序员关于航空业的十大误解》揭示了软件工程师在处理航空数据时,可能会想当然但实际上是错误的假设。文章延续了 Patrick McKenzie 关于名字的经典文章风格,列举了在构建飞行追踪引擎 Hyperfeed 过程中遇到的实际问题。
文章将这些误解分成了几个主要类别:
- 航班 (Flights): 误认为航班总是准时、只离开登机口一次、有固定时刻表、由唯一的航班号标识且不会改变等。现实中,航班可能延误超过一天、在非机场地点起降、持续数天,代码共享导致多航班号,甚至同一航空公司在同一时间有相同航班号的航班。
- 机场 (Airports): 误认为机场永不搬迁、登机口编号有统一规则、跑道只属于一个机场、机场总有两个(或三个)唯一的标识符。实际上,机场会搬迁、合并、改名,跑道可能跨越多个机场,甚至火星上的着陆点都有了 ICAO 代码。
- 航空公司 (Airlines): 误认为没有两家航空公司共享同一 IATA 代码、可以通过飞机外观判断运营航空公司等。实际上,代码共享、湿租(wet lease)等操作使得这些假设都不成立。
- 导航 (Navigation): 误认为航路点名称是唯一的、海拔高度定义是统一的、空管服务提供商的信息是准确的。现实是数据可能不准确、不一致,甚至飞机可能多次备降。
- 应答器和 ADS-B (Transponders and ADS-B): 误认为 ADS-B 消息只来自飞机、GPS 位置准确、消息总是包含正确的航班识别等。这些系统在现实中充满了错误、不准确、甚至恶意或意外的错误配置和数据。
文章强调了现实世界航空数据的混乱和复杂性,远非简单的结构化数据所能概括。
社区对这篇文章反响热烈,许多开发者分享了自己的经验和看法。一个核心讨论点围绕着唯一标识符展开。大家普遍认为,飞机并没有一个简单、时间不变的唯一标识符,注册号、尾号、应答器地址都可能改变。最接近永久标识符的是制造商、型号和序列号的组合,但这甚至被申请了专利,引发了关于这种显而易见的组合为何能获得专利的讨论。
另一个重要的讨论主题是关于这些“误解”列表的本质。许多开发者认为,这些列表揭示的并非程序员对航空业的无知,而是现实世界系统的固有混乱和不规范,以及软件必须将这些混乱映射到结构化规则时的挑战。这不仅仅是航空业的问题,而是所有试图建模复杂人类系统的软件都会遇到的问题,比如处理人名、时间和地址等。
此外,讨论中还涉及了数据库设计如何应对这些不规范性,有人提倡使用代理键而非自然键,或采用时间敏感的数据模型。大家还提供了具体的例子或趣闻,比如火星上的 Jezero 陨石坑确实因为“机智号”直升机着陆而获得了 ICAO 代码 JZRO,以及直升机或水上飞机经常在非机场地点起降等。
使用 Zig 进行低级优化:Comptime 的力量
alloc.dev 的一篇文章《使用 Zig 进行低级优化》探讨了程序优化的重要性,并着重介绍了 Zig 语言在这一领域的优势,特别是其 comptime
(编译时执行)特性。
文章指出,优化对于提升程序性能、降低成本和实现高级扩展至关重要。低级语言之所以通常更高效,除了缺乏高级语言的运行时开销外,更重要的是它们允许开发者向编译器清晰地表达“意图”。文章通过对比 JavaScript 和 Zig 实现数组最大值操作的代码,展示了 Zig 如何通过显式的类型、大小、对齐和别名信息,帮助编译器生成高度优化的、甚至向量化的汇编代码。
文章的核心在于介绍 Zig 的 comptime
特性,称其为 Zig 真正的优化“超能力”。comptime
允许在编译时执行常规 Zig 代码,主要用于代码生成和元编程,例如生成常量、实现泛型以及基于编译时已知数据进行优化。作者将 comptime
与传统宏和 C++ 的 constexpr
进行对比,认为 comptime
更无缝地融入语言,并且能够检查、反射和生成类型。文章以字符串比较为例,展示了如何使用 comptime
让编译器知道其中一个字符串是编译时常量,从而生成比通用运行时比较函数更优化的汇编代码。
社区对文章内容展开了热烈讨论。一些开发者对 Zig 的构建系统、跨平台编译能力和快速迭代速度表示赞赏,认为这些特性使其在游戏开发等领域具有吸引力。
一个主要的讨论点是 Zig 缺乏私有结构体字段。批评者认为这损害了模块化和长期可维护性,使得库作者难以在不破坏用户代码的情况下修改内部实现。支持者则认为,通过命名约定和文档可以清晰界定公共 API,或者可以使用不透明指针来强制隐藏实现。
关于 comptime
在优化中的作用也引发了辩论。一些开发者认为,文章中简单的字符串比较例子并不能充分证明 comptime
的独特优势,因为现代 C/C++ 编译器也能实现类似的优化。他们质疑 comptime
是否增加了不必要的复杂性。comptime
的支持者则强调其与语言的无缝集成、对跨平台编译的天然支持、以及在更复杂的算法级优化方面的强大能力,认为它是比 C 宏或 C++ 模板更优雅的解决方案。
克服拖延症:行动激发动力
IEEE Spectrum 的一篇文章《克服拖延症》探讨了许多科技界人士都面临的挑战:拖延症。文章作者 Rahul Pandey 分享了他个人与拖延症的斗争,并提出了一个核心观点:行动激发动力,而非反之。
作者认为,你不应该等待动力来袭才开始行动。相反,关键在于立即开始做一些事情,无论多么微小,只要它能推动你朝着目标前进。他以解决复杂 bug 为例:不要想着立即解决整个 bug,只需迈出微小的一步,比如添加一个日志语句来打印变量的值。这种小行动降低了开始所需的“启动能量”,从而启动一个积极的“飞轮效应”:你变得高效,感觉良好,这种感觉又会让你更高效。
社区对这篇文章展开了热烈讨论,许多开发者分享了自己的经验和策略。大量开发者强烈认同“行动激发动力”的原则,并分享了降低启动门槛的类似技巧。一个流行的方法是在一天结束时故意留下一个未完成的、甚至带有语法错误或失败测试的琐碎步骤,这样第二天就能有一个即时、简单的切入点来重新开始。
然而,讨论也带来了更细致的观点。一些开发者认为,拖延症并非总是坏事,也并非仅仅是缺乏动力。他们提出,有时拖延是大脑在发出更深层次的信号——也许任务本身确实无趣,或者个人过度劳累需要休息。对于经验丰富的工程师来说,在复杂问题上的拖延可能是一个必要的“酝酿”或“沉淀”期,让思维可视化潜在问题并设计解决方案。
讨论中一个反复出现的主题是拖延症与潜在问题(如恐惧、任务规模过大)或神经多样性(如 ADHD 和执行功能障碍)之间的联系。一些开发者指出,对于患有这些情况的人来说,简单的“去做”或分解任务的建议可能无效,甚至会适得其反。他们强调,在这些情况下,拖延并非道德缺陷,而是大脑运作方式的症状,需要更深层次的理解和个性化的应对策略。
其他实用的建议包括使用 AI 工具(如 LLM)生成初始草稿以获得动力,以及通过“准备”任务(如清理工作区)来降低启动能量。
为什么工业烟囱要建得那么高?
Practical Engineering 的一篇文章探讨了我们可能经常看到但很少深究的问题:为什么工业烟囱要建得那么高?文章指出,虽然我们理想中希望生产过程没有排放,但这在现实中很难实现。因此,工程师们的工作就是管理这些排放,尽量减少其对公众健康的影响。烟囱就是这种管理手段之一。
文章深入解释了烟囱之所以高大的几个关键原因。首先,历史上,高烟囱的主要作用是为了提高燃烧效率,通过“烟囱效应”增强空气流动。然而,随着时代发展和环保法规的出现,烟囱的主要功能转向了空气质量管理。现代工业设施通常会安装各种先进的排放控制系统来去除大部分污染物,但对于那些无法完全去除或需要进一步处理的污染物,高烟囱的作用就凸显出来了。文章强调,“稀释是解决污染的一种方法”,在局部尺度上,将污染物排放到更高的大气层,可以利用风和大气扩散将其稀释到对人体健康影响微乎其微的浓度。
文章详细阐述了烟囱效应如何帮助污染物上升得更高、更快,从而促进扩散。但设计一个烟囱远不止这么简单,工程师还需要考虑污染物离开烟囱后的行为,这涉及到复杂的空气化学和大气条件,如风速、风向、大气稳定性、地形和建筑物的影响,以及环境中已有的污染物浓度。为了确保排放不会导致任何地点、任何时间、任何条件下污染物浓度超过国家环境标准,工程师们需要使用复杂的模型软件进行模拟和预测。
社区对这篇文章展开了热烈讨论。许多读者对文章详细解释烟囱效应和大气扩散的复杂性表示赞赏,认为它将一个看似简单的问题讲得非常透彻。一些有工程背景的开发者证实了文章中提到的烟囱高度计算是环境工程或化工工程课程中的标准内容,其目的正是为了满足空气质量法规的要求。
关于烟囱高大的历史原因,大家也进行了讨论。有人最初认为高烟囱只是为了避免烟尘落在工厂附近,文章澄清了早期主要是为了提高燃烧效率,空气质量的改善是次要的,直到环保法规出现后才成为主要目的。
我读了 Cloudflare 所有由 Claude 生成的提交记录:AI 辅助编程的实践与思考
Max Mitchell 的一篇文章《我读了 Cloudflare 所有由 Claude 生成的提交记录》深入研究了 Cloudflare 开源的一个 OAuth 2.1 库,这个库的绝大部分代码是由 Anthropic 的 Claude 模型生成的。
这篇文章的核心在于,Cloudflare 在开发这个库时,采取了一个非常透明和有价值的做法:他们在 Git 提交信息中记录了用于生成代码的具体 Prompt(提示词)。作者通过阅读这些提交记录,得以一窥人类工程师与 AI 模型 Claude 之间真实的协作过程。
文章详细阐述了几个关键发现:
- 透明的开发记录: 将 Prompt 包含在提交信息中,使得 Git 历史不仅仅是代码变更的记录,更成为了人类意图和 AI 实现过程的“考古记录”。
- 协作模式: 作者观察到几种有效的协作模式,包括“通过示例 Prompt”和迭代式的反馈。AI 在生成文档方面表现出色,将这项繁琐的任务变得轻松。
- AI 的局限性: 尽管 AI 生成了大部分代码,但它并非完美。作者注意到 Claude 在处理代码结构调整、复杂的查找替换等方面遇到了困难。这表明人类的判断和干预在整个过程中至关重要。
- 实践启示: 对于使用 AI 编码工具的开发者,文章建议关注最终交付物,用示例来指导 AI;将 Prompt 视为版本控制的一部分;接受多轮 Prompt 迭代是常态;以及知道何时应该放弃 Prompting 转为手动修改。
- 对未来的思考: 作者提出了一个引人深思的设想:如果 Prompt 成为真正的“源代码”,我们是否可以只版本控制 Prompt,并在模型改进后重新生成整个代码库?
社区对这篇文章引发了热烈讨论,特别是关于“Prompt 即源代码”的设想,以及 AI 对开发者工作的影响。
关于“Prompt 即源代码”的争议,绝大多数开发者表示反对。核心理由是自然语言的模糊性和 LLM 的非确定性。他们认为,与编译器不同,LLM 即使使用相同的 Prompt 也可能生成不同的代码,这使得重现性、调试和审计变得极其困难甚至不可能。如果代码库无法确定性地重现,如何保证其安全性和稳定性?如何进行代码审查?少数开发者认为这个想法有潜力,但需要改进,例如 Prompt 应该与生成的代码一起提交,作为一种增强的文档或意图记录,而不是替代代码本身。
关于 AI 对开发者工作的影响,一种观点认为,AI 极大地提高了资深工程师的生产力,可能导致公司减少对初级工程师的需求。另一些人则认为,AI 可以成为初级开发者学习的强大工具,它比忙碌的资深同事更容易获取和提问。大家普遍认为,未来的开发者可能需要更强的 Prompting 能力和对 AI 生成代码的审查能力,这是一种技能的转变。
深入理解梯度噪声:从原理到 GPU 实现
pkh.me 的一篇文章《分享我对梯度噪声(gradient noise)的所有理解》深入探讨了梯度噪声的原理和实现,这是一种在计算机图形学、游戏开发和程序化艺术中广泛使用的技术,大家可能更熟悉它的一个具体实现——Perlin 噪声。作者的目标是提供一个更深入、更有意义的理解,从基础的 1D 版本开始,逐步扩展到更高维度,并特别关注了 GPU 上的实现,所有代码示例都使用了 WebGL2/GLSL。
文章首先介绍了梯度噪声的基础:一个确定性的、基于坐标的伪随机系统,需要一个哈希函数为任何整数坐标生成伪随机值。作者推荐了一个名为 lowbias32
的哈希函数变体,并展示了如何将其扩展到 2D 和 3D 输入。接着,文章介绍了“值噪声”(Value Noise),这是梯度噪声的一个简化版本,通过插值来生成连续信号。
核心部分是梯度噪声的解释。与值噪声不同,梯度噪声在每个格点上存储一个随机的梯度,在任意点计算噪声值时,需要计算该点到周围格点的向量,并与格点上的梯度向量进行点乘,然后对这些点乘结果进行插值。文章详细展示了 1D、2D 和 3D 的实现。在此基础上,文章介绍了分形布朗运动(Fractal Brownian Motion, fBm),这是一种通过叠加多个不同频率和振幅的噪声层来创建更复杂、更自然的纹理的技术。
文章的另一大重点是噪声的“导数”(Derivatives),它描述了信号的变化率,在很多应用中都非常有用,比如计算曲面的法线用于光照、模拟侵蚀效果。作者对比了数值导数和解析导数,并详细推导了平滑插值函数和多维插值函数的导数,展示了如何在噪声函数中集成导数计算。
社区对这篇文章的反馈非常积极。许多开发者都对文章的深度和清晰度表示赞赏,认为文章的插图极大地帮助了理解最终效果。关于文章中的动态插图,作者本人透露,这些插图实际上是直接在 WebGL2/GLSL 中实现的实时渲染,而不是预录制的动画,这个细节让开发者们更加印象深刻。
有开发者表达了对平滑噪声“过度使用”的看法,希望能有更多不同“风味”的平滑噪声。也有开发者提到自己过去在项目中也曾满足于“看起来够好就行”,没有深究背后的数学细节,这篇文章让他对噪声的复杂性有了新的认识,特别是导数和数值稳定性。
Railway 放弃 Nix,推出全新 Railpack:简化构建体验
Railway 近日宣布将放弃其基于 Nix 的构建系统 Nixpacks,转而推出全新的 Railpack。文章指出,尽管 Nixpacks 为 80% 的用户提供了良好的服务,但剩余的 20% 仍会遇到限制,这阻碍了 Railway 从 100 万用户扩展到 1 亿用户的目标。因此,他们需要一个重大的构建器升级。
文章详细阐述了放弃 Nix 的主要原因。首先是 Nix 的基于提交的版本管理方式,这使得支持特定补丁版本变得困难且难以维护。更新某个包到最新版本会导致所有其他包的版本也随之更新,这可能导致之前正常工作的构建突然失败。Railway 认为,用户不应该被迫理解 Nix 的内部机制。其次是镜像大小和缓存问题。Nixpacks 使用 Nix 引入依赖的方式常常导致巨大的镜像,且缓存控制有限。文章强调,问题不在于 Nix 本身,而在于他们使用 Nix 的方式——试图抽象掉 Nix 的核心特性根本行不通。
为了解决这些问题,Railway 构建了 Railpack。Railpack 采用了全新的架构,从 Rust 切换到 Go,以便更好地利用 BuildKit 库。Railpack 的亮点包括:更细粒度的版本控制(支持 major.minor.patch),显著减小的镜像大小(Node 镜像减小 38%,Python 减小 77%),以及通过直接与 BuildKit 交互实现的更优异的缓存控制。Railpack 使用 Mise 进行版本解析和包安装,允许锁定成功构建时的依赖版本,防止未来的默认版本更新导致构建失败。Railpack 目前处于 Beta 阶段,并已开源。
社区对 Railway 的决定展开了热烈讨论,观点多样。许多 Nix 爱好者和有经验的用户对 Railway 提出的问题表示质疑,认为这些问题并非 Nix 的固有缺陷,而是 Railway 在 Nixpacks 中对 Nix 的特定使用方式导致的。他们指出,Nix 本身非常灵活,通过使用 Overlays、Flakes 或 nix2container
等工具,完全可以实现对特定版本(包括旧版本或补丁版本)的精确控制和管理,并构建分层的 Docker 镜像,从而减小最终镜像大小并改善缓存效率。
另一些开发者则从更宏观的角度分析了 Railway 的决策。有人认为,这反映了 Nix 学习曲线陡峭、复杂性高的问题。即使技术上可行,但如果团队缺乏足够的 Nix 专家,或者维护成本过高,转向更易于理解和控制的技术栈是合理的商业选择。这种情况下,问题可能更多在于团队技能文化或项目管理,而非 Nix 本身的优劣。
CDImage:在光盘数据面上“烧录”可见图片
一个名为 CDImage 的有趣项目近日引起了社区的关注。它是一个工具,能够让你在普通的可刻录光盘(CD-R 或 CD-RW)的数据表面上“烧录”出肉眼可见的图片。
这个工具的核心思想是利用 CD 刻录机激光头在光盘表面制造微小凹坑(pits)和平面(lands)来存储数据的方式。通过精心计算和排列这些凹坑和平面,CDImage 生成一个特殊的音频轨道文件。当你使用标准的 CD 刻录软件将这个文件作为音频 CD 刻录到光盘上时,激光头按照文件中的模式进行刻录,最终在光盘的数据层形成一个可见的灰度图像。
项目的作者提到,这个想法并非首创,灵感来源于大约 15 年前 Instructables 上的一个项目以及另一个名为 CD PAINT 的俄语项目。作者在这些项目的基础上,开发了这个带有图形界面的工具。他指出,不同品牌和型号的光盘,其几何参数存在细微差异,而这种差异对数据存储影响不大,却对图像的精确计算至关重要,导致校准非常困难。最近,作者重新发现了这段代码,并将其移植到了现代的 Qt6 平台,作为对 CD 时代的致敬而分享出来。
社区对这个项目表现出了浓厚的兴趣和怀旧情绪。许多人立刻联想到了过去的光盘刻录技术,特别是雅马哈的 DiscT@2 和惠普的 LightScribe。开发者指出,DiscT@2 可以在 CD 的未使用区域刻录文字和图像,而 LightScribe 则是在光盘的特殊标签面上用激光刻录。CDImage 的独特之处在于它直接在 数据面 上通过数据凹坑来形成图像,这与前两者是不同的技术路径。
关于校准的难度,有开发者证实了作者的说法,分享了自己尝试类似项目时,需要进行多达 50 次实验才能获得尚可的结果。讨论也延伸到了这种技术的潜在应用,有人猜测是否可以实现极高的细节,甚至像衍射光栅一样产生光学效果,或者烧录出全息图像。
此外,讨论中还出现了一个关于光盘作为长期存储介质的有趣分支讨论。一些人认为光盘(特别是蓝光或 M-Disc)是可靠的长期存档方式,而另一些人则分享了自己刻录的 CD/DVD 随着时间推移无法读取的经历,认为光盘也会降解,强调了定期检查和重新刻录备份的重要性。