pragmatic-programmer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseThe Pragmatic Programmer Framework
《程序员修炼之道》框架
A systems-level approach to software craftsmanship from Hunt & Thomas' "The Pragmatic Programmer" (20th Anniversary Edition). Apply these principles when designing systems, reviewing architecture, writing code, or advising on engineering culture. This framework addresses the meta-level: how to think about software, not just how to write it.
这是基于Hunt & Thomas所著《程序员修炼之道》(20周年纪念版)提出的系统级软件工艺方法。在设计系统、评审架构、编写代码或指导工程文化时,均可应用这些原则。该框架聚焦元层面:即如何思考软件,而非仅关注如何编写代码。
Core Principle
核心原则
Care about your craft. Software development is a craft that demands continuous learning, disciplined practice, and personal responsibility. Pragmatic programmers think beyond the immediate problem -- they consider context, trade-offs, and long-term consequences of every technical decision.
The foundation: Great software comes from great habits. A pragmatic programmer maintains a broad knowledge portfolio, communicates clearly, avoids duplication ruthlessly, keeps components orthogonal, and treats every line of code as a living asset that must earn its place. The goal is not perfection -- it is building systems that are easy to change, easy to understand, and easy to trust.
重视你的手艺。 软件开发是一门需要持续学习、严谨实践和个人责任感的手艺。务实的程序员会超越眼前的问题——他们会考虑每个技术决策的背景、权衡因素和长期影响。
基础: 优秀的软件源于良好的习惯。务实的程序员会维护广泛的知识体系、清晰沟通、坚决避免重复、保持组件正交性,并将每一行代码视为必须证明其存在价值的鲜活资产。目标并非完美——而是构建易于变更、易于理解且值得信赖的系统。
Scoring
评分标准
Goal: 10/10. When reviewing or creating software designs, architecture, or code, rate it 0-10 based on adherence to the principles below. A 10/10 means full alignment with all guidelines; lower scores indicate gaps to address. Always provide the current score and specific improvements needed to reach 10/10.
目标:10/10分。 在评审或创建软件设计、架构或代码时,根据对以下原则的遵守程度从0-10分进行评级。10分表示完全符合所有准则;分数越低则说明存在需要解决的差距。需始终提供当前分数以及达到10分所需的具体改进措施。
The Pragmatic Programmer Framework
《程序员修炼之道》框架
Seven meta-principles for building software that lasts:
构建持久软件的七大元原则:
1. DRY (Don't Repeat Yourself)
1. DRY(Don't Repeat Yourself,不要重复自己)
Core concept: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. DRY is about knowledge, not code -- duplicated logic, business rules, or configuration are far more dangerous than duplicated syntax.
Why it works: When knowledge is duplicated, changes must be made in multiple places. Eventually one gets missed, introducing inconsistency. DRY reduces the surface area for bugs and makes systems easier to change.
Key insights:
- DRY applies to knowledge and intent, not textual similarity -- two identical code blocks serving different business rules are NOT duplication
- Four types of duplication: imposed (environment forces it), inadvertent (developers don't realize), impatient (too lazy to abstract), inter-developer (multiple people duplicate)
- Code comments that restate the code violate DRY -- comments should explain why, not what
- Database schemas, API specs, and documentation are all sources of duplication if not generated from a single source
- The opposite of DRY is WET: "Write Everything Twice" or "We Enjoy Typing"
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Config values | Single source of truth | Define DB connection in one env file, reference everywhere |
| Validation rules | Shared schema | Use JSON Schema or Zod schema for both client and server validation |
| API contracts | Generate from spec | OpenAPI spec generates types, docs, and client code |
| Business logic | Domain module | Tax calculation in one module, not scattered across controllers |
| Database schema | Migration-driven | Schema defined in migrations, ORM models generated from DB |
See: references/dry-orthogonality.md
核心概念: 系统中的每一项知识都必须有单一、明确且权威的表示。DRY关注的是知识,而非代码——重复的逻辑、业务规则或配置比重复的语法危险得多。
为何有效: 当知识存在重复时,变更必须在多个地方进行。最终总会有一处被遗漏,导致不一致性。DRY减少了bug的产生范围,让系统更易于变更。
关键见解:
- DRY适用于知识和意图,而非文本相似性——两个服务于不同业务规则的相同代码块不属于重复
- 四种重复类型:强制型(环境所迫)、无意型(开发者未意识到)、急躁型(懒得抽象)、跨开发者型(多人重复编写)
- 重述代码的注释违反DRY原则——注释应解释「为什么」,而非「是什么」
- 数据库 schema、API 规范和文档如果不是从单一源生成,都会成为重复的来源
- DRY的对立面是WET:「Write Everything Twice(重复编写所有内容)」或「We Enjoy Typing(我们喜欢打字)」
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 配置值 | 单一可信源 | 在一个环境文件中定义数据库连接信息,在所有地方引用 |
| 验证规则 | 共享 schema | 使用JSON Schema或Zod schema同时用于客户端和服务端验证 |
| API 契约 | 从规范生成 | OpenAPI 规范用于生成类型、文档和客户端代码 |
| 业务逻辑 | 领域模块 | 税务计算逻辑集中在一个模块中,而非分散在各个控制器 |
| 数据库 schema | 迁移驱动 | schema在迁移中定义,ORM模型从数据库生成 |
参考:references/dry-orthogonality.md
2. Orthogonality
2. 正交性
Core concept: Two components are orthogonal if changes in one do not affect the other. Design systems where components are self-contained, independent, and have a single, well-defined purpose.
Why it works: Orthogonal systems are easier to test, easier to change, and produce fewer side effects. When you change the database layer, the UI should not break. When you change the auth provider, the business logic should not care.
Key insights:
- Ask: "If I dramatically change the requirements behind a particular function, how many modules are affected?" The answer should be one
- Eliminate effects between unrelated things -- a logging change should never break billing
- Layered architectures promote orthogonality: presentation, domain logic, data access
- Avoid global data -- every consumer of global state is coupled to it
- Toolkits and libraries that force you to inherit from framework classes reduce orthogonality
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Architecture | Layered separation | Controller -> Service -> Repository, each replaceable |
| Dependencies | Dependency injection | Pass a |
| Testing | Isolated unit tests | Test business logic without database, network, or filesystem |
| Configuration | Environment-driven | Feature flags in config, not |
| Deployment | Independent services | Deploy auth service without redeploying payment service |
See: references/dry-orthogonality.md
核心概念: 若两个组件的变更互不影响,则它们是正交的。设计系统时应让组件具备自包含、独立且单一明确的用途。
为何有效: 正交系统更易于测试、变更,且产生的副作用更少。当你修改数据库层时,UI不应崩溃;当你更换认证提供商时,业务逻辑不应受到影响。
关键见解:
- 自问:「如果我大幅改变某个功能的需求,会影响多少个模块?」答案应该是1个
- 消除无关事物之间的影响——日志变更绝不应该破坏计费功能
- 分层架构有助于实现正交性:表现层、领域逻辑层、数据访问层
- 避免全局数据——每个全局状态的使用者都会与其耦合
- 强制要求继承框架类的工具包和库会降低正交性
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 架构 | 分层分离 | 控制器 -> 服务 -> 仓库,每个层均可替换 |
| 依赖 | 依赖注入 | 传递 |
| 测试 | 独立单元测试 | 在不依赖数据库、网络或文件系统的情况下测试业务逻辑 |
| 配置 | 环境驱动 | 功能标志在配置中设置,而非业务逻辑中的 |
| 部署 | 独立服务 | 部署认证服务时无需重新部署支付服务 |
参考:references/dry-orthogonality.md
3. Tracer Bullets and Prototypes
3. 追踪代码与原型
Core concept: Tracer bullets are end-to-end implementations that connect all layers of the system with minimal functionality. Unlike prototypes (which are throwaway), tracer bullet code is production code -- thin but real.
Why it works: Tracer bullets give immediate feedback. You see what the system looks like end-to-end before investing in filling out every feature. Users can see something real, developers have a framework to build on, and integration issues surface early.
Key insights:
- Tracer bullet: thin but complete path through the system (UI -> API -> DB) -- you keep it
- Prototype: focused exploration of a single risky aspect -- you throw it away
- Tracer bullets work when you're "shooting in the dark" -- requirements are vague, architecture is unproven
- If a tracer misses, adjust and fire again -- the cost of iteration is low
- Prototypes should be clearly labeled as throwaway -- never let a prototype become production code
Code applications:
| Context | Pattern | Example |
|---|---|---|
| New project | Vertical slice | Build one feature end-to-end: button -> API -> DB -> response |
| Uncertain tech | Spike prototype | Test if WebSocket performance is sufficient before committing |
| Framework eval | Tracer through stack | Build login flow through the full framework before choosing it |
| Microservice | Walking skeleton | Deploy a hello-world service through the full CI/CD pipeline |
| Data pipeline | End-to-end flow | One record from ingestion through transformation to output |
See: references/tracer-bullets.md
核心概念: 追踪代码是连接系统所有层级的端到端实现,功能极简。与原型(可丢弃)不同,追踪代码是生产代码——虽精简但真实可用。
为何有效: 追踪代码能提供即时反馈。在投入大量精力完善所有功能之前,你就能看到系统的端到端效果。用户能看到真实的产品,开发者有了构建的框架,集成问题也能提前暴露。
关键见解:
- 追踪代码:贯穿系统的精简但完整路径(UI -> API -> 数据库)——会被保留下来
- 原型:聚焦探索单一风险点——会被丢弃
- 当你「在黑暗中摸索」时(需求模糊、架构未经验证),追踪代码非常有用
- 如果一次追踪未达预期,调整后再尝试——迭代成本很低
- 原型应明确标记为可丢弃——绝不能让原型成为生产代码
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 新项目 | 垂直切片 | 端到端构建一个功能:按钮 -> API -> 数据库 -> 响应 |
| 不确定技术 | 探索型原型 | 在投入之前测试WebSocket性能是否达标 |
| 框架评估 | 全栈追踪 | 在选择框架之前,通过完整框架构建登录流程 |
| 微服务 | 行走骨架 | 通过完整CI/CD管道部署一个hello-world服务 |
| 数据管道 | 端到端流程 | 一条记录从 ingestion 到转换再到输出的完整流程 |
参考:references/tracer-bullets.md
4. Design by Contract and Assertive Programming
4. 契约式设计与断言式编程
Core concept: Define and enforce the rights and responsibilities of software modules through preconditions (what must be true before), postconditions (what is guaranteed after), and class invariants (what is always true). When a contract is violated, fail immediately and loudly.
Why it works: Contracts make assumptions explicit. Instead of silently corrupting data or limping along in an invalid state, the system crashes at the point of the problem -- making bugs visible and traceable. Dead programs tell no lies.
Key insights:
- Preconditions: caller's responsibility -- "I accept only positive integers"
- Postconditions: routine's guarantee -- "I will return a sorted list"
- Invariants: always true -- "Account balance never goes negative"
- Crash early: a dead program does far less damage than a crippled one
- Use assertions for things that should never happen; use error handling for things that might
- In dynamic languages, implement contracts through runtime checks and guard clauses
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Function entry | Precondition guard | |
| Function exit | Postcondition check | Verify returned list is sorted before returning |
| Class state | Invariant validation | |
| API boundary | Schema validation | Validate request body against schema before processing |
| Data pipeline | Stage assertions | Assert row count after ETL transform matches expectation |
See: references/contracts-assertions.md
核心概念: 通过前置条件(执行前必须满足的条件)、后置条件(执行后保证满足的条件)和类不变量(始终满足的条件)来定义并强制执行软件模块的权利与责任。当契约被违反时,立即且明确地终止程序。
为何有效: 契约让假设变得明确。系统不会默默损坏数据或在无效状态下勉强运行,而是在问题发生点崩溃——让bug可见且可追踪。崩溃的程序不会说谎。
关键见解:
- 前置条件:调用方的责任——「我只接受正整数」
- 后置条件:程序的保证——「我会返回一个排序后的列表」
- 不变量:始终成立——「账户余额永远不会为负」
- 尽早崩溃:崩溃的程序造成的损害远小于瘫痪的程序
- 断言用于处理绝不可能发生的情况;错误处理用于处理可能发生的情况
- 在动态语言中,通过运行时检查和守卫子句实现契约
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 函数入口 | 前置条件守卫 | 函数开始处使用 |
| 函数出口 | 后置条件检查 | 返回前验证返回的列表已排序 |
| 类状态 | 不变量验证 | 每次状态变更后调用 |
| API 边界 | Schema 验证 | 处理前验证请求体符合schema |
| 数据管道 | 阶段断言 | ETL转换后断言行数符合预期 |
参考:references/contracts-assertions.md
5. The Broken Window Theory
5. 破窗理论
Core concept: One broken window -- a badly designed piece of code, a poor management decision, a hack that "we'll fix later" -- starts the rot. Once a system shows neglect, entropy accelerates and discipline collapses.
Why it works: Psychology. When code is clean and well-maintained, developers feel social pressure to keep it that way. When code is already messy, the threshold for adding more mess drops to zero. Quality is a team habit, not an individual heroic effort.
Key insights:
- Don't leave broken windows (bad designs, wrong decisions, poor code) unrepaired
- If you can't fix it now, board it up: add a TODO with a ticket, disable the feature, replace with a stub
- Be a catalyst for change: show people a working glimpse of the future (stone soup)
- Watch for slow degradation (boiled frog) -- monitor tech debt metrics over time
- The first hack is the most expensive because it gives permission for all subsequent hacks
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Legacy code | Board up windows | Wrap bad code in a clean interface before adding features |
| Code review | Zero-tolerance for new debt | Reject PRs that add |
| Tech debt | Debt budget | Allocate 20% of each sprint to fixing broken windows |
| New team member | Clean onboarding path | First task: fix a broken window to learn the codebase |
| Monitoring | Entropy metrics | Track linting violations, test coverage trends over time |
See: references/broken-windows.md
核心概念: 一扇破窗——一段设计糟糕的代码、一个错误的管理决策、一个「以后再修」的临时方案——会引发衰败。一旦系统显示出被忽视的迹象,熵增会加速,纪律会瓦解。
为何有效: 这源于心理学。当代码干净且维护良好时,开发者会有社会压力保持其整洁;当代码已经混乱时,添加更多混乱的门槛会降为零。质量是团队的习惯,而非个人的英雄主义努力。
关键见解:
- 不要放任破窗(糟糕的设计、错误的决策、劣质代码)不修复
- 如果现在无法修复,就先「封起来」:添加带工单的TODO、禁用功能、用存根替换
- 成为变革的催化剂:向人们展示未来的可行雏形(石头汤策略)
- 警惕缓慢退化(温水煮青蛙)——随时间监控技术债务指标
- 第一个临时方案代价最高,因为它为后续所有临时方案开了绿灯
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 遗留代码 | 封装破窗 | 在添加功能之前,用干净的接口包裹糟糕的代码 |
| 代码评审 | 零容忍新增债务 | 拒绝添加无工单的 |
| 技术债务 | 债务预算 | 每个 sprint 分配20%的时间用于修复破窗 |
| 新团队成员 | 整洁入职路径 | 第一个任务:修复一个破窗以熟悉代码库 |
| 监控 | 熵指标 | 随时间跟踪lint违规、测试覆盖率趋势 |
参考:references/broken-windows.md
6. Reversibility and Flexibility
6. 可逆转性与灵活性
Core concept: There are no final decisions. Build systems that make it easy to change your mind about databases, frameworks, vendors, architecture, and deployment targets. The cost of change should be proportional to the scope of change.
Why it works: Requirements change. Vendors get acquired. Technologies fall out of favor. If your architecture has hard-coded assumptions about any of these, every change becomes a rewrite. Flexible architecture treats decisions as configuration, not structure.
Key insights:
- Abstract third-party dependencies behind your own interfaces -- never let vendor APIs leak into business logic
- Use the "forking road" test: could you switch from Postgres to DynamoDB in a week? If not, you're coupled
- Metadata-driven systems (config files, feature flags) are more flexible than hard-coded logic
- YAGNI applies to premature abstraction too -- don't build flexibility you don't need yet
- Reversibility is not about predicting the future; it's about not painting yourself into a corner
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Database | Repository pattern | Business logic calls |
| External API | Adapter/wrapper | |
| Feature flags | Runtime toggles | New checkout flow behind a flag, rollback in seconds |
| Architecture | Event-driven decoupling | Services communicate via events, not direct HTTP calls |
| Deployment | Container abstraction | Dockerized app runs on AWS, GCP, or bare metal unchanged |
See: references/reversibility.md
核心概念: 没有最终的决策。构建易于变更的系统,支持更换数据库、框架、供应商、架构和部署目标。变更的成本应与变更的范围成正比。
为何有效: 需求会变化,供应商会被收购,技术会过时。如果你的架构对这些因素有硬编码假设,每次变更都会变成重写。灵活的架构将决策视为配置,而非结构。
关键见解:
- 用自己的接口抽象第三方依赖——绝不让供应商API渗透到业务逻辑中
- 用「岔路口测试」:你能在一周内从Postgres切换到DynamoDB吗?如果不能,说明存在耦合
- 元数据驱动的系统(配置文件、功能标志)比硬编码逻辑更灵活
- YAGNI原则也适用于过早抽象——不要构建目前不需要的灵活性
- 可逆转性不是预测未来,而是不让自己陷入绝境
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| 数据库 | 仓库模式 | 业务逻辑调用 |
| 外部API | 适配器/包装器 | |
| 功能标志 | 运行时切换 | 新结账流程在标志后,可在几秒内回滚 |
| 架构 | 事件驱动解耦 | 服务通过事件通信,而非直接HTTP调用 |
| 部署 | 容器抽象 | 容器化应用可在AWS、GCP或裸金属上无修改运行 |
参考:references/reversibility.md
7. Estimation and Knowledge Portfolio
7. 估算与知识体系
Core concept: Learn to estimate reliably by understanding scope, building models, decomposing into components, and assigning ranges. Manage your learning like a financial portfolio: invest regularly, diversify, and rebalance.
Why it works: Estimation builds trust with stakeholders when done honestly ("1-3 weeks" is better than "2 weeks exactly"). A knowledge portfolio ensures you stay relevant as technologies shift -- the programmer who stops learning stops being effective.
Key insights:
- Ask "what is this estimate for?" -- context determines precision (budget planning vs. sprint planning)
- Use PERT: Optimistic + 4x Most Likely + Pessimistic, divided by 6
- Break estimates into components and estimate each; the total is more accurate than a single guess
- Keep an estimation log: compare estimates to actuals and calibrate
- Knowledge portfolio rules: invest regularly (learn something every week), diversify (don't only learn your stack), manage risk (mix safe and speculative bets), buy low/sell high (learn emerging tech early)
Code applications:
| Context | Pattern | Example |
|---|---|---|
| Sprint planning | Range estimates | "3-5 days" with confidence level, not a single number |
| New technology | Time-boxed spike | "I'll spend 2 days evaluating; then I can estimate properly" |
| Large project | Bottom-up decomposition | Break into tasks < 1 day, sum with buffer for integration |
| Learning | Weekly investment | 1 hour/week on a new language, tool, or domain |
| Career growth | Portfolio diversification | Mix of depth (expertise) and breadth (adjacent skills) |
See: references/estimation-portfolio.md
核心概念: 通过理解范围、构建模型、分解组件和分配范围区间,学会可靠估算。像管理金融投资组合一样管理你的学习:定期投资、分散布局、动态再平衡。
为何有效: 当估算诚实时(「1-3周」比「正好2周」更好),能与利益相关者建立信任。知识体系确保你在技术变革中保持竞争力——停止学习的程序员会失去效力。
关键见解:
- 问自己「这个估算用于什么场景?」——场景决定精度(预算规划 vs sprint规划)
- 使用PERT方法:(乐观值 + 4×最可能值 + 悲观值)÷6
- 将估算分解为组件并分别估算;总和比单一猜测更准确
- 保留估算日志:比较估算值与实际值并校准
- 知识体系规则:定期投资(每周学习新内容)、分散布局(不要只学习当前技术栈)、管理风险(混合安全和投机性学习)、低买高卖(尽早学习新兴技术)
代码应用场景:
| 场景 | 模式 | 示例 |
|---|---|---|
| Sprint规划 | 范围估算 | 给出「3-5天」及置信度,而非单一数字 |
| 新技术 | 时间盒探索 | 「我会花2天评估;之后就能给出准确估算」 |
| 大型项目 | 自底向上分解 | 分解为小于1天的任务,总和加上集成缓冲时间 |
| 学习 | 每周投资 | 每周花1小时学习新语言、工具或领域 |
| 职业发展 | 投资组合多元化 | 混合深度(专业技能)和广度(相邻技能) |
参考:references/estimation-portfolio.md
Common Mistakes
常见错误
| Mistake | Why It Fails | Fix |
|---|---|---|
| DRY-ing similar-looking code that serves different purposes | Creates coupling between unrelated concepts; changes to one break the other | Only DRY knowledge, not coincidental code similarity |
| Skipping tracer bullets and building layer-by-layer | Integration issues surface late; no end-to-end feedback until the end | Build one thin vertical slice first |
| Ignoring broken windows "because we'll refactor later" | Entropy accelerates; later never comes; team morale drops | Fix immediately or board up with a tracked ticket |
| Estimates as single-point commitments | Creates false precision; erodes trust when missed | Always give ranges with confidence levels |
| Making everything "flexible" upfront | Over-engineering; YAGNI; abstraction without evidence of need | Add flexibility when you have concrete evidence you'll need it |
| Assertions in production removed "for performance" | Bugs that assertions would catch now silently corrupt data | Keep critical assertions; benchmark before removing any |
| Global state "for convenience" | Destroys orthogonality; every module coupled to everything | Use dependency injection and explicit parameters |
| 错误 | 失败原因 | 修复方案 |
|---|---|---|
| 对服务于不同目的的相似代码应用DRY原则 | 会在不相关概念之间创建耦合;变更其中一个会破坏另一个 | 仅对知识应用DRY,而非巧合的代码相似性 |
| 跳过追踪代码,逐层构建 | 集成问题很晚才暴露;直到最后才得到端到端反馈 | 先构建一个垂直切片再扩展 |
| 忽视破窗「因为以后会重构」 | 熵增加速;「以后」永远不会到来;团队士气下降 | 立即修复或用跟踪工单封起来 |
| 估算作为单点承诺 | 造成虚假精度;未达标时会损害信任 | 始终给出带置信度的范围 |
| 提前让所有内容「灵活」 | 过度设计;违反YAGNI;无需求依据的抽象 | 当有明确证据需要时再添加灵活性 |
| 为了「性能」在生产环境移除断言 | 断言本可以捕获的bug现在会默默损坏数据 | 保留关键断言;在移除前先做基准测试 |
| 为了「方便」使用全局状态 | 破坏正交性;每个模块都与所有内容耦合 | 使用依赖注入和显式参数 |
Quick Diagnostic
快速诊断
| Question | If No | Action |
|---|---|---|
| Can I change the database without touching business logic? | Orthogonality violation | Introduce repository/adapter pattern |
| Do I have an end-to-end slice working? | Missing tracer bullet | Build one vertical slice before expanding |
| Is every business rule defined in exactly one place? | DRY violation | Identify the authoritative source and remove duplicates |
| Would a new developer call this codebase "clean"? | Broken windows present | Schedule a dedicated cleanup sprint |
| Do my estimates include ranges and confidence levels? | Estimation problem | Switch to PERT or range-based estimates |
| Can I roll back this deployment in under 5 minutes? | Reversibility gap | Add feature flags and blue-green deploys |
| Am I learning something new every week? | Knowledge portfolio stagnant | Schedule weekly learning time and track it |
| 问题 | 如果答案为否 | 行动 |
|---|---|---|
| 我可以在不修改业务逻辑的情况下更换数据库吗? | 违反正交性 | 引入仓库/适配器模式 |
| 我有一个可用的端到端切片吗? | 缺少追踪代码 | 在扩展之前构建一个垂直切片 |
| 每个业务规则都只在一个地方定义吗? | 违反DRY原则 | 确定权威源并移除重复 |
| 新开发者会认为这个代码库「干净」吗? | 存在破窗 | 安排专门的清理sprint |
| 我的估算包含范围和置信度吗? | 估算问题 | 切换到PERT或基于范围的估算 |
| 我能在5分钟内回滚这个部署吗? | 可逆转性不足 | 添加功能标志和蓝绿部署 |
| 我每周都在学习新东西吗? | 知识体系停滞 | 安排每周学习时间并跟踪 |
Reference Files
参考文件
- references/dry-orthogonality.md -- DRY knowledge vs. code duplication, four types of duplication, orthogonality in design and testing
- references/tracer-bullets.md -- Tracer bullet vs. prototype development, building walking skeletons, iterating on tracer code
- references/contracts-assertions.md -- Design by Contract, preconditions/postconditions/invariants, assertive programming patterns
- references/broken-windows.md -- Software entropy, broken window theory, stone soup strategy, fighting degradation
- references/reversibility.md -- Flexible architecture, decoupling strategies, avoiding vendor lock-in, forking road decisions
- references/estimation-portfolio.md -- PERT estimation, decomposition techniques, knowledge portfolio management
- references/dry-orthogonality.md -- DRY知识vs代码重复、四种重复类型、设计与测试中的正交性
- references/tracer-bullets.md -- 追踪代码vs原型开发、构建行走骨架、迭代追踪代码
- references/contracts-assertions.md -- 契约式设计、前置条件/后置条件/不变量、断言式编程模式
- references/broken-windows.md -- 软件熵、破窗理论、石头汤策略、对抗退化
- references/reversibility.md -- 灵活架构、解耦策略、避免供应商锁定、岔路口决策
- references/estimation-portfolio.md -- PERT估算、分解技巧、知识体系管理
Further Reading
延伸阅读
- The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition by Andrew Hunt and David Thomas
- 《程序员修炼之道:通向务实最高境界》20周年纪念版 作者:Andrew Hunt 和 David Thomas
About the Authors
关于作者
Andrew Hunt is a programmer, author, and publisher. He co-founded the Pragmatic Bookshelf and was one of the 17 original authors of the Agile Manifesto. His work focuses on the human side of software development -- how teams learn, communicate, and maintain quality over time.
David Thomas is a programmer and author who co-founded the Pragmatic Bookshelf. He coined the term "DRY" (Don't Repeat Yourself) and "Code Kata." A pioneer in Ruby adoption outside Japan, he co-authored "Programming Ruby" (the Pickaxe book) and has spent decades advocating for developer pragmatism over dogma.
Andrew Hunt 是程序员、作家和出版商。他共同创立了Pragmatic Bookshelf,是敏捷宣言的17位原始作者之一。他的研究聚焦于软件开发的人文层面——团队如何学习、沟通并长期保持质量。
David Thomas 是程序员和作家,共同创立了Pragmatic Bookshelf。他提出了「DRY(Don't Repeat Yourself)」和「Code Kata」的概念。他是日本以外Ruby推广的先驱,合著了《Programming Ruby》(Pickaxe书),数十年来一直倡导开发者务实而非教条。