engineering

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Engineering

软件工程实践

You're here because someone asked "how should I build this?" or needs help choosing between options. This document teaches you how to think about these problems, not just what the answers are.
你来到这里是因为有人问了“我该如何构建这个系统?”,或者需要在多个选项中做出选择。本文档会教你如何思考这类问题,而不只是给出答案。

Why This Matters

为何这至关重要

Technical decisions compound. A framework choice affects every line of code. An architecture pattern shapes how the team works for years. A database decision can't easily be reversed.
The goal isn't to make perfect decisions—it's to make good-enough decisions with clear reasoning that can be revisited when context changes.

技术决策具有复利效应。框架的选择会影响每一行代码。架构模式会塑造团队未来数年的工作方式。数据库的选择一旦做出就很难逆转。
我们的目标不是做出完美的决策——而是在清晰的推理基础上做出足够好的决策,并且当环境变化时可以重新审视这些决策。

The Core Question

核心问题

Before any technical decision, ask yourself:
What problem am I actually solving?
Not "what technology should I use?" That's a solution-shaped question. The real question is about the problem.
A common pattern:
User: "Should I use MongoDB or PostgreSQL?"
Wrong response: Compare features of MongoDB vs PostgreSQL
Right response: "What does your data look like? What queries will you run?"
The choice follows from understanding the problem. Technology is a means, not an end.

在做出任何技术决策之前,先问自己:
我真正要解决的问题是什么?
而不是“我应该使用什么技术?”这是一个以解决方案为导向的问题,真正的核心在于问题本身。
一个常见的场景:
用户:“我应该用MongoDB还是PostgreSQL?”
错误回应:比较MongoDB和PostgreSQL的特性
正确回应:“你的数据结构是什么样的?你需要执行哪些查询?”
技术选型应该基于对问题的理解。技术是手段,而非目的。

Making Technical Decisions

如何做出技术决策

When someone asks you to help choose between options:
当有人请你帮忙在多个选项中做出选择时:

1. Clarify the Problem

1. 明确问题

Ask:
  • What exactly are we trying to achieve?
  • What happens if we do nothing?
  • Who are the users? What do they need?
Don't assume you understand the problem. Often the person asking hasn't fully articulated it either.
询问:
  • 我们真正想要实现的目标是什么?
  • 如果我们不做任何改变,会发生什么?
  • 用户是谁?他们的需求是什么?
不要假设你已经理解了问题。通常提问的人自己也没有完全明确问题。

2. Identify Constraints

2. 识别约束条件

Every decision happens in a context:
  • Time: How urgent is this?
  • Team: What does the team already know?
  • Existing tech: What's already in place?
  • Scale: How big does this need to get?
Constraints eliminate options. A team of two shouldn't build microservices. A system processing billions of rows can't use SQLite.
每一个决策都在特定的背景下做出:
  • 时间:这个需求有多紧急?
  • 团队:团队已经掌握了哪些技术?
  • 现有技术栈:当前已经使用了哪些技术?
  • 规模:系统需要支持多大的规模?
约束条件会帮你排除一些选项。一个只有两个人的团队不应该构建微服务。处理数十亿条数据的系统不能使用SQLite。

3. Consider Reversibility

3. 考虑可逆转性

Easy to reverse          Hard to reverse
←─────────────────────────────────────→
Library choice    Database    Language
Config change     Schema      Architecture
For reversible decisions: decide quickly and move on. For irreversible decisions: invest more time, consider more carefully.
易逆转决策          难逆转决策
←─────────────────────────────────────→
库选择    数据库    编程语言
配置变更  数据库Schema      架构设计
对于易逆转的决策:快速做出决定并推进。 对于难逆转的决策:投入更多时间,更谨慎地考虑。

4. Make a Recommendation

4. 给出明确建议

Don't just present options. Make a call:
"I recommend PostgreSQL because:
- Your data is relational (foreign keys, joins)
- Team already knows SQL
- Query patterns are complex and variable

The trade-off: If you need to scale beyond a single database, you'll need to add read replicas or sharding later. But you're not there yet."
State the recommendation, the reasoning, and the trade-offs. Let the human decide, but don't make them do your thinking.

不要只罗列选项,要做出明确的选择:
“我推荐使用PostgreSQL,原因如下:
- 你的数据是关系型的(需要外键、关联查询)
- 团队已经掌握SQL
- 查询模式复杂且多变

需要权衡的点:如果未来需要突破单数据库的规模限制,你需要添加只读副本或进行分片。但目前你还不需要考虑这些。”
明确说明推荐方案、推理过程以及权衡点。让最终的决策者来拍板,但不要让他们替你完成思考过程。

Thinking About Architecture

架构设计思考

Architecture is about structure: what are the pieces, and how do they connect?
架构关乎系统的结构:系统由哪些组件构成,这些组件之间如何交互?

The Questions That Matter

关键问题

When designing or evaluating architecture:
  1. What changes often? Put those things together.
  2. What changes rarely? Those can be coupled more tightly.
  3. What would be expensive to get wrong? Invest more thought there.
  4. What can be deferred? Don't design what you don't need yet.
在设计或评估架构时,思考以下问题:
  1. 哪些部分经常变化? 将这些部分整合在一起。
  2. 哪些部分很少变化? 这些部分可以更紧密地耦合。
  3. 哪些部分如果设计错误会付出高昂代价? 在这些部分投入更多精力。
  4. 哪些部分可以推迟设计? 不要设计当前不需要的功能。

Common Traps

常见误区

Over-engineering: Building for scale you don't have.
  • A startup doesn't need microservices.
  • A side project doesn't need Kubernetes.
  • YAGNI: You Aren't Gonna Need It.
Under-engineering: No structure at all.
  • When everything talks to everything, changes become terrifying.
  • Some boundaries are worth the upfront cost.
Copying without understanding: Using patterns because "that's how X does it."
  • Netflix's architecture solves Netflix's problems.
  • Your problems are different.
过度设计:为当前不需要的规模提前构建复杂架构。
  • 初创公司不需要微服务。
  • 个人项目不需要Kubernetes。
  • YAGNI:You Aren't Gonna Need It(你不会需要它)。
设计不足:完全没有结构。
  • 当所有组件都直接相互调用时,任何变更都会变得风险极高。
  • 适当的边界划分值得付出前期成本。
盲目照搬:因为“某大厂就是这么做的”而使用特定模式。
  • Netflix的架构是为了解决Netflix的问题。
  • 你的问题和他们的不一样。

The Progression

演进路径

Most projects should follow this path:
Start here: Simple script or monolith
            ↓ when code becomes tangled
Then: Clear module boundaries
            ↓ when modules need to scale independently
Then: Extract services
            ↓ when you hit specific bottlenecks
Then: Specialized solutions
Don't skip steps. Each step teaches you what you actually need.

大多数项目应该遵循以下路径:
从这里开始:简单脚本或单体应用
            ↓ 当代码变得混乱时
下一步:清晰的模块边界
            ↓ 当模块需要独立扩展时
下一步:拆分服务
            ↓ 当遇到特定性能瓶颈时
下一步:专用解决方案
不要跳过任何步骤。每一步都会让你明确自己真正的需求。

Thinking About Implementation

落地实现思考

When writing or reviewing code:
在编写或评审代码时:

Clarity Over Cleverness

清晰优先于技巧

Code is read more than written. The "clever" solution that saves three lines but takes five minutes to understand is the wrong choice.
Wrong: x?.y ?? z || w && v
Right: Explicit conditions with clear names
代码被阅读的次数远多于被编写的次数。那些节省三行代码但需要五分钟才能理解的“技巧性”写法是错误的选择。
错误写法:x?.y ?? z || w && v
正确写法:使用明确的条件判断和清晰的变量名

The Rule of Three

三次原则

  • First time you see a pattern: just write the code.
  • Second time: note the duplication.
  • Third time: consider abstraction.
Premature abstraction is worse than duplication. Wait until you see the pattern clearly.
  • 第一次遇到重复模式:直接编写代码。
  • 第二次遇到:标记出重复的部分。
  • 第三次遇到:考虑抽象封装。
过早的抽象比重复代码更糟糕。等到你清晰地看到模式后再进行抽象。

Fail Fast

快速失败

Detect errors early and surface them clearly:
  • Validate inputs at the boundary
  • Throw exceptions instead of returning null
  • Make invalid states unrepresentable
The worst bugs are the ones that silently corrupt data and only surface weeks later.

尽早检测错误并清晰地暴露出来:
  • 在系统边界处验证输入
  • 抛出异常而非返回null
  • 让无效状态无法被表示
最糟糕的bug是那些悄悄破坏数据,并且数周后才暴露出来的问题。

When to Use Reference Files

何时参考其他文档

This document teaches you how to think. The reference files provide specific knowledge for specific situations.
SituationReference
Choosing between technologiestechnical-decisions.md
Designing system structurearchitecture/patterns.md
Defining module boundariesarchitecture/boundaries.md
Planning data flowarchitecture/data-flow.md
Writing quality codeimplementation/best-practices.md
Applying design patternsimplementation/patterns.md
Restructuring existing coderefactoring.md
Designing APIsapi-design.md
Improving performanceperformance.md
Building CI/CD pipelinescicd-architecture.md
Don't read them all. Read the one you need, when you need it.

本文档教你如何思考这类问题。参考文档为特定场景提供具体的知识。
场景参考文档
技术选型technical-decisions.md
系统结构设计architecture/patterns.md
模块边界定义architecture/boundaries.md
数据流规划architecture/data-flow.md
高质量代码编写implementation/best-practices.md
设计模式应用implementation/patterns.md
现有代码重构refactoring.md
API设计api-design.md
性能优化performance.md
CI/CD流水线构建cicd-architecture.md
不要一次性阅读所有文档。只在需要的时候阅读对应的文档。

What Engineering Is Not

软件工程不是什么

Engineering is not housekeeping.
  • Engineering: "How should we structure authentication?"
  • Housekeeping: "Let's remove these unused imports."
Engineering is not validation.
  • Engineering: "Should we use Jest or Vitest?"
  • Validation: "Do the tests pass?"
Engineering is not implementation.
  • Engineering: "Here's the architecture for this feature."
  • Implementation: Actually writing the code.
Engineering guides the work. Other skills (and humans) do the work.

软件工程不是日常维护。
  • 软件工程:“我们应该如何设计认证系统的结构?”
  • 日常维护:“我们来删除这些未使用的导入语句。”
软件工程不是验证工作。
  • 软件工程:“我们应该使用Jest还是Vitest?”
  • 验证工作:“测试用例是否通过?”
软件工程不是代码编写。
  • 软件工程:“这是该功能的架构设计方案。”
  • 代码编写:实际编写代码的过程。
软件工程指导工作的方向,其他技能(和具体的人)负责执行工作。

The Mindset

思维模式

Good engineering comes from asking good questions:
  • What problem are we solving?
  • What are the constraints?
  • What are the trade-offs?
  • What's the simplest thing that could work?
  • What would we do if we're wrong?
You won't always have perfect information. That's fine. Make the best decision you can with what you know, document your reasoning, and stay ready to adapt.
"Make it work, make it right, make it fast—in that order."
Working software beats elegant architecture. Clarity beats cleverness. Simple solutions beat complex ones.
When in doubt, choose the option that's easier to change later.
优秀的软件工程源于提出好问题:
  • 我们要解决的问题是什么?
  • 有哪些约束条件?
  • 有哪些需要权衡的点?
  • 最简单的可行方案是什么?
  • 如果我们的决策错了,该怎么办?
你不会总是拥有完美的信息。没关系,利用你所知道的一切做出最好的决策,记录你的推理过程,并随时准备适应变化。
“先让它运行起来,再让它正确,最后让它更快——按这个顺序来。”
可运行的软件优于优雅的架构。清晰优先于技巧。简单的解决方案优于复杂的方案。
当你不确定时,选择那些未来更容易调整的选项。