复杂度三症状
Ousterhout 把复杂度拆成认知负载、变更放大、未知的未知。第三项最危险,因为你甚至不知道边界在哪里。
SYS-DISCIPLINE / CONTROL SURFACE / REV 2
把工程判断拆成九个可巡检模块:从复杂度源头到 Agent runtime,每个模块都要有输入、约束、验证和可追踪来源。
Foundation
软件工程的主战场不是语法,而是人脑有限。好设计持续降低认知负载、变更放大和未知的未知。
Ousterhout 把复杂度拆成认知负载、变更放大、未知的未知。第三项最危险,因为你甚至不知道边界在哪里。
战术编程追求当下最快通过;战略编程愿意多花 10-20% 时间换结构复利。
界面简单、实现复杂才叫抽象。浅模块只是把同样复杂的东西又包了一层。
重要 design 至少做两版方案再选;如果一个东西难注释,通常是设计还没想清楚。
复杂度不是一次事故,而是无数小妥协复利出来的。战略编程是一种持续纪律。
Spec Engineering
写 spec 不是为了文档好看,而是在代码还没产生沉没成本时,把设计做完。
用自然语言设计产品,只需要几分钟就能删除、重写、比较方案;等代码写出来再改,成本会变成几周。
声明式 desired state、spec/status 分离、conditions、opaque resourceVersion 和 lists-over-maps 是工业 API 的硬约束。
deploy 维度也需要 spec:配置进 env,服务视为 attached resources,日志作为 event streams,进程无状态。
70 行函数、100 列、零依赖、命名按显著性递减,把“怎么写代码”变成可执行契约。
Spec 的价值是把延后的决策提前,把口头默契转成可审计的工程输入。
Code Discipline
代码被读的次数远多于被写。所有多花时间写的纪律,最终都是为了让未来读者省时间。
TigerStyle 认为 assert 不是 debug 工具,而是 mental model 的契约。每个函数平均至少两条断言。
既断言“这是真的”,也断言“这不可能”。边界穿越处最容易藏 bug。
不缩写、带单位、显著性递减,例如 latency_ms_max,让变量排序后自然对齐。
避免递归,循环必须可证有界,复合条件拆开,所有错误必须处理。
可读性不是审美偏好,而是系统长期演进的生存条件。
Testing
测试不是证明正确,而是把你不知道的状态空间系统化地挖出来检视。
155.8 KSLOC 核心对应 92,053 KSLOC 测试脚本,约 1:590。真正值得学的是多探针结构。
statement 最弱,branch 更强,MC/DC 要证明每个条件能独立影响结果。
OOM、I/O 错误、断电都可以被人为注入,让最差路径成为日常测试输入。
决定性模拟测试让事件顺序、网络延迟、崩溃都可重放;bug 出现后必须能复现。
你不能预见未知未知,但可以构造系统化探针逼它们现身。
API Contract
分布式系统里,请求可能丢失、重复、乱序。好 API 用契约消除不确定性,而不是靠希望。
Kubernetes 用 resourceVersion 做读改写一致性;客户端必须把它当不透明字符串。
状态不应塞进单一 phase enum,而应拆成可叠加、可演化的条件数组。
POST 这类副作用操作必须让客户端传唯一 key,服务端按 key 缓存结果。
指数退避避免持续砸服务,jitter 避免所有客户端同时重试造成羊群效应。
幂等性把“做了没做”的不确定性,从用户心智中移到系统契约里。
Schema Evolution
改一张活表是在同时和昨天的写者、读者、数据与回滚路径谈判。
先 dual-write + backfill,再切 read path,再切 write path,最后删除旧数据。
永远不要一次同时改读和写;每个 phase 都要能回退。
dual-read 时同时跑新旧实现并比对差异,不一致就告警。
Kubernetes controller 看最新 desired state 收敛,不依赖每个中间 edge 都被观察到。
在线迁移不是一次发布,而是一组可观测、可回退、可逐步收敛的状态机。
Agent Design
Workflow 的控制流由代码定,Agent 的下一步由 LLM 决定。复杂度每升一档都要有测量证明。
从 augmented LLM 到 prompt chaining、routing、parallelization、orchestrator-workers、evaluator-optimizer,再到 autonomous agent。
Anthropic 的核心建议是从最简单可行方案开始,只在结果证明需要时增加复杂度。
给 agent 的 tool 就像给人的 UI。参数、边界、例子、重叠关系都要设计。
避免要求模型数行号、嵌套 JSON 转义或在一堆功能重叠的工具里猜。
Agent 不是魔法,是控制流、工具契约和环境反馈共同组成的新运行时。
AI Coding Practice
不是把代码外包给 LLM,而是和它协作压缩你的意图。人写约束和签名,模型填实现,人保留判断权。
Context engineering 的目标是找到最小但足够高信号的 token 集,而不是把所有材料塞进去。
保留路径、查询、链接,让 agent 用工具按需拉上下文,避免上下文腐烂。
System prompt 要足够具体能指导行为,又足够灵活让模型自己找路径。
tree-sitter 抽取符号和签名,按相关度排序,给模型结构而非整仓实现。
LLM 放大的是已有专业能力;不能把“它真的能跑”这件事外包给机器。
Meta Principles
九个方向最后汇成同一件事:把靠记性、靠默契、靠聪明,换成靠系统、工具和契约。
简单不是第一稿,而是多轮约束、比较和删除后的结果。
硬限制不是束缚,而是迫使设计者发现更稳的结构。
可选/必填、Idempotency-Key、assert 正负空间,都在拒绝“你应该懂”。
AI 时代的工程纪律多了新维度:spec、tool 设计、context 工程都成为 agent runtime 的一部分。
大神和普通工程师的差距,不在于谁更聪明,而在于谁更不依赖聪明。
REFERENCE BUS / VERIFIED 16
Workflow vs agent 分类法,模式梯度,ACI 概念,start simple 原则。
最小高信号 token 集、just-in-time retrieval、compaction、structured notes、sub-agents、right altitude。
NASA Power of Ten、assertion 密度、命名学、控制流硬规则、静态内存。
复杂度三症状、战术 vs 战略、深模块、design twice、注释即设计。
Spec 强制设计、沟通只发生一次、排期前置、代码沉没成本。
四套测试、MC/DC、anomaly testing、mutation testing、测试/代码 1:590。
决定性模拟测试、FoundationDB 经验、50x productivity 论点。
SaaS app 的 12 条 deploy 契约:config、backing services、logs、process model。
声明式 API、spec/status、conditions、resourceVersion、lists over maps。
dual-write、backfill、dual-read、Scientist、增量切换写路径、删除旧数据。
Idempotency-Key、指数退避、jitter、thundering herd 防护。
LLM expectations、training cutoff、context is king、测试责任、专家能力放大。
tree-sitter、PageRank、repo map、结构性压缩优于截断。
数据集作为 source code,训练把目标函数编译成神经网络权重。
把条件上推、循环下沉,集中分支并让批处理成为基础形态。
198 个生产故障分析,92% 灾难性故障来自非致命错误处理不当。