惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
Last Week in AI
Last Week in AI
J
Java Code Geeks
V
Visual Studio Blog
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
宝玉的分享
宝玉的分享
博客园 - Franky
博客园 - 【当耐特】
Jina AI
Jina AI
月光博客
月光博客
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
H
Heimdal Security Blog
Y
Y Combinator Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News - Newest:
Hacker News - Newest: "LLM"
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
MongoDB | Blog
MongoDB | Blog
Forbes - Security
Forbes - Security
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
L
LINUX DO - 最新话题
M
MIT News - Artificial intelligence
Schneier on Security
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Schneier on Security
罗磊的独立博客
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
C
Check Point Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
AI
AI
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
T
The Blog of Author Tim Ferriss

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 在Linux上限制儿童使用电脑 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
读:20条软件工程定律 - 暗无天日
2026-05-17 · via 暗无天日

Milan 在他的newsletter里整理了 20 条软件工程定律。这些定律有些来自 1960 年代,到现在还管用。它们讲的是人在压力下一起造东西时会发生什么,不教你怎么做,只告诉你已经发生了什么、什么行不通。下面逐条解读。

Gall 定律

一个能跑的复杂系统,一定是从一个能跑的简单系统演变来的。

系统在纸面上看着没问题,真正的问题要等真实用户用起来才会暴露。所以每个能跑的复杂系统都是一步步长出来的。想一步到位造出完美系统,基本都失败了。从零重写的系统经常翻车也是这个原因:大功能倒是照搬了,但老系统在多年运行中积累的那些不起眼的小设计(比如某个特殊的缓存策略、某条异常处理路径),没人记得也没人照搬,而它们恰恰是让系统跑起来的关键。

Instagram 前身叫 Burbn,集合了签到、游戏、拍照分享。创始人砍掉所有功能只留照片分享,变成了现在的 Instagram。Google Wave 反其道行之,聊天、邮件、论坛、文档编辑一起上,没人说得清它到底是干嘛的,15 个月就死了。

KISS 原则

保持简单。超出必要的都是负担。

能 50 行脚本解决的问题,别搞 500 行的复杂方案。每多写一行代码就多一分引入 bug 的风险。简单的设计好维护:新人上手快,bug 好找,改一处不会牵动一片。别整那些花里胡哨的代码技巧,也别替未来还不存在的问题预埋复杂度。

有个创业公司需要功能开关(feature flag,不改代码就能开关某个功能的配置项),于是建了一个独立微服务:自己的数据库、缓存、管理界面、WebSocket 通知、A/B 测试支持,花了大量时间,出了问题还很难查。其实一个 JSON 配置文件就够了,一个下午搞定。

Conway 定律

组织的沟通结构会镜像到系统架构里。

你的应用架构基本等同于组织架构图。四个团队做项目,大概率产出四个模块。前端、后端、数据各干各的,做出来的东西也拼不到一块。光重写系统不调组织架构,换汤不换药。

反过来也成立:先选好想要的架构,再按架构组建团队。Amazon 在 2000 年代就把系统拆成小服务、每个服务一个小团队,系统和组织一起变了。这叫逆向 Conway 播种(Inverse Conway's Maneuver)。

三人的团队几乎总是出单体应用,因为拆分的成本比维持整体的成本还高。

Hyrum 定律

用户够多之后,你 API 的每一个可观测行为都会变成某人的依赖,不管接口文档怎么写。

接口文档写着不算数,系统实际表现出来的才算。响应时间、错误信息的文字、JSON 字段顺序、哈希的精确字节,这些你从没觉得重要的细节,总有人依赖着。

SimCity 有个 use-after-free 的 bug,在 Windows 3.x 上没事,因为内存压根不被回收。到了 Windows 95 真正回收内存了,SimCity 就崩。微软专门在 Windows 95 里加了一个特殊内存分配模式,只在 SimCity 运行时激活,让这个 bug 继续工作。

浏览器也是这么干的。Web 开发者依赖的每一个怪癖都变成了平台的一部分,浏览器改不了,改了就崩半个互联网。

CAP 定理

分布式系统只能同时保证一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)中的两个。

网络迟早会断。一旦两个节点联系不上(这就是分区),你要么停写保数据一致,要么继续服务但允许副本间数据不一致。每个分布式数据库都做了选择,只是多数不会主动告诉你。

MongoDB 选了 consistency:分区时某些副本拒绝写入,等整个系统恢复。Cassandra 则选了 availability:副本数据不一致时照样响应查询,之后再修。谁都没错,取舍不同罢了。

Zawinski 定律

每个程序都会膨胀到能收发邮件为止。做不到的会被能做到的替代。

这是 Netscape 早期工程师 Jamie Zawinski 在 1990 年代说的玩笑话。那个年代浏览器、编辑器、日历都在加邮件功能,好像不收发邮件就不完整。说白了就是每个程序都会无限制地膨胀,直到塞满所有能想到的功能。工具做好了、用户喜欢,产品方就想让人留在平台上,于是不断往里塞东西。时间一长,工具变得又慢又臃肿,然后新的竞争者带着精简版出现。

Netscape 从浏览器膨胀成套装(邮件、新闻、网页编辑器),Firefox 来收拾残局,精简后火了,然后又加插件和开发工具链。Slack 诞生时说要杀死邮件,现在有语音、视频、机器人、应用商店。

Brooks 定律

给延期的项目加人,只会让它更延期。

软件工作拆不了。新人进来要上手,老手得停下手头的活来带。项目已经延期了,加人只会添乱。Brooks 说得好:九个女人也不能一个月生出孩子。

有人带过一个八人团队,一直延期。第一反应是招两个人。结果招人期间走了两个,团队变成六个人,沟通反而顺畅了,产出反而更高了。

Ringelmann 效应

团队越大,人均产出越低。

很多人一起拉绳子,每个人反而不用那么大力。协作摩擦是一方面,"总觉得别人会做"是另一方面。

GitHub 做过大规模统计:2-5 人团队的工程师平均每月写 1850 行代码,10 人团队降到 1200 行,50 人以上只剩 450 行。人均掉了 75%。小团队出活快,Amazon 的"两个披萨"规则也是这个道理。

Price 定律

一半的工作是由人数的平方根完成的。

100 人的团队,大约 10 个人干了一半的重要工作。16 人的团队,4 个人承担主要产出。所有创意领域都这样。核心的人走了,团队产出能力大幅缩水。剩下的人也没闲着,干的是让团队运转起来的支撑活。

Musk 接管 Twitter 后裁员约 50%,网站照样跑。Price 定律提前预测到了。但裁掉的是那些不怎么显眼却不可或缺的能力:内容审核团队没了,SRE(站点可靠性工程)人手不够了,出了故障没人能深入排查根因,只能头疼医头。核心人员撑住了日常运转,但碰到下一个复杂问题就抓瞎了。Twitter 后来悄悄请回了一些被裁的人。

Dunning-Kruger 效应

你对一件事知道得越少,越自信。

做一件事需要的本事,和判断自己做得好不好的本事,是同一件本事。不会的人看不出自己哪做错了,觉得自己挺厉害。会的人看得到自己所有的不足,觉得自己还不够好。

新工程师被问到工期,张口就来一个精确数字。老工程师给的是范围,口头禅是"看情况"。新人不是在瞎说,他们只是还不知道自己不知道什么。

刚接触新技术的人总是特别兴奋。AI 领域正在上演这一幕:喊"AI 什么都能做"最响的,通常不是天天在用 AI 的人。

Hofstadter 定律

做事总是比你预期的久,就算你已经考虑了 Hofstadter 定律也一样。

你估 4 周,想起自己总是太乐观,翻倍到 8 周,最后花了 16 周。下次学乖了估 16 周,结果花了 32 周,因为总有你不知道的意外冒出来。

柏林勃兰登堡机场就是个典型。软件集成涉及 75000 个传感器和 50000 个灯具控制,原计划 18 个月完工,后来意识到不可能,延长到 30 个月。最终花了 7 年,造价 70 亿欧元,超支 2.5 倍,晚了 9 年。

Parkinson 定律

工作会膨胀到填满分配给它的时间。

给开发者两周做一个两天能完成的任务,他会花两周。不是说他想偷懒,而是在两周里会做计划、试方案、加没人要求的花哨细节(gold-plating)。截止日期就定一天,他大概率一天能交。

Goodhart 定律

一个指标一旦变成考核目标,就不再是好指标了。

拿 bug 数、事故数、测试覆盖率、团队速度来考核人,大家就会想办法让数字好看,而不是把事做好。数字上去了,质量没动。

2000 年代初有团队按代码行数发奖金,后来有人按 PR 数考核。结果开发者开始复制粘贴而不是提取共享逻辑,有人几乎每次提交都开一个 PR。现在流行按 AI token 消耗量(tokenmaxxing)来衡量,消耗越多越"高效"。

Gilb 定律

任何你需要量化的东西,总能找到某种方式来测量,而且比不量强。

Gilb 定律和 Goodhart 定律一体两面。Goodhart 说指标被滥用会失真,Gilb 说没指标更糟。重要的东西就该想办法去量,量不了就没法优化。DORA 指标里的部署频率和变更交付时间就是开发生产力的可用度量,不完美,但比代码行数和 token 消耗靠谱。

Knuth 的优化原则

过早优化是万恶之源。

性能优化经常做早了、做错了地方。团队优化了永远不会成为热点的代码路径,引入了用不上的复杂度,花时间解决根本不会遇到的规模问题。先写出能跑的代码,再查性能。瓶颈在哪,就改哪。没有就继续往前走。

有人在创业公司花了大量时间搭 Kubernetes,为了扛百万用户。问题是他连 10 个用户都还没有。基础设施做好了,产品功能还没做完。

Amdahl 定律

并行加速的上限取决于串行部分的比例。

10% 的工作必须串行做,那无论多少台机器,最多快 10 倍。50% 必须串行,最多快 2 倍。

人也一样。一个审批组要过问每个技术决策,不管你有多少工程师,速度都卡在审批组。加人只是让排队等着审批的队伍更长。

Web 流量水平扩展,加应用服务器就行,直到每个请求都要打同一个共享数据库或认证服务。之后再加机器没用。

AI 让编码变快了,但思考、检查、修错、协作这些步骤没法并行。所以有人效率提升 10 倍,有人只有 1.2 倍。

Murphy 定律

可能出错的事一定会出错。

空指针、竞态条件、网络断开,用户量够大的时候,一定会在最糟糕的时刻出现。所以代码要写防御性的:检查空值、处理异常、验证输入。运维那边也准备好:监控、回滚方案、应急预案,都不能少。

2024 年 7 月 19 日,CrowdStrike 改了 Falcon Sensor 的配置,850 万台 Windows 蓝屏。修复得人逐台登录,因为机器起不来,远程不了。偏偏那边是周五上午,而且IT还 不在岗。航空公司、医院、银行全中招。能出错的都出了。

Postel 定律

发送要保守,接收要宽容。

自己返回数据时,格式严格按规范来。但收别人的数据时,即使格式不标准只要能安全解读就别直接丢。

浏览器就是活例子。网上大部分 HTML 写得都不规范,但浏览器照样渲染。严格按规范来的话,半个互联网打不开。

但太宽容也有代价:所有人都容忍乱七八糟的输入,问题永远不会被修正,只会越积越多。安全敏感的代码里,容忍输入等于给攻击者开门。宽容不等于放任,得有判断。

Sturgeon 定律

90% 的东西都是垃圾。

造的大部分东西没人用,写的大部分代码质量不行,启动的大部分项目没能交付预期价值。这没什么,创造的常态就是这样。假装一切都好、给每个项目同样的资源,只会把事情搞复杂。要紧的是找到那 10%,砍掉其余的。

WordPress 插件目录大约有 57000 个插件,超过 34000 个两年没更新过,将近 19% 零安装。少数维护良好的插件撑起了公开网站 40% 以上的份额。

Cunningham 定律

在网上得到正确答案最快的方法,是贴一个错误的答案。

论坛提问经常没人理。贴一个明显错误的东西,马上就有人跳出来纠正。路过问题可能懒得停,看到错误忍不住要改。遇到难题别问"该怎么做",提一个你明知道不太行的方案,正确答案可能不请自来。

Wiki 和后来的 Wikipedia 赌的就是这个:人们改错的速度远快于从零写新文章。事实证明这个赌赌对了,Wikipedia 就是靠这个机制撑起来的。

这些定律之间的关系

20 条不用全记住,前五六条能解决大部分问题,剩下的等新问题冒出来再查。关键是要知道什么时候哪条适用。

定律之间会打架。Knuth 说别过早优化,Amdahl 说找到瓶颈修掉它。两条都对,但适用时机不同:项目早期听 Knuth,性能真出问题了听 Amdahl。

还有一点:这是作者个人的清单,他还出了本书涵盖了 56 条定律。你自己的清单会不一样。哪些定律让你吃过亏,哪些对你就是最重要的。下次遇到项目事故、团队重组、系统重写,花一分钟记下来:哪条定律帮了你?哪条给了教训?记久了,你自己的清单比谁的都好用。

框架、平台、部署模式从 Brooks 1975 年写书到现在变了很多,但这些定律没变,因为人性从不改变。