technical-constitution

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

The Constitution: Technical Preference Universal Principles

《项目章程:技术偏好通用准则》

⚖️ CRITICAL GOVERNANCE NOTICE
CRITICAL: BEFORE doing ANYTHING else, Read and Comprehend this document COMPLETELY.
MANDATORY COMPLIANCE CHECK:
Before executing your task, you must perform a "Constitution Lookup":
  1. IDENTIFY the domain of your task (e.g., API, DB, Auth, logging, etc.).
  2. SEARCH the relevant sections (e.g., grep "API Design").
  3. REVIEW Critical Constraints table for domain
  4. VERIFY your plan against the discipline and constraints before proceeding.
⚖️ 重要治理通知
重要提示: 开展任何工作前,请先完整阅读并理解本文件。

1. The Supremacy Clause & Conflict Resolution

强制合规检查:

When directives conflict or seem impossible to satisfy simultaneously, follow this precedence:
  1. Security Principles [Non-Negotiable]
    • OWASP Top 10 compliance
    • Input validation and sanitization
    • Authentication and authorization
    • Secrets management
    • No information leakage
    • Action: Security ALWAYS wins. Refactor other requirements to satisfy security.
  2. Testability & Modularity [Structural Law]
    • I/O isolation (dependencies mockable in tests)
    • Pure business logic (no side effects in core logic)
    • Clear module boundaries with contracts
    • Action: If code cannot be unit tested without external dependencies, refactor to add abstraction layer.
  3. Error Handling Standards [Reliability Law]
    • No silent failures
    • Correlation IDs required
    • JSON envelope format
    • Resource cleanup in all paths
    • Action: All error paths must be explicit. No exceptions.
  4. Language Idioms [Implementation Preference]
    • Use native patterns (defer, RAII, context managers)
    • Follow community conventions
    • Leverage standard library
    • Action: Implement above laws idiomatically, don't blindly copy other languages.
  5. Performance Optimizations [Measure First]
    • Appropriate data structures
    • Profile before optimizing
    • Caching strategies
    • Action: Only optimize with measured bottlenecks. Correctness > speed
执行任务前,你必须完成「章程核查」流程:
  1. 明确任务所属领域(例如:API、数据库、鉴权、日志等)。
  2. 检索相关章节(例如:grep "API Design")。
  3. 查阅对应领域的关键约束表。
  4. 推进工作前,对照规则与约束校验你的方案是否合规。

Escalation Protocol

1. 最高效力条款与冲突解决规则

If following a directive is impossible:
  1. STOP coding immediately
  2. Document the conflict:
    • Which directives conflict?
    • Why is compliance impossible?
    • What are the tradeoffs?
  3. Propose alternatives:
    • Option A: [approach + which rules satisfied/violated]
    • Option B: [approach + which rules satisfied/violated]
    • ...
  4. ASK human for decision
    • Present the precedence hierarchy
    • Recommend least-harmful deviation option with justification based on hierarchy
    • Wait for explicit approval
CRITICAL: NEVER silently violate, If following directive is impossible, STOP and ask human
当不同指令出现冲突或无法同时满足时,按以下优先级处理:
  1. 安全原则 [不可协商]
    • 符合OWASP Top 10规范
    • 输入校验与内容清洗
    • 身份认证与权限控制
    • 密钥管理
    • 无信息泄露
    • 处理方式: 安全优先级最高,调整其他需求以满足安全要求。
  2. 可测试性与模块化 [结构性规则]
    • I/O隔离(依赖可在测试中被mock)
    • 纯业务逻辑(核心逻辑无副作用)
    • 带契约的清晰模块边界
    • 处理方式: 如果代码脱离外部依赖就无法进行单元测试,需要重构增加抽象层。
  3. 错误处理标准 [可靠性规则]
    • 无静默失败
    • 必须携带关联ID
    • JSON信封格式
    • 所有路径下的资源清理
    • 处理方式: 所有错误路径必须显式处理,无例外。
  4. 语言惯用规范 [实现偏好]
    • 使用原生模式(defer、RAII、上下文管理器)
    • 遵循社区约定
    • 优先使用标准库
    • 处理方式: 用符合语言习惯的方式实现上述规则,不要盲目照搬其他语言的写法。
  5. 性能优化 [先测量再优化]
    • 选用合适的数据结构
    • 优化前先做性能分析
    • 缓存策略
    • 处理方式: 仅针对已测量确认的瓶颈做优化,正确性优先于速度。

Example:

升级上报协议

Scenario 1: Framework Requires Inheritance (Architecture vs Language Idiom)
  • Conflict: Django ORM requires model inheritance, but domain must be pure
  • Hierarchy: Architecture (Level 2) > Framework idiom (Level 4)
  • Resolution: Create Database Model (inherits ORM) + Pure Domain Entity + Mapper pattern
  • PROCEED: Architecture wins
Scenario 2: Performance vs Security
  • Conflict: Caching would speed up response but contains PII
  • Hierarchy: Security (Level 1) > Performance (Level 5)
  • Resolution: Sanitize PII before caching OR skip caching for PII endpoints
  • PROCEED: Security wins
Scenario 3: Testing Pure Functions with Time Dependencies
  • Conflict: Domain needs current timestamp but should be pure
  • Hierarchy: Architecture purity (Level 2) maintained via Time Port (Level 4 idiom)
  • Resolution: Inject Clock/Time interface as driven port, mock in tests
  • PROCEED: Both satisfied through proper port design
如果确实无法遵循某条指令:
  1. 立即停止编码
  2. 记录冲突信息:
    • 哪些指令存在冲突?
    • 为什么无法满足合规要求?
    • 涉及的取舍是什么?
  3. 提出替代方案:
    • 选项A:[实现思路 + 满足/违反的规则]
    • 选项B:[实现思路 + 满足/违反的规则]
    • ...
  4. 咨询人类开发者做决策
    • 展示优先级层级
    • 基于层级推荐危害最小的偏离方案并说明理由
    • 等待明确审批
重要提示:绝对不要静默违反规则,如果无法遵循指令,请立即停止并咨询人类开发者。

2. Critical Constraints Manifest (Context Triggers)

示例:

Agent Note: If the user query touches on these specific topics, prioritize the following internal rules over general knowledge. These are the High-Priority Constraints. Violating these is an automatic failure.
TopicCritical Constraint (Summary)
ArchitectureTestability-First Design. Domain is pure, All code must be independently testable. Feature-based packaging.
Essential Software DesignSOLID Principles, Essential Design Practices(DRY, YAGNI, KISS), Code Organization Principles.
Error HandlingJSON format only (
code
,
message
,
correlationId
). No silent failures. No
try/catch
swallowing.
Testing70/20/10 Pyramid. Mock Ports, not Internals. Integration tests use real infrastructure (Testcontainers).
ConcurrencyAvoid shared memory. Use message passing/channels. Timeout ALL I/O operations.
ConfigHybrid approach: YAML for structure,
.env
for secrets. Fail fast on missing config.
API DesignResource-based URLs. Standard HTTP status codes. Envelope response format (
data
,
meta
).
Security (Auth)Deny by default. Server-side checks EVERY request. RBAC/ABAC. MFA for sensitive ops. Rate limit (5/15min). Bcrypt/Argon2 only.
Security (Data)TLS 1.2+. Encrypt at rest. No secrets in code. PII redacted in logs.
Security (Input)Validation: Validated Zod/Pydantic Schemas at ALL boundaries. Sanitization: Parameterized queries ONLY. Sanitize output.
场景1:框架要求继承(架构 vs 语言惯用规范)
  • 冲突:Django ORM要求模型继承,但领域层需要保持纯逻辑
  • 优先级:架构(第2级)> 框架惯用规范(第4级)
  • 解决方案:创建数据库模型(继承ORM) + 纯领域实体 + 映射器模式
  • 结论:按架构规则执行
场景2:性能 vs 安全
  • 冲突:缓存可以提升响应速度,但缓存内容包含个人可识别信息(PII)
  • 优先级:安全(第1级)> 性能(第5级)
  • 解决方案:缓存前清洗PII信息,或者包含PII的接口不使用缓存
  • 结论:按安全规则执行
场景3:测试带时间依赖的纯函数
  • 冲突:领域逻辑需要获取当前时间戳,但需要保持纯逻辑特性
  • 优先级:通过时间端口(第4级惯用规范)维持架构纯净性(第2级)
  • 解决方案:注入时钟/时间接口作为驱动端口,测试时进行mock
  • 结论:通过合理的端口设计同时满足两个要求

3. Table of Contents

2. 关键约束清单(上下文触发规则)

Agent Note: Refer to the sections below for detailed implementation rules on all 16 topics.
Agent注意:如果用户查询涉及以下特定主题,优先遵循以下内部规则,优先级高于通用知识。这些是最高优先级约束,违反将直接判定为失败。
主题关键约束(摘要)
架构可测试性优先设计,领域层为纯逻辑,所有代码必须可独立测试,按功能打包。
基础软件设计SOLID原则、基础设计实践(DRY、YAGNI、KISS)、代码组织原则。
错误处理仅使用JSON格式(
code
message
correlationId
),无静默失败,不允许
try/catch
吞掉异常。
测试70/20/10测试金字塔,Mock端口而非内部逻辑,集成测试使用真实基础设施(Testcontainers)。
并发避免共享内存,使用消息传递/通道,所有I/O操作必须设置超时。
配置混合方案:YAML存储结构,
.env
存储密钥,配置缺失时快速失败。
API设计基于资源的URL,标准HTTP状态码,信封响应格式(
data
meta
)。
安全(鉴权)默认拒绝,服务端校验所有请求,RBAC/ABAC权限模型,敏感操作要求MFA,限流规则(5次/15分钟),仅使用Bcrypt/Argon2加密。
安全(数据)TLS 1.2+,静态数据加密,代码中不允许硬编码密钥,日志中PII信息需脱敏。
安全(输入)校验: 所有边界都使用Zod/Pydantic Schema做校验。清洗: 仅使用参数化查询,输出内容做清洗。

Architectural Patterns - Testability-First Design

3. 目录

Core Principle

All code must be independently testable without running the full application or external infrastructure.
Agent注意:以下章节包含16个主题的详细实现规则,可参考查阅。

Universal Architecture Rules

架构模式 - 可测试性优先设计

Rule 1: I/O Isolation

核心原则

Problem: Tightly coupled I/O makes tests slow, flaky, and environment-dependent.
Solution: Abstract all I/O behind interfaces/contracts:
  • Database queries
  • HTTP calls (to external APIs)
  • File system operations
  • Time/randomness (for determinism)
  • Message queues
Implementation Discovery:
  1. Search for existing abstraction patterns:
    find_symbol("Interface")
    ,
    find_symbol("Mock")
    ,
    find_symbol("Repository")
  2. Match the style (interface in Go, Protocol in Python, interface in TypeScript)
  3. Implement production adapter AND test adapter
Example (Go):
Go

// Contract (port)
type UserStore interface {
  Create(ctx context.Context, user User) error
  GetByEmail(ctx context.Context, email string) (*User, error)
}

// Production adapter
type PostgresUserStore struct { /* ... */ }

// Test adapter
type MockUserStore struct { /* ... */ }
Example (TypeScript/Vue):
typescript

// Contract (service layer)
export interface TaskAPI {
  createTask(title: string): Promise<Task>;
  getTasks(): Promise<Task[]>;
}

// Production adapter
export class EncoreTaskAPI implements TaskAPI { /* ... */ }

// Test adapter (vi.mock or manual)
export class MockTaskAPI implements TaskAPI { /* ... */ }
所有代码必须可独立测试,无需运行完整应用或依赖外部基础设施。

Rule 2: Pure Business Logic

通用架构规则

规则1:I/O隔离

Problem: Business rules mixed with I/O are impossible to test without infrastructure.
Solution: Extract calculations, validations, transformations into pure functions:
  • Input → Output, no side effects
  • Deterministic: same input = same output
  • No I/O inside business rules
Examples:

// ✅ Pure function - easy to test
func calculateDiscount(items []Item, coupon Coupon) (float64, error) {
// Pure calculation, returns value
}

// ❌ Impure - database call inside
func calculateDiscount(ctx context.Context, items []Item, coupon Coupon) (float64, error) {
validCoupon, err := db.GetCoupon(ctx, coupon.ID) // NO!
}
Correct approach:

// 1. Fetch dependencies first (in handler/service)
validCoupon, err := store.GetCoupon(ctx, coupon.ID)

// 2. Pass to pure logic
discount, err := calculateDiscount(items, validCoupon)

// 3. Persist result
err = store.SaveOrder(ctx, order)
问题: 紧耦合的I/O会导致测试变慢、不稳定、依赖环境。 解决方案: 将所有I/O抽象到接口/契约之后:
  • 数据库查询
  • HTTP调用(外部API)
  • 文件系统操作
  • 时间/随机数(保证确定性)
  • 消息队列
实现发现流程:
  1. 查找现有抽象模式:
    find_symbol("Interface")
    find_symbol("Mock")
    find_symbol("Repository")
  2. 匹配现有风格(Go的interface、Python的Protocol、TypeScript的interface)
  3. 实现生产适配器 测试适配器
示例(Go):
Go
// 契约(端口)
type UserStore interface {
  Create(ctx context.Context, user User) error
  GetByEmail(ctx context.Context, email string) (*User, error)
}

// 生产适配器
type PostgresUserStore struct { /* ... */ }

// 测试适配器
type MockUserStore struct { /* ... */ }
示例(TypeScript/Vue):
typescript
// 契约(服务层)
export interface TaskAPI {
  createTask(title: string): Promise<Task>;
  getTasks(): Promise<Task[]>;
}

// 生产适配器
export class EncoreTaskAPI implements TaskAPI { /* ... */ }

// 测试适配器(vi.mock 或手动实现)
export class MockTaskAPI implements TaskAPI { /* ... */ }

Rule 3: Module Boundaries

规则2:纯业务逻辑

Problem: Cross-module coupling makes changes ripple across codebase.
Solution: Feature-based organization with clear public interfaces:
  • One feature = one directory
  • Each module exposes a public API (exported functions/classes)
  • Internal implementation details are private
  • Cross-module calls only through public API
Directory Structure (Language-Agnostic):

/task

- public_api.{ext}      # Exported interface
- business.{ext}        # Pure logic
- store.{ext}           # I/O abstraction (interface)
- postgres.{ext}        # I/O implementation
- mock.{ext}            # Test implementation
- test.{ext}            # Unit tests (mocked I/O)
- integration.test.{ext} # Integration tests (real I/O)
Go Example:

/apps/backend/task

- task.go               # Encore API endpoints (public)
- business.go           # Pure domain logic
- store.go              # interface UserStore
- postgres.go           # implements UserStore
- task_test.go          # Unit tests with MockStore
- task_integration_test.go # Integration with real DB
Vue Example:

/apps/frontend/src/features/task

- index.ts              # Public exports
- task.service.ts       # Business logic
- task.api.ts           # interface TaskAPI
- task.api.encore.ts    # implements TaskAPI
- task.store.ts         # Pinia store (uses TaskAPI)
- task.service.spec.ts  # Unit tests (mock API)
问题: 业务规则与I/O混合在一起,脱离基础设施就无法测试。 解决方案: 将计算、校验、转换逻辑提取为纯函数:
  • 输入 → 输出,无副作用
  • 确定性:相同输入一定得到相同输出
  • 业务规则内部无I/O操作
示例:
// ✅ 纯函数 - 易于测试
func calculateDiscount(items []Item, coupon Coupon) (float64, error) {
// 纯计算,返回结果
}

// ❌ 非纯函数 - 内部包含数据库调用
func calculateDiscount(ctx context.Context, items []Item, coupon Coupon) (float64, error) {
validCoupon, err := db.GetCoupon(ctx, coupon.ID) // 禁止!
}
正确实现方式:
// 1. 先获取依赖(在handler/服务层)
validCoupon, err := store.GetCoupon(ctx, coupon.ID)

// 2. 传入纯逻辑处理
discount, err := calculateDiscount(items, validCoupon)

// 3. 持久化结果
err = store.SaveOrder(ctx, order)

Rule 4: Dependency Direction

规则3:模块边界

Principle: Dependencies point inward toward business logic.

┌─────────────────────────────────────┐
│  Infrastructure Layer               │
│  (DB, HTTP, Files, External APIs)   │
│                                     │
│  Depends on ↓                       │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│  Contracts/Interfaces Layer         │
│  (Abstract ports - no implementation)│
│                                     │
│  Depends on ↓                       │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│  Business Logic Layer               │
│  (Pure functions, domain rules)     │
│  NO dependencies on infrastructure  │
└─────────────────────────────────────┘
Never:
  • Business logic imports database driver
  • Domain entities import HTTP framework
  • Core calculations import config files
Always:
  • Infrastructure implements interfaces defined by business layer
  • Business logic receives dependencies via injection
Package Structure Philosophy:
  • Organize by FEATURE, not by technical layer
  • Each feature is a vertical slice
  • Enables modular growth, clear boundaries, and independent deployability
Universal Rule: Context → Feature → Layer
1. Level 1: Repository Scope (Conditional)
  • Scenario A (Monorepo/Full-Stack): Root contains
    apps/
    grouping distinct applications (e.g.,
    apps/backend
    ,
    apps/web
    ).
  • Scenario B (Single Service): Root IS the application. Do not create
    apps/backend
    wrapper. Start directly at Level 2.
2. Level 2: Feature Organization
  • Rule: Divide application into vertical business slices (e.g.,
    user/
    ,
    order/
    ,
    payment/
    ).
  • Anti-Pattern: Do NOT organize by technical layer (e.g.,
    controllers/
    ,
    models/
    ,
    services/
    ) at the top level.
问题: 跨模块耦合会导致修改扩散到整个代码库。 解决方案: 按功能组织,具备清晰的公共接口:
  • 一个功能对应一个目录
  • 每个模块暴露公共API(导出的函数/类)
  • 内部实现细节私有
  • 跨模块调用只能通过公共API
目录结构(语言无关):
/task

- public_api.{ext}      # 导出的接口
- business.{ext}        # 纯逻辑
- store.{ext}           # I/O抽象(接口)
- postgres.{ext}        # I/O实现
- mock.{ext}            # 测试实现
- test.{ext}            # 单元测试(mock I/O)
- integration.test.{ext} # 集成测试(真实I/O)
Go示例:
/apps/backend/task

- task.go               # Encore API端点(公共)
- business.go           # 纯领域逻辑
- store.go              # interface UserStore
- postgres.go           # implements UserStore
- task_test.go          # 单元测试(使用MockStore)
- task_integration_test.go # 真实数据库集成测试
Vue示例:
/apps/frontend/src/features/task

- index.ts              # 公共导出
- task.service.ts       # 业务逻辑
- task.api.ts           # interface TaskAPI
- task.api.encore.ts    # implements TaskAPI
- task.store.ts         # Pinia store(使用TaskAPI)
- task.service.spec.ts  # 单元测试(mock API)

Layout Examples

规则4:依赖方向

A. Standard Single Service (Backend, Microservice or MVC)
  apps/  
    task/                       # Feature: Task management    
      task.go                      # API handlers (public interface)
      task_test.go                 # Unit tests (mocked dependencies)
      business.go                  # Pure business logic
      business_test.go             # Unit tests (pure functions)
      store.go                     # interface TaskStore
      postgres.go                  # implements TaskStore
      postgres_integration_test.go # Integration tests (real DB)
      mock_store.go               # Test implementation
    migrations/
      001_create_tasks.up.sql
    order/                      # Feature: Order management  
      ...
B. Monorepo Layout (Multi-Stack): *Use this structure when managing monolithic full-stack applications with backend, frontend, mobile in a single repository. Clear Boundaries: Backend business logic is isolated from Frontend UI logic, even if they share the same repo
  apps/
    backend/                        # Backend application source code  
        task/                       # Feature: Task management  
          task.go                      # API handlers (public interface)
          ...   
        order/                      # Feature: Order management  
        ...
    frontend/                       # Frontend application source code
      assets/                       # Fonts, Images
      components/                   # Shared Component (Buttons, Inputs) - Dumb UI, No Domain Logic
        BaseButton.vue
        BaseInput.vue
      layouts/                      # App shells (Sidebar, Navbar wrappers)
      utils/                        # Date formatting, validation helpers
      features/                     # Business Features (Vertical Slices)
        task/                       # Feature: Task management
          TaskForm.vue              # Feature-specific components
          TaskListItem.vue          
          TaskFilters.vue           
          index.ts                  # Public exports
          task.service.ts           # Business logic
          task.api.ts               # interface TaskAPI
          task.api.encore.ts        # Production implementation
          task.store.ts             # Pinia store
        order/
      ...
This Feature/Domain/UI/API structure is framework-agnostic. It applies equally to React, Vue, Svelte, and Mobile (React Native/Flutter). 'UI' always refers to the framework's native component format (.tsx, .vue, .svelte, .dart).
原则: 依赖向内指向业务逻辑。
┌─────────────────────────────────────┐
│  基础设施层                         │
│  (数据库、HTTP、文件、外部API)    │
│                                     │
│  依赖 ↓                             │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│  契约/接口层                        │
│  (抽象端口 - 无实现)              │
│                                     │
│  依赖 ↓                             │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│  业务逻辑层                         │
│  (纯函数、领域规则)               │
│  无基础设施依赖                     │
└─────────────────────────────────────┘
禁止:
  • 业务逻辑导入数据库驱动
  • 领域实体导入HTTP框架
  • 核心计算导入配置文件
必须:
  • 基础设施实现业务层定义的接口
  • 业务逻辑通过注入接收依赖
包结构设计理念:
  • 按功能组织,而非按技术层组织
  • 每个功能是一个垂直切片
  • 支持模块化增长、清晰边界、独立部署
通用规则:上下文 → 功能 → 层级 1. 第一层:仓库范围(可选)
  • 场景A(Monorepo/全栈): 根目录包含
    apps/
    ,存放不同应用(例如:
    apps/backend
    apps/web
    )。
  • 场景B(单服务): 根目录 就是 应用,不要创建
    apps/backend
    包装,直接从第二层开始。
2. 第二层:功能组织
  • 规则: 将应用拆分为垂直业务切片(例如:
    user/
    order/
    payment/
    )。
  • 反模式: 顶层不要按技术层组织(例如:
    controllers/
    models/
    services/
    )。

Pattern Discovery Protocol

布局示例

Before implementing ANY feature:
  1. Search existing patterns (MANDATORY):

find_symbol("Interface") OR find_symbol("Repository") OR find_symbol("Service")
  1. Examine 3 existing modules for consistency:
  • How do they handle database access?
  • Where are pure functions vs I/O operations?
  • What testing patterns exist?
  1. Document pattern (80%+ consistency required):
  • "Following pattern from [task, user, auth] modules"
  • "X/Y modules use interface-based stores"
  • "All tests use [MockStore, vi.mock, TestingPinia] pattern"
  1. If consistency <80%: STOP and report fragmentation to human.
A. 标准单服务(后端、微服务或MVC)
  apps/  
    task/                       # 功能:任务管理    
      task.go                      # API handler(公共接口)
      task_test.go                 # 单元测试(mock依赖)
      business.go                  # 纯业务逻辑
      business_test.go             # 单元测试(纯函数)
      store.go                     # interface TaskStore
      postgres.go                  # implements TaskStore
      postgres_integration_test.go # 集成测试(真实数据库)
      mock_store.go               # 测试实现
    migrations/
      001_create_tasks.up.sql
    order/                      # 功能:订单管理  
      ...
B. Monorepo布局(多技术栈): 当在单个仓库中管理包含后端、前端、移动端的单体全栈应用时使用此结构。 边界清晰:后端业务逻辑与前端UI逻辑隔离,即使它们在同一个仓库中
  apps/
    backend/                        # 后端应用源代码  
        task/                       # 功能:任务管理  
          task.go                      # API handler(公共接口)
          ...   
        order/                      # 功能:订单管理  
        ...
    frontend/                       # 前端应用源代码
      assets/                       # 字体、图片
      components/                   # 共享组件(按钮、输入框)- 纯UI,无领域逻辑
        BaseButton.vue
        BaseInput.vue
      layouts/                      # 应用外壳(侧边栏、导航栏包装)
      utils/                        # 日期格式化、校验工具
      features/                     # 业务功能(垂直切片)
        task/                       # 功能:任务管理
          TaskForm.vue              # 功能专属组件
          TaskListItem.vue          
          TaskFilters.vue           
          index.ts                  # 公共导出
          task.service.ts           # 业务逻辑
          task.api.ts               # interface TaskAPI
          task.api.encore.ts        # 生产实现
          task.store.ts             # Pinia store
        order/
      ...
这种功能/领域/UI/API结构与框架无关,同样适用于React、Vue、Svelte和移动端(React Native/Flutter)。'UI'始终指代框架的原生组件格式(.tsx、.vue、.svelte、.dart)。

Testing Requirements

模式发现协议

Unit Tests (must run without infrastructure):
  • Mock all I/O dependencies
  • Test business logic in isolation
  • Fast (<100ms per test)
  • 85%+ coverage of business paths
Integration Tests (must test real infrastructure):
  • Use real database (Testcontainers, Firebase emulator)
  • Test adapter implementations
  • Verify contracts work end-to-end
  • Cover all I/O adapters
Test Organization:
  • Unit/Integration tests: Co-located with implementation
  • E2E tests: Separate
    /e2e
    directory
实现任何功能前:
  1. 查找现有模式(强制):
find_symbol("Interface") OR find_symbol("Repository") OR find_symbol("Service")
  1. 检查3个现有模块保证一致性:
  • 它们如何处理数据库访问?
  • 纯函数和I/O操作分别放在哪里?
  • 现有测试模式是什么?
  1. 记录模式(需要80%+一致性):
  • "遵循[task、user、auth]模块的模式"
  • "X/Y模块使用基于接口的存储层"
  • "所有测试使用[MockStore、vi.mock、TestingPinia]模式"
  1. 如果一致性<80%:停止并向人类开发者报告碎片化问题。

Language-Specific Idioms

测试要求

How to achieve testability in each ecosystem:
Language/FrameworkAbstraction PatternTest Strategy
GoInterface types, dependency injectionTable-driven tests, mock implementations
TypeScript/VueInterface types, service layer, Pinia storesVitest with
vi.mock
,
createTestingPinia
TypeScript/ReactInterface types, service layer, Context/hooksJest with mock factories, React Testing Library
Python
typing.Protocol
or abstract base classes
pytest with fixtures, monkeypatch
RustTraits, dependency injectionUnit tests with mock implementations,
#[cfg(test)]
Flutter/DartAbstract classes, dependency injection
mockito
package, widget tests
单元测试(无需基础设施即可运行):
  • Mock所有I/O依赖
  • 隔离测试业务逻辑
  • 速度快(每个测试<100ms)
  • 业务路径覆盖率85%+
集成测试(测试真实基础设施):
  • 使用真实数据库(Testcontainers、Firebase模拟器)
  • 测试适配器实现
  • 端到端验证契约可用
  • 覆盖所有I/O适配器
测试组织:
  • 单元/集成测试:与实现代码放在一起
  • E2E测试:单独的
    /e2e
    目录

Enforcement Checklist

语言专属惯用规范

Before marking code complete, verify:
  • Can I run unit tests without starting database/external services?
  • Are all I/O operations behind an abstraction?
  • Is business logic pure (no side effects)?
  • Do integration tests exist for all adapters?
  • Does pattern match existing codebase (80%+ consistency)?
不同生态下实现可测试性的方式:
语言/框架抽象模式测试策略
Go接口类型、依赖注入表驱动测试、mock实现
TypeScript/Vue接口类型、服务层、Pinia stores基于
vi.mock
createTestingPinia
的Vitest测试
TypeScript/React接口类型、服务层、Context/hooks基于mock工厂、React Testing Library的Jest测试
Python
typing.Protocol
或抽象基类
基于fixtures、monkeypatch的pytest测试
RustTrait、依赖注入带mock实现的单元测试、
#[cfg(test)]
Flutter/Dart抽象类、依赖注入
mockito
包、组件测试

Related Principles

落地检查清单

标记代码完成前,验证:
  • 无需启动数据库/外部服务即可运行单元测试?
  • 所有I/O操作都在抽象层之后?
  • 业务逻辑是纯逻辑(无副作用)?
  • 所有适配器都有对应的集成测试?
  • 模式与现有代码库匹配(80%+一致性)?

Core Design Principles

关联原则

SOLID Principles

Single Responsibility Principle (SRP):
  • Each class, module, or function should have ONE and ONLY ONE reason to change
  • Generate focused, cohesive units of functionality
  • If explaining what something does requires "and", it likely violates SRP
Open/Closed Principle (OCP):
  • Software entities should be open for extension but closed for modification
  • Design abstractions (interfaces, ports) that allow behavior changes without modifying existing code
  • Use composition and dependency injection to enable extensibility
Liskov Substitution Principle (LSP):
  • Subtypes must be substitutable for their base types without altering program correctness
  • Inheritance hierarchies must maintain behavioral consistency
  • If substituting a subclass breaks functionality, LSP is violated
Interface Segregation Principle (ISP):
  • Clients should not be forced to depend on interfaces they don't use
  • Create focused, role-specific interfaces rather than monolithic ones
  • Many small, cohesive interfaces > one large, general-purpose interface
Dependency Inversion Principle (DIP):
  • Depend on abstractions (interfaces/ports), not concretions (implementations/adapters)
  • High-level modules should not depend on low-level modules; both should depend on abstractions
  • Core principle enabling Testability-First architecture

Essential Design Practices

核心设计原则

SOLID原则

DRY (Don't Repeat Yourself):
  • Eliminate code duplication through proper abstraction, shared utilities, composable functions
  • Each piece of knowledge should have single, authoritative representation
  • Don't duplicate logic, algorithms, or business rules
YAGNI (You Aren't Gonna Need It):
CRITICAL: Code maintainability always prevail
  • Avoid implementing functionality before it's actually required
  • Don't add features based on speculation about future needs
  • Build for today's requirements, refactor when needs change
KISS (Keep It Simple, Stupid):
CRITICAL: Code maintainability always prevail
  • Prefer simple(simple to maintain), straightforward solutions over complex, clever ones
  • Complexity should be justified by actual requirements, not theoretical flexibility
  • Simple code is easier to test, maintain, and debug
Separation of Concerns:
  • Divide program functionality into distinct sections with minimal overlap
  • Each concern should be isolated in its own module or layer
Composition Over Inheritance:
  • Favor object composition and delegation over class inheritance for code reuse
  • Composition is more flexible and easier to test
  • Use interfaces/traits for polymorphism instead of deep inheritance hierarchies
Principle of Least Astonishment:
  • Code should behave in ways that users and maintainers naturally expect
  • Avoid surprising or counterintuitive behavior
  • Follow established conventions and patterns
单一职责原则(SRP):
  • 每个类、模块或函数应该只有一个变更原因
  • 生成内聚的功能单元
  • 如果描述某个东西的功能需要用「和」,那它很可能违反了SRP
开闭原则(OCP):
  • 软件实体应该对扩展开放,对修改关闭
  • 设计抽象(接口、端口),无需修改现有代码即可变更行为
  • 使用组合和依赖注入实现可扩展性
里氏替换原则(LSP):
  • 子类型必须可以替换其基类型,且不会改变程序正确性
  • 继承层级必须保持行为一致性
  • 如果替换子类会破坏功能,就违反了LSP
接口隔离原则(ISP):
  • 不应该强迫客户端依赖它们不需要的接口
  • 创建聚焦、面向角色的接口,而非大一统接口
  • 多个小的内聚接口 > 一个大的通用接口
依赖倒置原则(DIP):
  • 依赖抽象(接口/端口),而非具体实现(实现/适配器)
  • 高层模块不应该依赖低层模块,两者都应该依赖抽象
  • 是实现可测试性优先架构的核心原则

Code Organization Principles

基础设计实践

  • Generate small, focused functions with clear single purposes (typically 10-50 lines)
  • Keep cognitive complexity low (cyclomatic complexity < 10 for most functions)
  • Maintain clear boundaries between different layers (presentation, business logic, data access)
  • Design for testability from the start, avoiding tight coupling that prevents testing
  • Apply consistent naming conventions that reveal intent without requiring comments
DRY(不要重复自己):
  • 通过合理的抽象、共享工具、可组合函数消除代码重复
  • 每一项知识都应该有单一的权威表示
  • 不要重复逻辑、算法或业务规则
YAGNI(你不会需要它): 重要提示: 代码可维护性始终优先
  • 避免实现实际还不需要的功能
  • 不要基于对未来需求的猜测添加功能
  • 为当前需求构建,需求变化时再重构
KISS(保持简单): 重要提示: 代码可维护性始终优先
  • 优先选择简单(易于维护)、直接的解决方案,而非复杂、巧妙的方案
  • 复杂性应该由实际需求 justify,而非理论上的灵活性
  • 简单代码更易于测试、维护和调试
关注点分离:
  • 将程序功能划分为不同的部分,重叠最小
  • 每个关注点应该隔离在自己的模块或层中
组合优于继承:
  • 优先使用对象组合和委托实现代码复用,而非类继承
  • 组合更灵活,更易于测试
  • 使用接口/trait实现多态,而非深继承层级
最小惊讶原则:
  • 代码的行为应该符合用户和维护者的自然预期
  • 避免意外或反直觉的行为
  • 遵循已建立的约定和模式

Error Handling Principles

代码组织原则

Error Categories

1. Validation Errors (4xx):
  • User input doesn't meet requirements (wrong format, missing fields, out of range)
  • Examples: Invalid email, password too short, required field missing
  • Response: 400 Bad Request with detailed field-level errors
  • User can fix: Yes, by correcting input
2. Business Errors (4xx):
  • Domain rule violations (insufficient balance, duplicate email, order already shipped)
  • Examples: Can't delete user with active orders, can't process refund after 30 days
  • Response: 400/409/422 with business rule explanation
  • User can fix: Maybe, depends on business context
3. Authentication Errors (401):
  • Identity verification failed (invalid credentials, expired token, missing token)
  • Response: 401 Unauthorized
  • User can fix: Yes, by providing valid credentials
4. Authorization Errors (403):
  • Permission denied (user identified but lacks permission)
  • Response: 403 Forbidden
  • User can fix: No, requires admin intervention
5. Not Found Errors (404):
  • Resource doesn't exist or user lacks permission to know it exists
  • Response: 404 Not Found
  • User can fix: No
6. Infrastructure Errors (5xx):
  • Database down, network timeout, external service failure, out of memory
  • Response: 500/502/503 with generic message
  • User can fix: No, system issue
  • 编写小的、聚焦的函数,具备清晰的单一职责(通常10-50行)
  • 保持认知复杂度低(大多数函数的圈复杂度<10)
  • 不同层(展示层、业务逻辑层、数据访问层)之间保持清晰边界
  • 从一开始就为可测试性设计,避免导致无法测试的紧耦合
  • 应用一致的命名约定,无需注释即可表达意图

Recoverable vs Non-Recoverable Errors

错误处理原则

错误分类

Recoverable (4xx - User can fix):
  • Invalid input, missing fields, wrong format
  • Action: Allow retry with corrected input
  • Response: Detailed error message with guidance
Non-Recoverable (5xx - System issue):
  • Database down, disk full, out of memory
  • Action: Log details, alert ops team, return safe generic error
  • Response: Generic message, correlation ID for support
1. 校验错误(4xx):
  • 用户输入不符合要求(格式错误、字段缺失、超出范围)
  • 示例:无效邮箱、密码过短、必填字段缺失
  • 响应:400 Bad Request,附带详细的字段级别错误
  • 用户可修复:是,修正输入即可
2. 业务错误(4xx):
  • 违反领域规则(余额不足、邮箱重复、订单已发货)
  • 示例:无法删除有活跃订单的用户、30天后无法处理退款
  • 响应:400/409/422,附带业务规则说明
  • 用户可修复:视业务场景而定
3. 认证错误(401):
  • 身份验证失败(无效凭证、token过期、token缺失)
  • 响应:401 Unauthorized
  • 用户可修复:是,提供有效凭证即可
4. 授权错误(403):
  • 权限不足(用户已认证但没有对应权限)
  • 响应:403 Forbidden
  • 用户可修复:否,需要管理员介入
5. 未找到错误(404):
  • 资源不存在,或用户没有权限知道资源存在
  • 响应:404 Not Found
  • 用户可修复:否
6. 基础设施错误(5xx):
  • 数据库宕机、网络超时、外部服务故障、内存不足
  • 响应:500/502/503,附带通用提示信息
  • 用户可修复:否,属于系统问题

Universal Error Handling Principles

可恢复 vs 不可恢复错误

1. Never Fail Silently:
  • All errors must be handled explicitly (no empty catch blocks)
  • If you catch an error, do something with it (log, return, transform, retry)
2. Fail Fast:
  • Detect and report errors as early as possible
  • Validate at system boundaries before processing
  • Don't process invalid data hoping it'll work out
3. Provide Context:
  • Include error codes, correlation IDs, actionable messages
  • Enough information for debugging without exposing sensitive details
  • Example: "Database query failed (correlation-id: abc-123)" not "SELECT * FROM users WHERE..."
4. Separate Concerns:
  • Different handlers for different error types
  • Business errors ≠ technical errors ≠ security errors
5. Resource Cleanup:
  • Always clean up in error scenarios (close files, release connections, unlock resources)
  • Use language-appropriate patterns (defer, finally, RAII, context managers)
6. No Information Leakage:
  • Sanitize error messages for external consumption
  • Don't expose stack traces, SQL queries, file paths, internal structure to users
  • Log full details internally, show generic message externally
可恢复(4xx - 用户可修复):
  • 无效输入、字段缺失、格式错误
  • 处理方式:允许用修正后的输入重试
  • 响应:附带指导信息的详细错误消息
不可恢复(5xx - 系统问题):
  • 数据库宕机、磁盘已满、内存不足
  • 处理方式:记录详细日志、告警运维团队、返回安全的通用错误
  • 响应:通用消息、用于支持排查的关联ID

Application Error Object (Internal/Log Format)

通用错误处理原则

{
  "status": "error",
  "code": "VALIDATION_ERROR",
  "message": "User-friendly error message",
  "correlationId": "uuid-for-tracking",
  "details": {
    "field": "email",
    "issue": "Invalid email format",
    "provided": "invalid-email",
    "expected": "valid email format (user@example.com)"
  }
}
1. 永不静默失败:
  • 所有错误必须显式处理(无空catch块)
  • 如果你捕获了错误,必须做相应处理(记录日志、返回、转换、重试)
2. 快速失败:
  • 尽可能早地检测并报告错误
  • 处理前在系统边界做校验
  • 不要处理无效数据抱有侥幸心理
3. 提供上下文:
  • 包含错误码、关联ID、可操作的消息
  • 提供足够的调试信息,同时不暴露敏感细节
  • 示例:"数据库查询失败(关联ID: abc-123)",而非"SELECT * FROM users WHERE..."
4. 关注点分离:
  • 不同错误类型使用不同的handler
  • 业务错误 ≠ 技术错误 ≠ 安全错误
5. 资源清理:
  • 错误场景下始终要清理资源(关闭文件、释放连接、解锁资源)
  • 使用语言适配的模式(defer、finally、RAII、上下文管理器)
6. 无信息泄露:
  • 对外返回的错误消息做脱敏处理
  • 不要向用户暴露栈跟踪、SQL查询、文件路径、内部结构
  • 内部记录完整详情,对外展示通用消息

Error Handling Checklist

应用错误对象(内部/日志格式)

  • Are all error paths explicitly handled (no empty catch blocks)?
  • Do errors include correlation IDs for debugging?
  • Are sensitive details sanitized before returning to client?
  • Are resources cleaned up in all error scenarios?
  • Are errors logged at appropriate levels (warn for 4xx, error for 5xx)?
  • Are error tests written (negative test cases)?
  • Is error handling consistent across application?
{
  "status": "error",
  "code": "VALIDATION_ERROR",
  "message": "用户友好的错误消息",
  "correlationId": "用于追踪的uuid",
  "details": {
    "field": "email",
    "issue": "无效的邮箱格式",
    "provided": "invalid-email",
    "expected": "有效的邮箱格式(user@example.com)"
  }
}

Related Principles

错误处理检查清单

  • 所有错误路径都显式处理(无空catch块)?
  • 错误都包含用于调试的关联ID?
  • 返回给客户端前敏感细节已脱敏?
  • 所有错误场景下资源都已清理?
  • 错误按对应级别记录(4xx为warn、5xx为error)?
  • 已编写错误测试(负向测试用例)?
  • 整个应用的错误处理保持一致?

Concurrency and Threading Principles

关联原则

When to Use Concurrency

I/O-Bound Operations (async/await, event loops):
  • Network requests, file I/O, database queries
  • Waiting for external responses dominates execution time
  • Use: Asynchronous I/O, event-driven concurrency, coroutines
CPU-Bound Operations (threads, parallel processing):
  • Heavy computation, data processing, video encoding
  • CPU cycles dominate execution time
  • Use: OS threads, thread pools, parallel workers
Don't Over-Use Concurrency:
  • Adds significant complexity (race conditions, deadlocks, debugging difficulty)
  • Use only when there's measurable performance benefit
  • Profile first, optimize second

Universal Concurrency Principles

并发与多线程原则

何时使用并发

1. Avoid Race Conditions
What is a race condition:
  • Multiple threads access shared data concurrently
  • At least one thread writes/modifies the data
  • No synchronization mechanism in place
  • Result depends on unpredictable thread execution timing
Prevention strategies:
  • Synchronization: Locks, mutexes, semaphores
  • Immutability: Immutable data is thread-safe by default
  • Message passing: Send data between threads instead of sharing
  • Thread-local storage: Each thread has its own copy
Detection:
  • Go: Run with
    -race
    flag (race detector)
  • Rust: Miri tool for undefined behavior detection
  • C/C++: ThreadSanitizer (TSan)
  • Java: JCStress, FindBugs
2. Prevent Deadlocks
What is a deadlock:
  • Two or more threads waiting for each other indefinitely
  • Example: Thread A holds Lock 1, waits for Lock 2; Thread B holds Lock 2, waits for Lock 1
Four conditions (ALL must be true for deadlock):
  1. Mutual exclusion: Resources held exclusively (locks)
  2. Hold and wait: Holding one resource while waiting for another
  3. No preemption: Can't force unlock
  4. Circular wait: A waits for B, B waits for A
Prevention (break any one condition):
  • Lock ordering: Always acquire locks in same order
  • Timeout: Use try_lock with timeout, back off and retry
  • Avoid nested locks: Don't hold multiple locks simultaneously
  • Use lock-free data structures when possible
3. Prefer Immutability
  • Immutable data = thread-safe by default (no synchronization needed)
  • Share immutable data freely between threads
  • Use immutable data structures where possible (Rust default, functional languages)
  • If data must change, use message passing instead of shared mutable state
4. Message Passing Over Shared Memory
  • "Don't communicate by sharing memory; share memory by communicating" (Go proverb)
  • Send data through channels/queues instead of accessing shared memory
  • Reduces need for locks and synchronization
  • Easier to reason about and test
5. Graceful Degradation
  • Handle concurrency errors gracefully (timeouts, retries, circuit breakers)
  • Don't crash entire application on one thread failure
  • Use supervisors/monitors for fault tolerance (Erlang/Elixir actor model)
  • Implement backpressure for producer-consumer scenarios
I/O密集型操作(async/await、事件循环):
  • 网络请求、文件I/O、数据库查询
  • 等待外部响应占主导执行时间
  • 使用:异步I/O、事件驱动并发、协程
CPU密集型操作(线程、并行处理):
  • 重型计算、数据处理、视频编码
  • CPU周期占主导执行时间
  • 使用:OS线程、线程池、并行工作器
不要过度使用并发:
  • 会增加显著的复杂性(竞态条件、死锁、调试难度)
  • 只有在有可测量的性能收益时才使用
  • 先做性能分析,再优化

Concurrency Models by Use Case

通用并发原则

  • I/O-bound: async/await, event loops, coroutines, green threads
  • CPU-bound: OS threads, thread pools, parallel processing
  • Actor model: Erlang/Elixir actors, Akka (message passing, isolated state)
  • CSP (Communicating Sequential Processes): Go channels, Rust channels
1. 避免竞态条件 什么是竞态条件:
  • 多个线程同时访问共享数据
  • 至少有一个线程写入/修改数据
  • 没有同步机制
  • 结果取决于不可预测的线程执行时序
预防策略:
  • 同步:锁、互斥量、信号量
  • 不可变性:不可变数据默认是线程安全的
  • 消息传递:在线程之间发送数据,而非共享
  • 线程本地存储:每个线程有自己的副本
检测:
  • Go:带
    -race
    flag运行(竞态检测器)
  • Rust:Miri工具检测未定义行为
  • C/C++:ThreadSanitizer(TSan)
  • Java:JCStress、FindBugs
2. 预防死锁 什么是死锁:
  • 两个或多个线程无限期互相等待
  • 示例:线程A持有锁1,等待锁2;线程B持有锁2,等待锁1
四个必要条件(死锁发生必须全部满足):
  1. 互斥:资源被独占持有(锁)
  2. 持有并等待:持有一个资源的同时等待另一个
  3. 不可抢占:不能强制解锁
  4. 循环等待:A等待B,B等待A
预防(打破任意一个条件即可):
  • 锁顺序:始终按相同顺序获取锁
  • 超时:使用带超时的try_lock,退避后重试
  • 避免嵌套锁:不要同时持有多个锁
  • 尽可能使用无锁数据结构
3. 优先使用不可变性
  • 不可变数据 = 默认线程安全(无需同步)
  • 可以在线程之间自由共享不可变数据
  • 尽可能使用不可变数据结构(Rust默认、函数式语言)
  • 如果数据必须变更,使用消息传递而非共享可变状态
4. 消息传递优于共享内存
  • "不要通过共享内存来通信,要通过通信来共享内存"(Go谚语)
  • 通过通道/队列发送数据,而非访问共享内存
  • 减少对锁和同步的需求
  • 更易于理解和测试
5. 优雅降级
  • 优雅处理并发错误(超时、重试、断路器)
  • 不要因为单个线程失败导致整个应用崩溃
  • 使用监管器/监控器实现容错(Erlang/Elixir actor模型)
  • 生产者-消费者场景下实现背压

Testing Concurrent Code

按场景选择并发模型

  • Write unit tests with controlled concurrency (deterministic execution)
  • Test timeout scenarios and resource exhaustion
  • Test thread pool full, queue full scenarios
  • I/O密集型: async/await、事件循环、协程、绿色线程
  • CPU密集型: OS线程、线程池、并行处理
  • Actor模型: Erlang/Elixir actors、Akka(消息传递、隔离状态)
  • CSP(通信顺序进程): Go通道、Rust通道

Related Principles

并发代码测试

  • 编写可控并发的单元测试(确定性执行)
  • 测试超时场景和资源耗尽场景
  • 测试线程池满、队列满场景

Resource and Memory Management Principles

关联原则

Universal Resource Management Rules

1. Always Clean Up Resources
Resources requiring cleanup:
  • Files, network connections, database connections
  • Locks, semaphores, mutexes
  • Memory allocations (in manual-memory languages)
  • OS handles, GPU resources
Clean up in ALL paths:
  • Success path: Normal completion
  • Error path: Exception thrown, error returned
  • Early return path: Guard clauses, validation failures
Use language-appropriate patterns:
  • Go: defer statements
  • Rust: Drop trait (RAII)
  • Python: context managers (with statement)
  • TypeScript: try/finally
  • Java: try-with-resources
2. Timeout All I/O Operations
Why timeout:
  • Network requests can hang indefinitely
  • Prevents resource exhaustion (connections, threads)
  • Provides predictable failure behavior
Timeout recommendations:
  • Network requests: 30s default, shorter (5-10s) for interactive
  • Database queries: 10s default, configure per query complexity
  • File operations: Usually fast, but timeout on network filesystems
  • Message queue operations: Configurable, avoid indefinite blocking
3. Pool Expensive Resources
Resources to pool:
  • Database connections: Pool size 5-20 per app instance
  • HTTP connections: Reuse with keep-alive
  • Thread pools: Size based on CPU count (CPU-bound) or I/O wait (I/O-bound)
Benefits:
  • Reduces latency (no connection setup overhead)
  • Limits resource consumption (cap on max connections)
  • Improves throughput (reuse vs create new)
Connection Pool Best Practices:
  • Minimum connections: 5 (ensures pool is warm)
  • Maximum connections: 20-50 (prevents overwhelming database)
  • Idle timeout: Close connections idle >5-10 minutes
  • Validation: Test connections before use (avoid broken connections)
  • Monitoring: Track utilization, wait times, timeout rates
4. Avoid Resource Leaks
What is a leak:
  • Acquire resource (open file, allocate memory, get connection)
  • Never release it (forget to close, exception prevents cleanup)
  • Eventually exhaust system resources (OOM, max connections, file descriptors)
Detection:
  • Monitor open file descriptors, connection counts, memory usage over time
  • Run long-duration tests, verify resource counts stay stable
  • Use leak detection tools (valgrind, ASan, heap profilers)
Prevention:
  • Use language patterns that guarantee cleanup (RAII, defer, context managers)
  • Never rely on manual cleanup alone (use language features)
5. Handle Backpressure
Problem: Producer faster than consumer
  • Queue grows unbounded → memory exhaustion
  • System becomes unresponsive under load
Solutions:
  • Bounded queues: Fixed size, block or reject when full
  • Rate limiting: Limit incoming request rate
  • Flow control: Consumer signals producer to slow down
  • Circuit breakers: Stop accepting requests when overwhelmed
  • Drop/reject: Fail fast when overloaded (better than crashing)

Memory Management by Language Type

资源与内存管理原则

通用资源管理规则

Garbage Collected (Go, Java, Python, JavaScript, C#):
  • Memory automatically freed by GC
  • Still must release non-memory resources (files, connections, locks)
  • Be aware of GC pauses in latency-sensitive applications
  • Profile memory usage to find leaks (retained references preventing GC)
Manual Memory Management (C, C++):
  • Explicit malloc/free or new/delete
  • Use RAII pattern in C++ (Resource Acquisition Is Initialization)
  • Avoid manual management in modern C++ (use smart pointers: unique_ptr, shared_ptr)
Ownership-Based (Rust):
  • Compiler enforces memory safety at compile time
  • No GC pauses, no manual management
  • Ownership rules prevent leaks and use-after-free automatically
  • Use reference counting (Arc, Rc) for shared ownership
1. 始终清理资源 需要清理的资源:
  • 文件、网络连接、数据库连接
  • 锁、信号量、互斥量
  • 内存分配(手动内存管理语言)
  • OS句柄、GPU资源
所有路径下都要清理:
  • 成功路径:正常完成
  • 错误路径:抛出异常、返回错误
  • 提前返回路径:守卫子句、校验失败
使用语言适配的模式:
  • Go:defer语句
  • Rust:Drop trait(RAII)
  • Python:上下文管理器(with语句)
  • TypeScript:try/finally
  • Java:try-with-resources
2. 所有I/O操作设置超时 为什么要超时:
  • 网络请求可能无限期挂起
  • 防止资源耗尽(连接、线程)
  • 提供可预测的失败行为
超时建议:
  • 网络请求:默认30s,交互场景更短(5-10s)
  • 数据库查询:默认10s,根据查询复杂度配置
  • 文件操作:通常很快,但网络文件系统需要设置超时
  • 消息队列操作:可配置,避免无限阻塞
3. 池化昂贵资源 需要池化的资源:
  • 数据库连接:每个应用实例池大小5-20
  • HTTP连接:通过keep-alive复用
  • 线程池:大小基于CPU核数(CPU密集型)或I/O等待(I/O密集型)
优势:
  • 降低延迟(无连接建立开销)
  • 限制资源消耗(最大连接数上限)
  • 提升吞吐量(复用而非新建)
连接池最佳实践:
  • 最小连接数:5(保证池预热)
  • 最大连接数:20-50(避免压垮数据库)
  • 空闲超时:关闭空闲超过5-10分钟的连接
  • 校验:使用前测试连接(避免无效连接)
  • 监控:追踪利用率、等待时间、超时率
4. 避免资源泄露 什么是泄露:
  • 获取资源(打开文件、分配内存、获取连接)
  • 从未释放(忘记关闭、异常阻止清理)
  • 最终耗尽系统资源(OOM、最大连接数、文件描述符)
检测:
  • 长期监控打开的文件描述符、连接数、内存使用
  • 运行长时间测试,验证资源计数保持稳定
  • 使用泄露检测工具(valgrind、ASan、堆分析器)
预防:
  • 使用可保证清理的语言模式(RAII、defer、上下文管理器)
  • 不要仅依赖手动清理(使用语言特性)
5. 处理背压 问题: 生产者速度快于消费者
  • 队列无限增长 → 内存耗尽
  • 负载下系统无响应
解决方案:
  • 有界队列:固定大小,满时阻塞或拒绝
  • 限流:限制传入请求速率
  • 流控:消费者通知生产者减速
  • 断路器:过载时停止接收请求
  • 丢弃/拒绝:过载时快速失败(好过崩溃)

Related Principles

按语言类型区分的内存管理

垃圾回收语言(Go、Java、Python、JavaScript、C#):
  • GC自动释放内存
  • 仍然需要释放非内存资源(文件、连接、锁)
  • 延迟敏感应用需要注意GC暂停
  • 分析内存使用以查找泄露(阻止GC的保留引用)
手动内存管理语言(C、C++):
  • 显式malloc/free或new/delete
  • C++中使用RAII模式(资源获取即初始化)
  • 现代C++中避免手动管理(使用智能指针:unique_ptr、shared_ptr)
基于所有权的语言(Rust):
  • 编译器在编译时强制内存安全
  • 无GC暂停、无手动管理
  • 所有权规则自动防止泄露和释放后使用
  • 共享所有权使用引用计数(Arc、Rc)

API Design Principles

关联原则

RESTful API Standards

Resource-Based URLs:
  • Use plural nouns for resources:
    /api/{version}/users
    ,
    /api/{version}/orders
  • Hierarchical relationships:
    /api/{version}/users/:userId/orders
  • Avoid verbs in URLs:
    /api/{version}/getUser
    ❌ →
    /api/{version}/users/:id
HTTP Methods:
  • GET: Read/retrieve resource (safe, idempotent, cacheable)
  • POST: Create new resource (not idempotent)
  • PUT: Replace entire resource (idempotent)
  • PATCH: Partial update (idempotent)
  • DELETE: Remove resource (idempotent)
HTTP Status Codes:
  • 200 OK: Success (GET, PUT, PATCH)
  • 201 Created: Resource created successfully (POST)
  • 204 No Content: Success with no response body (DELETE)
  • 400 Bad Request: Invalid input, validation failure
  • 401 Unauthorized: Authentication required or failed
  • 403 Forbidden: Authenticated but insufficient permissions
  • 404 Not Found: Resource doesn't exist
  • 409 Conflict: Conflict with current state (duplicate)
  • 422 Unprocessable Entity: Validation errors
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Unexpected server error
  • 502 Bad Gateway: Upstream service failure
  • 503 Service Unavailable: Temporary unavailability
Versioning:
  • URL path versioning:
    /api/{version}/users
    e.g.
    /api/v1/users
    (explicit, clear)
Pagination:
  • Limit results per page (default 20, max 100)
  • Cursor-based:
    ?cursor=abc123
    (better for real-time data)
  • Offset-based:
    ?page=2&limit=20
    (simpler, less accurate for changing data)
Filtering and Sorting:
  • Filtering:
    ?status=active&role=admin
  • Sorting:
    ?sort=created_at:desc,name:asc
  • Searching:
    ?q=search+term
Response Format:
{
  "data": { /* resource or array of resources */ },
  "meta": {
    "total": 100,
    "page": 1,
    "perPage": 20
  },
  "links": {
    "self": "/api/v1/users?page=1",
    "next": "/api/v1/users?page=2",
    "prev": null
  }
}
API Error Response Format:
All API errors must follow a consistent envelope structure, matching the success format where possible or using a standard error envelope.
{
  "status": "error",                      // Transport: Always "error" or "fail"
  "code": 400,                            // Transport: Redundant HTTP Status
  "error": {                              // Domain: The actual business problem
    "code": "VALIDATION_ERROR",           // Machine-readable business code (UPPER_SNAKE)
    "message": "Invalid email format",    // Human-readable message
    "details": {                          // Optional: Structured context
      "field": "email",
      "reason": "Must be a valid address"
    },
  "correlationId": "req-1234567890",      // Ops: Traceability
  "doc_url": "https://..."                // Optional: Help link
  }
}

Related Principles

API设计原则

RESTful API标准

基于资源的URL:
  • 资源使用复数名词:
    /api/{version}/users
    /api/{version}/orders
  • 层级关系:
    /api/{version}/users/:userId/orders
  • URL中避免动词:
    /api/{version}/getUser
    ❌ →
    /api/{version}/users/:id
HTTP方法:
  • GET:读取/检索资源(安全、幂等、可缓存)
  • POST:创建新资源(非幂等)
  • PUT:替换整个资源(幂等)
  • PATCH:部分更新(幂等)
  • DELETE:删除资源(幂等)
HTTP状态码:
  • 200 OK:成功(GET、PUT、PATCH)
  • 201 Created:资源创建成功(POST)
  • 204 No Content:成功且无响应体(DELETE)
  • 400 Bad Request:无效输入、校验失败
  • 401 Unauthorized:需要认证或认证失败
  • 403 Forbidden:已认证但权限不足
  • 404 Not Found:资源不存在
  • 409 Conflict:与当前状态冲突(重复)
  • 422 Unprocessable Entity:校验错误
  • 429 Too Many Requests:超出限流
  • 500 Internal Server Error:意外服务端错误
  • 502 Bad Gateway:上游服务故障
  • 503 Service Unavailable:临时不可用
版本控制:
  • URL路径版本控制:
    /api/{version}/users
    例如
    /api/v1/users
    (显式、清晰)
分页:
  • 每页结果限制(默认20,最大100)
  • 游标分页:
    ?cursor=abc123
    (更适合实时数据)
  • 偏移分页:
    ?page=2&limit=20
    (更简单,数据变化时准确性较低)
过滤与排序:
  • 过滤:
    ?status=active&role=admin
  • 排序:
    ?sort=created_at:desc,name:asc
  • 搜索:
    ?q=search+term
响应格式:
{
  "data": { /* 资源或资源数组 */ },
  "meta": {
    "total": 100,
    "page": 1,
    "perPage": 20
  },
  "links": {
    "self": "/api/v1/users?page=1",
    "next": "/api/v1/users?page=2",
    "prev": null
  }
}
API错误响应格式: 所有API错误必须遵循一致的信封结构,尽可能匹配成功格式,或使用标准错误信封。
{
  "status": "error",                      // 传输层:始终为"error"或"fail"
  "code": 400,                            // 传输层:冗余HTTP状态
  "error": {                              // 领域层:实际业务问题
    "code": "VALIDATION_ERROR",           // 机器可读业务码(大写下划线格式)
    "message": "无效的邮箱格式",    // 人类可读消息
    "details": {                          // 可选:结构化上下文
      "field": "email",
      "reason": "必须是有效的地址"
    },
  "correlationId": "req-1234567890",      // 运维层:可追溯性
  "doc_url": "https://..."                // 可选:帮助链接
  }
}

Testing Strategy

关联原则

Test Pyramid

Unit Tests (70% of tests):
  • What: Test domain logic in isolation with mocked dependencies
  • Speed: Fast (<100ms per test)
  • Scope: Single function, class, or module
  • Dependencies: All external dependencies mocked (repositories, APIs, time, random)
  • Coverage Goal: >85% of domain logic
Integration Tests (20% of tests):
  • What: Test adapters against real infrastructure
  • Speed: Medium (100ms-5s per test)
  • Scope: Component interaction with infrastructure (database, cache, message queue)
  • Dependencies: Real infrastructure via Testcontainers
  • Coverage Goal: All adapter implementations, critical integration points
End-to-End Tests (10% of tests):
  • What: Test complete user journeys through all layers
  • Speed: Slow (5s-30s per test)
  • Scope: Full system from HTTP request to database and back
  • Dependencies: Entire system running (or close approximation)
  • Coverage Goal: Happy paths, critical business flows

Test-Driven Development (TDD)

测试策略

测试金字塔

Red-Green-Refactor Cycle:
  1. Red: Write a failing test for next bit of functionality
  2. Green: Write minimal code to make test pass
  3. Refactor: Clean up code while keeping tests green
  4. Repeat: Next test
Benefits:
  • Tests written first ensure testable design
  • Comprehensive test coverage (code without test doesn't exist)
  • Faster development (catch bugs immediately, not in QA)
  • Better design (forces thinking about interfaces before implementation)
单元测试(70%的测试):
  • 测试范围: 隔离测试领域逻辑,依赖全部mock
  • 速度: 快(每个测试<100ms)
  • 覆盖范围: 单个函数、类或模块
  • 依赖: 所有外部依赖都被mock(仓库、API、时间、随机数)
  • 覆盖率目标: 领域逻辑>85%
集成测试(20%的测试):
  • 测试范围: 测试适配器与真实基础设施的交互
  • 速度: 中等(每个测试100ms-5s)
  • 覆盖范围: 组件与基础设施的交互(数据库、缓存、消息队列)
  • 依赖: 通过Testcontainers使用真实基础设施
  • 覆盖率目标: 所有适配器实现、关键集成点
端到端测试(10%的测试):
  • 测试范围: 测试跨所有层的完整用户旅程
  • 速度: 慢(每个测试5s-30s)
  • 覆盖范围: 从HTTP请求到数据库再返回的完整系统
  • 依赖: 整个系统运行(或近似运行)
  • 覆盖率目标: happy path、关键业务流程

Test Doubles Strategy

测试驱动开发(TDD)

Unit Tests: Use mocks/stubs for all driven ports
  • Mock repositories return pre-defined data
  • Mock external APIs return successful responses
  • Mock time/random for deterministic tests
  • Control test environment completely
Integration Tests: Use real infrastructure
  • Testcontainers spins up PostgreSQL, Redis, message queues
  • Firebase emulator spins up Firebase Authentication, Cloud Firestore, Realtime Database, Cloud Storage for Firebase, Firebase Hosting, Cloud Functions, Pub/Sub, and Firebase Extensions
  • Test actual database queries, connection handling, transactions
  • Verify adapter implementations work with real services
Best Practice:
  • Generate at least 2 implementations per driven port:
    1. Production adapter (PostgreSQL, GCP GCS, etc.)
    2. Test adapter (in-memory, fake implementation)
红-绿-重构循环:
  1. 红: 为下一个功能点编写失败的测试
  2. 绿: 编写最小化代码让测试通过
  3. 重构: 清理代码,保持测试通过
  4. 重复: 下一个测试
优势:
  • 先写测试保证可测试的设计
  • 全面的测试覆盖率(没有测试的代码不存在)
  • 更快的开发速度(立即发现bug,而非到QA阶段才发现)
  • 更好的设计(强制在实现前思考接口)

Test Organization

测试替身策略

Universal Rule: Co-locate implementation tests; Separate system tests.
1. Unit & Integration Tests (Co-located)
  • Rule: Place tests next to the file they test.
  • Why: Keeps tests visible, encourages maintenance, and supports refactoring (moving a file moves its tests).
  • Naming Convention Example:
    • TS/JS:
      *.spec.ts
      (Unit),
      *.integration.spec.ts
      (Integration)
    • Go:
      *_test.go
      (Unit),
      *_integration_test.go
      (Integration)
    • Python:
      test_*.py
      (Unit),
      test_*_integration.py
      (Integration)
    • Java:
      *Test.java
      (Unit),
      *IT.java
      (Integration)
    You must strictly follow the convention for the target language. Do not mix
    test
    and
    spec
    suffixes in the same application context.
2. End-to-End Tests (Separate)
  • Rule: Place in a dedicated
    e2e/
    folder
    • Single Service:
      e2e/
      at project root
    • Monorepo:
      apps/e2e/
      subdivided by test scope:
      • apps/e2e/api/
        for full API flow E2E tests (HTTP → Database)
      • apps/e2e/ui/
        for full-stack E2E tests (Browser → Backend → Database)
  • Why: E2E tests cross boundaries and don't belong to a single feature.
  • Naming: Follow
    {feature}-{ui/api}.e2e.test.{ext}
    (Universal - configure test runner to match this pattern
    **/*.e2e.test.*
    )
    • Example:
      • user-registration-api.e2e.test.ts
        # Full API flow: HTTP → DB
      • user-registration-ui.e2e.test.ts
        # Full-stack: Browser → Backend → DB
Directory Layout Example:
单元测试: 所有驱动端口使用mocks/stubs
  • Mock仓库返回预定义数据
  • Mock外部API返回成功响应
  • Mock时间/随机数实现确定性测试
  • 完全控制测试环境
集成测试: 使用真实基础设施
  • Testcontainers启动PostgreSQL、Redis、消息队列
  • Firebase模拟器启动Firebase Authentication、Cloud Firestore、Realtime Database、Cloud Storage for Firebase、Firebase Hosting、Cloud Functions、Pub/Sub和Firebase Extensions
  • 测试真实的数据库查询、连接处理、事务
  • 验证适配器实现可与真实服务正常工作
最佳实践:
  • 每个驱动端口至少实现2个版本:
    1. 生产适配器(PostgreSQL、GCP GCS等)
    2. 测试适配器(内存、假实现)

A. Backend (Go - Feature-Based)

测试组织

apps/
  backend/
    task/
      task.go                      # API handlers (public interface)
      task_test.go                 # Unit tests (mocked dependencies)
      business.go                  # Pure business logic
      business_test.go             # Unit tests (pure functions)
      store.go                     # interface TaskStore
      postgres.go                  # implements TaskStore
      postgres_integration_test.go # Integration tests (real DB)
      mock_store.go               # Test implementation
    migrations/
      001_create_tasks.up.sql
    user/
      user.go
      user_test.go
      store.go
      postgres.go
      postgres_integration_test.go
e2e/
  task_crud_api.e2e.test.go       # Full API flow
通用规则: 实现测试与代码放在一起,系统测试单独存放。 1. 单元与集成测试(同目录存放)
  • 规则: 测试放在它们测试的文件旁边
  • 原因: 保持测试可见,鼓励维护,支持重构(移动文件时同步移动测试)。
  • 命名约定示例:
    • TS/JS:
      *.spec.ts
      (单元测试)、
      *.integration.spec.ts
      (集成测试)
    • Go:
      *_test.go
      (单元测试)、
      *_integration_test.go
      (集成测试)
    • Python:
      test_*.py
      (单元测试)、
      test_*_integration.py
      (集成测试)
    • Java:
      *Test.java
      (单元测试)、
      *IT.java
      (集成测试)
    必须严格遵循目标语言的约定,同一个应用上下文中不要混合使用
    test
    spec
    后缀。
2. 端到端测试(单独存放)
  • 规则: 放在专用的
    e2e/
    文件夹
    • 单服务: 项目根目录下的
      e2e/
    • Monorepo:
      apps/e2e/
      按测试范围细分:
      • apps/e2e/api/
        存放全API流E2E测试(HTTP → 数据库)
      • apps/e2e/ui/
        存放全栈E2E测试(浏览器 → 后端 → 数据库)
  • 原因: E2E测试跨边界,不属于单个功能。
  • 命名: 遵循
    {feature}-{ui/api}.e2e.test.{ext}
    (通用 - 配置测试运行器匹配
    **/*.e2e.test.*
    模式)
    • 示例:
      • user-registration-api.e2e.test.ts
        # 全API流:HTTP → DB
      • user-registration-ui.e2e.test.ts
        # 全栈:浏览器 → 后端 → DB
目录布局示例:

B. Frontend (Vue - Feature-Sliced)

A. 后端(Go - 按功能组织)


apps/
  frontend/
    src/
      features/
        task/
          index.ts                 # Public exports
          task.service.ts          # Business logic
          task.service.spec.ts     # Unit tests
          task.api.ts              # interface TaskAPI
          task.api.encore.ts       # Production implementation
          task.api.mock.ts         # Test implementation
          task.store.ts            # Pinia store
          task.store.spec.ts       # Store unit tests
        auth/
        ...
      components/
        TaskInput.vue
        TaskInput.spec.ts          # Component unit tests
e2e/
  task-management-flow.e2e.test.ts  # Full UI journey
apps/
  backend/
    task/
      task.go                      # API handler(公共接口)
      task_test.go                 # 单元测试(mock依赖)
      business.go                  # 纯业务逻辑
      business_test.go             # 单元测试(纯函数)
      store.go                     # interface TaskStore
      postgres.go                  # implements TaskStore
      postgres_integration_test.go # 集成测试(真实数据库)
      mock_store.go               # 测试实现
    migrations/
      001_create_tasks.up.sql
    user/
      user.go
      user_test.go
      store.go
      postgres.go
      postgres_integration_test.go
e2e/
  task_crud_api.e2e.test.go       # 全API流

C. Monorepo (Multi-Stack)

B. 前端(Vue - 按功能切片)


apps/
  backend/
    task/
    ...
  frontend/
    src/features/task/
    ...
e2e/                             # Shared E2E suite
  api/
    task-crud-api.e2e.test.ts    # Backend-only E2E
  ui/
    checkout-flow.e2e.test.ts    # Full-stack E2E
Key Principles:
  • Unit/Integration tests: Co-located with implementation
  • E2E tests: Separate directory (crosses boundaries)
  • Test doubles: Co-located with interface (mock_store.go, taskAPI.mock.ts)
  • Pattern consistency: All features follow same structure
apps/
  frontend/
    src/
      features/
        task/
          index.ts                 # 公共导出
          task.service.ts          # 业务逻辑
          task.service.spec.ts     # 单元测试
          task.api.ts              # interface TaskAPI
          task.api.encore.ts       # 生产实现
          task.api.mock.ts         # 测试实现
          task.store.ts            # Pinia store
          task.store.spec.ts       # Store单元测试
        auth/
        ...
      components/
        TaskInput.vue
        TaskInput.spec.ts          # 组件单元测试
e2e/
  task-management-flow.e2e.test.ts  # 全UI流程

Test Quality Standards

C. Monorepo(多技术栈)

AAA Pattern (Arrange-Act-Assert):
// Arrange: Set up test data and mocks
const user = { id: '123', email: 'test@example.com' };
const mockRepo = createMockRepository();

// Act: Execute the code under test
const result = await userService.createUser(user);

// Assert: Verify expected outcome
expect(result.id).toBe('123');
expect(mockRepo.save).toHaveBeenCalledWith(user);
Test Naming:
  • Descriptive:
    should [expected behavior] when [condition]
  • Examples:
    • should return 404 when user not found
    • should hash password before saving to database
    • should reject email with invalid format
Coverage Requirements:
  • Unit tests: >85% code coverage
  • Integration tests: All adapter implementations
  • E2E tests: Critical user journeys
apps/
  backend/
    task/
    ...
  frontend/
    src/features/task/
    ...
e2e/                             # 共享E2E套件
  api/
    task-crud-api.e2e.test.ts    # 仅后端E2E
  ui/
    checkout-flow.e2e.test.ts    # 全栈E2E
核心原则:
  • 单元/集成测试:与实现代码放在一起
  • E2E测试:单独目录(跨边界)
  • 测试替身:与接口放在一起(mock_store.go、taskAPI.mock.ts)
  • 模式一致性:所有功能遵循相同结构

Related Principles

测试质量标准

AAA模式(安排-执行-断言):
// 安排:设置测试数据和mocks
const user = { id: '123', email: 'test@example.com' };
const mockRepo = createMockRepository();

// 执行:运行被测代码
const result = await userService.createUser(user);

// 断言:验证预期结果
expect(result.id).toBe('123');
expect(mockRepo.save).toHaveBeenCalledWith(user);
测试命名:
  • 描述性:
    should [预期行为] when [条件]
  • 示例:
    • should return 404 when user not found
    • should hash password before saving to database
    • should reject email with invalid format
覆盖率要求:
  • 单元测试:代码覆盖率>85%
  • 集成测试:覆盖所有适配器实现
  • E2E测试:覆盖关键用户旅程

Configuration Management Principles

关联原则

Separation of Configuration and Code

Configuration:
  • Environment-specific values (URLs, credentials, feature flags, timeouts)
  • Changes between dev/staging/prod
  • Can change without code deployment
Code:
  • Business logic and application behavior
  • Same across all environments
  • Requires deployment to change
Never hardcode configuration in code:
  • const DB_URL = "postgresql://prod-db:5432/myapp"
  • const DB_URL = process.env.DATABASE_URL

Configuration Validation

配置管理原则

配置与代码分离

Validate at startup:
  • Check all required configuration is present
  • Fail fast if required config is missing or invalid
  • Provide clear error messages for misconfiguration
  • Example: "DATABASE_URL environment variable is required"
Validation checks:
  • Type (string, number, boolean, enum)
  • Format (URL, email, file path)
  • Range (port numbers 1-65535)
  • Dependencies (if feature X enabled, config Y required)
配置:
  • 环境专属值(URL、凭证、功能开关、超时时间)
  • 开发/ staging/生产环境不同
  • 无需代码部署即可变更
代码:
  • 业务逻辑和应用行为
  • 所有环境相同
  • 需要部署才能变更
禁止在代码中硬编码配置:
  • const DB_URL = "postgresql://prod-db:5432/myapp"
  • const DB_URL = process.env.DATABASE_URL

Configuration Hierarchy

配置校验

Precedence (highest to lowest):
  1. Command-line arguments: Override everything (for testing, debugging)
  2. Environment variables: Override config files
  3. Config files: Environment-specific (config.prod.yaml, config.dev.yaml)
  4. Defaults: Reasonable defaults in code (fallback)
Example:
Database port resolution:
  1. Check CLI arg: --db-port=5433
  2. Check env var: DB_PORT=5432
  3. Check config file: database.port=5432
  4. Use default: 5432
启动时校验:
  • 检查所有必填配置是否存在
  • 必填配置缺失或无效时快速失败
  • 为配置错误提供清晰的错误消息
  • 示例:"需要DATABASE_URL环境变量"
校验项:
  • 类型(字符串、数字、布尔、枚举)
  • 格式(URL、邮箱、文件路径)
  • 范围(端口号1-65535)
  • 依赖(如果启用功能X,需要配置Y)

Configuration Organization

配置优先级

Hybrid Approach (config files + .env files): define the structure of configuration in config files (e.g. config/database.yaml) and use .env files to inject the secret values.
.env files: Description: A file dedicated to a specific environment (development) for production these values comes from secrets/environment platfrom or manager not a physical
.env
file on disk. When to Use: Use this only for secrets (API keys, passwords) and a few environment-specific values (like a server IP). These files except
.env.template
should never be committed to version control (git).
  • .env.template
    - Consist of credentials and secrets with blank value (SHOULD commit to git)
  • .env.development
    - Local development credentials and secrets (SHOULD NOT commit to git)
Example
.env.development
:
DEV_DB_HOST=123.45.67.89
DEV_DB_USERNAME=prod_user
DEV_DB_PASSWORD=a_very_secure_production_password
Feature files: Description: Settings are grouped into files based on what they do (database, auth, etc.). This keeps your configuration organized. When to Use: Use this as your primary method for organizing non-secret settings. It’s the best way to keep your configuration clean and scalable as your application grows.
  • config/database.yaml
    - Database settings
  • config/redis.yaml
    - Cache settings
  • config/auth.yaml
    - Authentication settings
Example
config/database.yaml
:
default: &default
  adapter: postgresql
  pool: 5
development:
  <<: *default
  host: localhost
  database: myapp_dev
  username: <%= ENV['DEV_DB_USERNAME'] %> # Placeholder for a secret
  password: <%= ENV['DEV_DB_PASSWORD'] %>
production:
  <<: *default
  host: <%= ENV['PROD_DB_HOST'] %>
  database: myapp_prod
  username: <%= ENV['PROD_DB_USERNAME'] %>
  password: <%= ENV['PROD_DB_PASSWORD'] %>
优先级(从高到低):
  1. 命令行参数: 覆盖所有配置(用于测试、调试)
  2. 环境变量: 覆盖配置文件
  3. 配置文件: 环境专属(config.prod.yaml、config.dev.yaml)
  4. 默认值: 代码中的合理默认值(兜底)
示例: 数据库端口解析:
  1. 检查CLI参数:--db-port=5433
  2. 检查环境变量:DB_PORT=5432
  3. 检查配置文件:database.port=5432
  4. 使用默认值:5432

Related Principles

配置组织

混合方案(配置文件 + .env文件):在配置文件(例如config/database.yaml)中定义配置结构,使用.env文件注入密钥值。
.env文件: 描述:专用于特定环境(开发)的文件,生产环境的这些值来自密钥/环境平台或管理器,而非磁盘上的物理
.env
文件。使用场景:仅用于密钥(API密钥、密码)和少量环境专属值(例如服务器IP)。除
.env.template
外,这些文件永远不应该提交到版本控制(git)。
  • .env.template
    - 包含占位符空白值的凭证和密钥清单(应该提交到git)
  • .env.development
    - 本地开发凭证和密钥(不应该提交到git)
示例
.env.development
DEV_DB_HOST=123.45.67.89
DEV_DB_USERNAME=prod_user
DEV_DB_PASSWORD=a_very_secure_production_password
功能配置文件: 描述:按功能分组的设置文件(数据库、鉴权等),保持配置有序。使用场景:作为组织非机密设置的主要方式,是随着应用增长保持配置清晰可扩展的最佳方式。
  • config/database.yaml
    - 数据库设置
  • config/redis.yaml
    - 缓存设置
  • config/auth.yaml
    - 鉴权设置
示例
config/database.yaml
default: &default
  adapter: postgresql
  pool: 5
development:
  <<: *default
  host: localhost
  database: myapp_dev
  username: <%= ENV['DEV_DB_USERNAME'] %> # 密钥占位符
  password: <%= ENV['DEV_DB_PASSWORD'] %>
production:
  <<: *default
  host: <%= ENV['PROD_DB_HOST'] %>
  database: myapp_prod
  username: <%= ENV['PROD_DB_USERNAME'] %>
  password: <%= ENV['PROD_DB_PASSWORD'] %>

Performance Optimization Principles

关联原则

Measure Before Optimizing

"Premature optimization is the root of all evil" - Donald Knuth
Process:
  1. Measure: Profile to find actual bottlenecks (don't guess)
  2. Identify: Find the 20% of code consuming 80% of resources
  3. Optimize: Improve that specific bottleneck
  4. Measure again: Verify improvement with benchmarks
  5. Repeat: Only if still not meeting performance goals
Don't optimize:
  • Code that's "fast enough" for requirements
  • Code that's rarely executed
  • Without measurable performance problem

Choose Appropriate Data Structures

性能优化原则

优化前先测量

Selection matters:
  • Hash map: O(1) lookup, unordered
  • Array/list: O(1) index access, O(n) search, ordered
  • Binary tree: O(log n) operations, sorted order
  • Set: O(1) membership testing, unique elements
Wrong choice causes performance degradation:
  • Using array for lookups: O(n) when O(1) possible with hash map
  • Using list for sorted data: O(n log n) sort vs O(log n) tree operations
"过早优化是万恶之源" - Donald Knuth 流程:
  1. 测量: 性能分析找到实际瓶颈(不要猜测)
  2. 识别: 找到消耗80%资源的20%代码
  3. 优化: 改进特定瓶颈
  4. 再次测量: 通过基准测试验证改进
  5. 重复: 仅在仍未满足性能目标时继续
不要优化:
  • 已经满足性能要求的"足够快"的代码
  • 很少执行的代码
  • 没有可测量的性能问题的代码

Avoid Premature Abstraction

选择合适的数据结构

Abstraction has costs:
  • Runtime overhead (indirection, virtual dispatch, dynamic resolution)
  • Cognitive overhead (understanding layers of abstraction)
  • Maintenance overhead (changes ripple through abstractions)
Start concrete, abstract when pattern emerges:
  • Write straightforward code first
  • Identify duplication and common patterns
  • Abstract only when there's clear benefit
  • Don't add "for future flexibility" without evidence
选择很重要:
  • 哈希表:O(1)查找,无序
  • 数组/列表:O(1)索引访问,O(n)搜索,有序
  • 二叉树:O(log n)操作,有序
  • 集合:O(1)成员检测,元素唯一
错误选择会导致性能下降:
  • 用数组做查找:本可以用哈希表实现O(1),却变成O(n)
  • 用列表存排序数据:本可以用树实现O(log n)操作,却变成O(n log n)排序

Optimization Techniques

避免过早抽象

Caching:
  • Store expensive computation results
  • Cache database queries, API responses, rendered templates
  • Use appropriate cache invalidation strategy
  • Set TTL (time-to-live) for cache entries
Lazy Loading:
  • Compute only when needed
  • Load data on-demand, not upfront
  • Defer expensive operations until required
Batching:
  • Process multiple items together
  • Batch database queries (N queries → 1 query)
  • Batch API requests where possible
Async I/O:
  • Don't block on I/O operations
  • Use async/await for concurrent I/O
  • Process multiple I/O operations in parallel
Connection Pooling:
  • Reuse expensive resources (database connections, HTTP connections)
  • See "Resource and Memory Management Principles"
抽象有成本:
  • 运行时开销(间接调用、虚拟分发、动态解析)
  • 认知开销(理解抽象层)
  • 维护开销(变更扩散到抽象层)
先写具体实现,模式出现后再抽象:
  • 先写直接的代码
  • 识别重复和通用模式
  • 只有在有明确收益时才抽象
  • 不要没有证据就添加「为了未来灵活性」的抽象

Data Serialization and Interchange Principles

优化技术

Validate at System Boundaries

All data entering system must be validated:
  • API requests, file uploads, message queue messages
  • Validate type, format, range, required fields
  • Fail fast on invalid data (don't process partially valid data)
  • Return clear validation errors to client
缓存:
  • 存储昂贵的计算结果
  • 缓存数据库查询、API响应、渲染模板
  • 使用合适的缓存失效策略
  • 为缓存条目设置TTL(生存时间)
懒加载:
  • 需要时才计算
  • 按需加载数据,而非提前加载
  • 推迟昂贵操作到需要时再执行
批量处理:
  • 一起处理多个条目
  • 批量数据库查询(N次查询 → 1次查询)
  • 尽可能批量API请求
异步I/O:
  • I/O操作不阻塞
  • 并发I/O使用async/await
  • 并行处理多个I/O操作
连接池:
  • 复用昂贵资源(数据库连接、HTTP连接)
  • 参见「资源与内存管理原则」

Handle Encoding Explicitly

数据序列化与交换原则

系统边界校验

Default to UTF-8:
  • UTF-8 for all text data (API responses, file contents, database strings)
  • Specify encoding explicitly when reading/writing files
  • Handle encoding errors gracefully (replacement characters or error)
Encoding errors:
  • Invalid UTF-8 sequences (malformed bytes)
  • Mixing encodings (reading UTF-8 as ISO-8859-1)
  • Always validate and normalize encoding
所有进入系统的数据必须校验:
  • API请求、文件上传、消息队列消息
  • 校验类型、格式、范围、必填字段
  • 无效数据快速失败(不要处理部分有效数据)
  • 向客户端返回清晰的校验错误

Serialization Format Selection

显式处理编码

JSON:
  • Human-readable, widely supported, language-agnostic
  • Good for: APIs, configuration files, web applications
  • Limitations: No binary support, larger size than binary formats
Protocol Buffers:
  • Compact binary format, fast serialization/deserialization
  • Schema evolution (backward/forward compatibility)
  • Good for: Internal microservices, high-throughput systems
  • Limitations: Not human-readable, requires schema definition
MessagePack:
  • Binary JSON-like format, faster and more compact than JSON
  • Good for: Internal APIs, when JSON too slow but readability still desired
  • Limitations: Less widely supported than JSON
XML:
  • Verbose, legacy systems, document-oriented
  • Good for: Enterprise systems, SOAP APIs, RSS/Atom feeds
  • Limitations: Verbosity, complexity, security issues (XXE attacks)
YAML:
  • Human-friendly, good for configuration files
  • Good for: Config files, Infrastructure as Code (Kubernetes, CI/CD)
  • Limitations: Complex parsing, performance, security issues (arbitrary code execution)
默认使用UTF-8:
  • 所有文本数据使用UTF-8(API响应、文件内容、数据库字符串)
  • 读写文件时显式指定编码
  • 优雅处理编码错误(替换字符或报错)
编码错误:
  • 无效UTF-8序列(格式错误的字节)
  • 编码混合(将UTF-8当做ISO-8859-1读取)
  • 始终校验并归一化编码

Security Considerations

序列化格式选择

Validate before deserialization:
  • Prevent deserialization attacks (arbitrary code execution)
  • Set size limits on payloads (prevent memory exhaustion)
  • Whitelist allowed types/classes for deserialization
Disable dangerous features:
  • XML: Disable external entity processing (XXE prevention)
  • YAML: Disable unsafe constructors
  • Python pickle: Never deserialize untrusted data
JSON:
  • 人类可读、广泛支持、语言无关
  • 适用场景:API、配置文件、Web应用
  • 限制:无二进制支持,比二进制格式体积大
Protocol Buffers:
  • 紧凑二进制格式,序列化/反序列化速度快
  • schema演进(向后/向前兼容)
  • 适用场景:内部微服务、高吞吐量系统
  • 限制:非人类可读,需要schema定义
MessagePack:
  • 类JSON的二进制格式,比JSON更快更紧凑
  • 适用场景:内部API,JSON太慢但仍需要可读性的场景
  • 限制:支持度不如JSON广泛
XML:
  • 冗长、遗留系统、面向文档
  • 适用场景:企业系统、SOAP API、RSS/Atom feed
  • 限制:冗长、复杂、安全问题(XXE攻击)
YAML:
  • 人类友好,适合配置文件
  • 适用场景:配置文件、基础设施即代码(Kubernetes、CI/CD)
  • 限制:解析复杂、性能低、安全问题(任意代码执行)

Related Principles

安全考虑

反序列化前校验:
  • 防止反序列化攻击(任意代码执行)
  • 设置 payload 大小限制(防止内存耗尽)
  • 反序列化的类型/类使用白名单
禁用危险特性:
  • XML:禁用外部实体处理(预防XXE)
  • YAML:禁用不安全构造函数
  • Python pickle:永远不要反序列化不受信任的数据

Logging and Observability Principles

关联原则

Logging Standards

Log Levels (Standard Priority)

Use consistent log levels across all services:
LevelWhen to UseExamples
TRACEExtremely detailed diagnostic infoFunction entry/exit, variable states (dev only)
DEBUGDetailed flow for debuggingQuery execution, cache hits/misses, state transitions
INFOGeneral informational messagesRequest started, task created, user logged in
WARNPotentially harmful situationsDeprecated API usage, fallback triggered, retry attempt
ERRORError events that allow app to continueRequest failed, external API timeout, validation failure
FATALSevere errors causing shutdownDatabase unreachable, critical config missing

Logging Rules

日志与可观测性原则

日志标准

日志级别(标准优先级)

1. Every request/operation must log:

// Start of operation
log.Info("creating task",
"correlationId", correlationID,
"userId", userID,
"title", task.Title,
)

// Success
log.Info("task created successfully",
"correlationId", correlationID,
"taskId", task.ID,
"duration", time.Since(start),
)

// Error
log.Error("failed to create task",
"correlationId", correlationID,
"error", err,
"userId", userID,
)
2. Always include context:
  • correlationId
    : Trace requests across services (UUID)
  • userId
    : Who triggered the action
  • duration
    : Operation timing (milliseconds)
  • error
    : Error details (if failed)
3. Structured logging only (no string formatting):

// ✅ Structured
log.Info("user login", "userId", userID, "ip", clientIP)

// ❌ String formatting
log.Info(fmt.Sprintf("User %s logged in from %s", userID, clientIP))
4. Security - Never log:
  • Passwords or password hashes
  • API keys or tokens
  • Credit card numbers
  • PII in production logs (email/phone only if necessary and sanitized)
  • Full request/response bodies (unless DEBUG level in non-prod)
5. Performance - Never log in hot paths:
  • Inside tight loops
  • Per-item processing in batch operations (use summary instead)
  • Synchronous logging in latency-critical paths
Best Practice: "Use logger middleware redaction (e.g., pino-redact, zap masking) rather than manual string manipulation."
所有服务使用一致的日志级别:
级别使用场景示例
TRACE极详细的诊断信息函数进入/退出、变量状态(仅开发环境)
DEBUG调试用的详细流程查询执行、缓存命中/未命中、状态转换
INFO通用信息消息请求开始、任务创建、用户登录
WARN潜在有害场景废弃API使用、触发降级、重试尝试
ERROR不影响应用继续运行的错误事件请求失败、外部API超时、校验失败
FATAL导致关闭的严重错误数据库不可达、关键配置缺失

Language-Specific Implementations

日志规则

Go (using slog standard library)

import "log/slog"

// Configure logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
  Level: slog.LevelInfo, // Production default
}))

// Usage
logger.Info("operation started",
  "correlationId", correlationID,
  "userId", userID,
)

logger.Error("operation failed",
  "correlationId", correlationID,
  "error", err,
  "retryCount", retries,
)
1. 每个请求/操作必须记录:
// 操作开始
log.Info("creating task",
"correlationId", correlationID,
"userId", userID,
"title", task.Title,
)

// 成功
log.Info("task created successfully",
"correlationId", correlationID,
"taskId", task.ID,
"duration", time.Since(start),
)

// 错误
log.Error("failed to create task",
"correlationId", correlationID,
"error", err,
"userId", userID,
)
2. 始终包含上下文:
  • correlationId
    :跨服务追踪请求(UUID)
  • userId
    :触发操作的用户
  • duration
    :操作耗时(毫秒)
  • error
    :错误详情(如果失败)
3. 仅使用结构化日志(无字符串格式化):
// ✅ 结构化
log.Info("user login", "userId", userID, "ip", clientIP)

// ❌ 字符串格式化
log.Info(fmt.Sprintf("User %s logged in from %s", userID, clientIP))
4. 安全 - 禁止记录:
  • 密码或密码哈希
  • API密钥或token
  • 信用卡号
  • 生产日志中的PII(仅在必要时记录邮箱/电话且需脱敏)
  • 完整请求/响应体(非生产环境DEBUG级别除外)
5. 性能 - 热路径中不要打日志:
  • 紧循环内部
  • 批量操作的单条处理(使用摘要替代)
  • 延迟敏感路径中的同步日志
最佳实践: "使用日志中间件脱敏(例如pino-redact、zap masking),而非手动字符串操作。"
TypeScript/Node.js (using pino)

语言专属实现

Go(使用slog标准库)

import pino from 'pino';

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
});

logger.info({
  correlationId,
  userId,
  duration: Date.now() - startTime,
}, 'task created successfully');

logger.error({
  correlationId,
  error: err.message,
  stack: err.stack,
}, 'failed to create task');
import "log/slog"

// 配置logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
  Level: slog.LevelInfo, // 生产环境默认
}))

// 使用
logger.Info("operation started",
  "correlationId", correlationID,
  "userId", userID,
)

logger.Error("operation failed",
  "correlationId", correlationID,
  "error", err,
  "retryCount", retries,
)

Python (using structlog)

TypeScript/Node.js(使用pino)

import structlog

logger = structlog.get_logger()

logger.info("task_created",
correlation_id=correlation_id,
user_id=user_id,
task_id=task.id,
)

logger.error("task_creation_failed",
correlation_id=correlation_id,
error=str(err),
user_id=user_id,
)
import pino from 'pino';

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
});

logger.info({
  correlationId,
  userId,
  duration: Date.now() - startTime,
}, 'task created successfully');

logger.error({
  correlationId,
  error: err.message,
  stack: err.stack,
}, 'failed to create task');

Log Patterns by Operation Type

Python(使用structlog)

API Request/Response

// Request received
log.Info("request received",
  "method", r.Method,
  "path", r.URL.Path,
  "correlationId", correlationID,
  "userId", userID,
)

// Request completed
log.Info("request completed",
  "correlationId", correlationID,
  "status", statusCode,
  "duration", duration,
)
import structlog

logger = structlog.get_logger()

logger.info("task_created",
correlation_id=correlation_id,
user_id=user_id,
task_id=task.id,
)

logger.error("task_creation_failed",
correlation_id=correlation_id,
error=str(err),
user_id=user_id,
)
Database Operations

按操作类型划分的日志模式

API请求/响应

// Query start (DEBUG level)
log.Debug("executing query",
  "correlationId", correlationID,
  "query", "SELECT * FROM tasks WHERE user_id = $1",
)

// Query success (DEBUG level)
log.Debug("query completed",
  "correlationId", correlationID,
  "rowsReturned", len(results),
  "duration", duration,
)

// Query error (ERROR level)
log.Error("query failed",
  "correlationId", correlationID,
  "error", err,
  "query", "SELECT * FROM tasks WHERE user_id = $1",
)
// 收到请求
log.Info("request received",
  "method", r.Method,
  "path", r.URL.Path,
  "correlationId", correlationID,
  "userId", userID,
)

// 请求完成
log.Info("request completed",
  "correlationId", correlationID,
  "status", statusCode,
  "duration", duration,
)
External API Calls
数据库操作

// Call start
log.Info("calling external API",
  "correlationId", correlationID,
  "service", "email-provider",
  "endpoint", "/send",
)

// Retry (WARN level)
log.Warn("retrying external API call",
  "correlationId", correlationID,
  "service", "email-provider",
  "attempt", retryCount,
  "error", err,
)

// Circuit breaker open (WARN level)
log.Warn("circuit breaker opened",
  "correlationId", correlationID,
  "service", "email-provider",
  "failureCount", failures,
)
// 查询开始(DEBUG级别)
log.Debug("executing query",
  "correlationId", correlationID,
  "query", "SELECT * FROM tasks WHERE user_id = $1",
)

// 查询成功(DEBUG级别)
log.Debug("query completed",
  "correlationId", correlationID,
  "rowsReturned", len(results),
  "duration", duration,
)

// 查询错误(ERROR级别)
log.Error("query failed",
  "correlationId", correlationID,
  "error", err,
  "query", "SELECT * FROM tasks WHERE user_id = $1",
)
Background Jobs
外部API调用

// Job start
log.Info("job started",
  "jobId", jobID,
  "jobType", "email-digest",
)

// Progress (INFO level - periodic, not per-item)
log.Info("job progress",
  "jobId", jobID,
  "processed", 1000,
  "total", 5000,
  "percentComplete", 20,
)

// Job complete
log.Info("job completed",
  "jobId", jobID,
  "duration", duration,
  "itemsProcessed", count,
)
// 调用开始
log.Info("calling external API",
  "correlationId", correlationID,
  "service", "email-provider",
  "endpoint", "/send",
)

// 重试(WARN级别)
log.Warn("retrying external API call",
  "correlationId", correlationID,
  "service", "email-provider",
  "attempt", retryCount,
  "error", err,
)

// 断路器打开(WARN级别)
log.Warn("circuit breaker opened",
  "correlationId", correlationID,
  "service", "email-provider",
  "failureCount", failures,
)
Error Scenarios
后台任务

// Recoverable error (ERROR level)
log.Error("validation failed",
  "correlationId", correlationID,
  "userId", userID,
  "error", "invalid email format",
  "input", sanitizedInput, // Sanitized!
)

// Fatal error (FATAL level)
log.Fatal("critical dependency unavailable",
  "error", err,
  "dependency", "database",
  "action", "shutting down",
)
// 任务开始
log.Info("job started",
  "jobId", jobID,
  "jobType", "email-digest",
)

// 进度(INFO级别 - 定期记录,而非每条都记)
log.Info("job progress",
  "jobId", jobID,
  "processed", 1000,
  "total", 5000,
  "percentComplete", 20,
)

// 任务完成
log.Info("job completed",
  "jobId", jobID,
  "duration", duration,
  "itemsProcessed", count,
)

Environment-Specific Configuration

错误场景
EnvironmentLevelFormatDestination
DevelopmentDEBUGPretty (colored)Console
StagingINFOJSONStdout → CloudWatch/GCP
ProductionINFOJSONStdout → CloudWatch/GCP
Configuration (Go example):

func configureLogger() *slog.Logger {
var handler slog.Handler

    level := slog.LevelInfo
    if os.Getenv("ENV") == "development" {
        level = slog.LevelDebug
        handler = slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
            Level: level,
        })
    } else {
        handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
            Level: level,
        })
    }
    
    return slog.New(handler)
    }
// 可恢复错误(ERROR级别)
log.Error("validation failed",
  "correlationId", correlationID,
  "userId", userID,
  "error", "invalid email format",
  "input", sanitizedInput, // 已脱敏!
)

// 致命错误(FATAL级别)
log.Fatal("critical dependency unavailable",
  "error", err,
  "dependency", "database",
  "action", "shutting down",
)

Testing Logs

按环境区分的配置

Unit tests: Capture and assert on log output

// Go example
func TestUserLogin(t *testing.T) {
var buf bytes.Buffer
logger := slog.New(slog.NewJSONHandler(&buf, nil))

    // Test operation
    service := NewUserService(logger, mockStore)
    err := service.Login(ctx, email, password)
    
    // Assert logs
    require.NoError(t, err)
    logs := buf.String()
    assert.Contains(t, logs, "user login successful")
    assert.Contains(t, logs, email)
    }
环境级别格式输出目标
开发环境DEBUG美化(彩色)控制台
Staging环境INFOJSONStdout → CloudWatch/GCP
生产环境INFOJSONStdout → CloudWatch/GCP
配置(Go示例):
func configureLogger() *slog.Logger {
var handler slog.Handler

    level := slog.LevelInfo
    if os.Getenv("ENV") == "development" {
        level = slog.LevelDebug
        handler = slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
            Level: level,
        })
    } else {
        handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
            Level: level,
        })
    }
    
    return slog.New(handler)
    }

Monitoring Integration

日志测试

Correlation IDs:
  • Generate at ingress (API gateway, first handler)
  • Propagate through all services
  • Include in all logs, errors, and traces
  • Format: UUID v4
Log aggregation:
  • Ship to centralized system (CloudWatch, GCP Logs, Datadog)
  • Index by: correlationId, userId, level, timestamp
  • Alert on ERROR/FATAL patterns
  • Dashboard: request rates, error rates, latency
单元测试: 捕获并断言日志输出
// Go示例
func TestUserLogin(t *testing.T) {
var buf bytes.Buffer
logger := slog.New(slog.NewJSONHandler(&buf, nil))

    // 测试操作
    service := NewUserService(logger, mockStore)
    err := service.Login(ctx, email, password)
    
    // 断言日志
    require.NoError(t, err)
    logs := buf.String()
    assert.Contains(t, logs, "user login successful")
    assert.Contains(t, logs, email)
    }

Checklist for Every Feature

监控集成

  • All public operations log INFO on start
  • All operations log INFO/ERROR on complete/failure
  • All logs include correlationId
  • No sensitive data in logs
  • Structured logging (key-value pairs)
  • Appropriate log level used
  • Error logs include error details
  • Performance-critical paths use DEBUG level
关联ID:
  • 在入口处生成(API网关、第一个handler)
  • 在所有服务中传递
  • 包含在所有日志、错误和链路追踪中
  • 格式:UUID v4
日志聚合:
  • 传输到集中式系统(CloudWatch、GCP Logs、Datadog)
  • 索引字段:correlationId、userId、level、timestamp
  • 针对ERROR/FATAL模式告警
  • 仪表盘:请求率、错误率、延迟

Observability Strategy

每个功能的检查清单

Three Pillars:
  1. Logs: What happened (events, errors, state changes)
  2. Metrics: How much/how many (quantitative measurements)
  3. Traces: How did it happen (request flow through system)
Key Metrics:
  • RED (for services):
    • Rate: Requests per second
    • Errors: Error rate/count
    • Duration: Latency (p50, p95, p99)
  • USE (for resources):
    • Utilization: % resource in use (CPU, memory, disk)
    • Saturation: How full (queue depth, wait time)
    • Errors: Error count
Health Checks:
  • /health
    : Simple "am I alive?" (process health only)
  • /ready
    : "Am I ready to serve?" (includes dependencies)
  • 所有公共操作在开始时记录INFO级别日志?
  • 所有操作在完成/失败时记录INFO/ERROR级别日志?
  • 所有日志包含关联ID?
  • 日志中无敏感数据?
  • 使用结构化日志(键值对)?
  • 使用了合适的日志级别?
  • 错误日志包含错误详情?
  • 性能关键路径使用DEBUG级别日志?

Related Principles

可观测性策略

三大支柱:
  1. 日志: 发生了什么(事件、错误、状态变更)
  2. 指标: 数量有多少(量化测量)
  3. 链路追踪: 是如何发生的(请求在系统中的流转路径)
关键指标:
  • RED(服务维度):
    • 速率:每秒请求数
    • 错误:错误率/计数
    • 耗时:延迟(p50、p95、p99)
  • USE(资源维度):
    • 利用率:资源使用百分比(CPU、内存、磁盘)
    • 饱和度:已满程度(队列深度、等待时间)
    • 错误:错误计数
健康检查:
  • /health
    :简单的「是否存活」(仅进程健康)
  • /ready
    :「是否可提供服务」(包含依赖检查)

Code Idioms and Conventions

关联原则

Universal Principle

Write idiomatic code for the target language:
  • Code should look natural to developers familiar with that language
  • Follow established community conventions, not personal preferences
  • Use language built-ins and standard library effectively
  • Apply language-appropriate patterns (don't force patterns from other languages)

Idiomatic Code Characteristics

代码惯用规范与约定

通用原则

  • Leverages language features (don't avoid features unnecessarily)
  • Follows language naming conventions
  • Uses appropriate error handling for language (exceptions vs Result types)
  • Applies established community patterns
为目标语言编写符合惯用规范的代码:
  • 代码对熟悉该语言的开发者来说应该是自然的
  • 遵循已建立的社区约定,而非个人偏好
  • 有效使用语言内置功能和标准库
  • 应用语言适配的模式(不要强行套用其他语言的模式)

Avoid Cross-Language Anti-Patterns

符合惯用规范的代码特征

  • ❌ Don't write "Java in Python" or "C in Go"
  • ❌ Don't force OOP patterns in functional languages
  • ❌ Don't avoid language features because they're "unfamiliar"
  • ✅ Learn and apply language-specific idioms
  • 利用语言特性(不要不必要地规避特性)
  • 遵循语言命名约定
  • 使用语言适配的错误处理(异常 vs Result类型)
  • 应用已建立的社区模式

Dependency Management Principles

避免跨语言反模式

Version Pinning

Production: Pin exact versions (1.2.3, not ^1.2.0)
  • Prevents supply chain attacks
  • Prevents unexpected breakage from patch updates
  • Ensures reproducible builds
Use lock files:
  • package-lock.json (Node.js)
  • Cargo.lock (Rust)
  • go.sum (Go)
  • requirements.txt or poetry.lock (Python)
  • ❌ 不要写「Python里的Java」或「Go里的C」
  • ❌ 不要在函数式语言中强行使用OOP模式
  • ❌ 不要因为「不熟悉」就规避语言特性
  • ✅ 学习并应用语言专属的惯用规范

Minimize Dependencies

依赖管理原则

版本锁定

Every dependency is a liability:
  • Potential security vulnerability
  • Increased build time and artifact size
  • Maintenance burden (updates, compatibility)
Ask before adding dependency:
  • "Can I implement this in 50 lines?"
  • "Is this functionality critical?"
  • "Is this dependency actively maintained?"
  • "Is this the latest stable version?"
生产环境: 锁定精确版本(1.2.3,而非^1.2.0)
  • 预防供应链攻击
  • 预防补丁更新导致的意外中断
  • 保证可复现构建
使用锁文件:
  • package-lock.json(Node.js)
  • Cargo.lock(Rust)
  • go.sum(Go)
  • requirements.txt 或 poetry.lock(Python)

Organize Imports

最小化依赖

Grouping:
  1. Standard library
  2. External dependencies
  3. Internal modules
Sorting: Alphabetical within groups
Cleanup: Remove unused imports (use linter/formatter)
每个依赖都是一个负债:
  • 潜在的安全漏洞
  • 增加构建时间和制品大小
  • 维护负担(更新、兼容性)
添加依赖前自问:
  • "我能在50行代码内实现这个功能吗?"
  • "这个功能是核心需求吗?"
  • "这个依赖还在积极维护吗?"
  • "这是最新的稳定版本吗?"

Avoid Circular Dependencies

导入组织

Problem: Module A imports B, B imports A
  • Causes build failures, initialization issues
  • Indicates poor module boundaries
Solution:
  • Extract shared code to third module
  • Restructure dependencies (A→C, B→C)
  • Use dependency injection
分组:
  1. 标准库
  2. 外部依赖
  3. 内部模块
排序: 组内按字母顺序排序
清理: 移除未使用的导入(使用linter/格式化工具)

Command Execution Principles

避免循环依赖

Security

Never execute user input directly:
  • exec(userInput)
  • shell("rm " + userFile)
  • ✅ Use argument lists, not shell string concatenation
  • ✅ Validate and sanitize all arguments
Run with minimum permissions:
  • Never run commands as root/admin without explicit human approval. If elevated permissions are absolutely required, STOP and request authorization.
  • Use least-privilege service accounts
问题: 模块A导入B,B导入A
  • 导致构建失败、初始化问题
  • 表明模块边界设计不合理
解决方案:
  • 将共享代码提取到第三个模块
  • 重构依赖关系(A→C,B→C)
  • 使用依赖注入

Portability

命令执行原则

安全

Use language standard library:
  • Avoid shell commands when standard library provides functionality
  • Example: Use file I/O APIs instead of
    cat
    ,
    cp
    ,
    mv
Test on all target OS:
  • Windows, Linux, macOS have different commands and behaviors
  • Use path joining functions (don't concatenate with /)
永远不要直接执行用户输入:
  • exec(userInput)
  • shell("rm " + userFile)
  • ✅ 使用参数列表,而非shell字符串拼接
  • ✅ 校验并清洗所有参数
以最小权限运行:
  • 没有明确的人类审批,永远不要以root/管理员身份运行命令。如果确实需要提升权限,停止并请求授权。
  • 使用最小权限的服务账号

Error Handling

可移植性

Check exit codes:
  • Non-zero exit code = failure
  • Capture and log stderr
  • Set timeouts for long-running commands
  • Handle "command not found" gracefully
使用语言标准库:
  • 标准库提供对应功能时避免使用shell命令
  • 示例:使用文件I/O API,而非
    cat
    cp
    mv
在所有目标OS上测试:
  • Windows、Linux、macOS的命令和行为不同
  • 使用路径拼接函数(不要用/拼接)

Related Principles

错误处理

检查退出码:
  • 非零退出码 = 失败
  • 捕获并记录stderr
  • 长时间运行的命令设置超时
  • 优雅处理「命令未找到」场景

Documentation Principles

关联原则

Self-Documenting Code

Clear naming reduces need for comments:
  • Code shows WHAT is happening
  • Comments explain WHY it's done this way
When to comment:
  • Complex business logic deserves explanation
  • Non-obvious algorithms (explain approach)
  • Workarounds for bugs (link to issue tracker)
  • Performance optimizations (explain trade-offs)

Documentation Levels

文档原则

自文档化代码

  1. Inline comments: Explain WHY for complex code
  2. Function/method docs: API contract (parameters, returns, errors)
  3. Module/package docs: High-level purpose and usage
  4. README: Setup, usage, examples
  5. Architecture docs: System design, component interactions
清晰的命名可以减少注释需求:
  • 代码展示正在做什么
  • 注释解释为什么这么做
何时需要注释:
  • 复杂的业务逻辑需要解释
  • 非直观的算法(说明实现思路)
  • bug的临时解决方案(链接到issue跟踪系统)
  • 性能优化(说明取舍)

Security Principles

文档层级

OWASP Top 10 Enforcement

  • Broken Access Control: Deny by default. Validate permissions server-side for every request. Do not rely on UI state.
  • Cryptographic Failures: Use TLS 1.2+ everywhere. Encrypt PII/Secrets at rest. Use standard algorithms (AES-256, RSA-2048, Ed25519). Never roll your own crypto.
  • Injection: ZERO TOLERANCE for string concatenation in queries. Use Parameterized Queries (SQL) or ORM bindings. Sanitize all HTML/JS output.
  • SSRF Prevention: Validate all user-provided URLs against an allowlist. Disable HTTP redirects in fetch clients. Block requests to internal IPs (metadata services, localhost).
  • Insecure Design: Threat model every new feature. Fail securely (closed), not openly.
  • Vulnerable Components: Pin dependency versions. Scan for CVEs in CI/CD.
  1. 内联注释: 解释复杂代码的实现原因
  2. 函数/方法文档: API契约(参数、返回值、错误)
  3. 模块/包文档: 高层用途和用法
  4. README: 搭建、用法、示例
  5. 架构文档: 系统设计、组件交互

Authentication & Authorization

安全原则

OWASP Top 10落地要求

  • Passwords: Hash with Argon2id or Bcrypt (min cost 12). Never plain text.
  • Tokens:
    • Access Tokens: Short-lived (15-30 mins). HS256 or RS256.
    • Refresh Tokens: Long-lived (7-30 days). Rotate on use. Store in
      HttpOnly; Secure; SameSite=Strict
      cookies.
  • Rate Limiting: Enforce strictly on public endpoints (Login, Register, Password Reset). Standard: 5 attempts / 15 mins.
  • MFA: Required for Admin and Sensitive Data access.
  • RBAC: Map permissions to Roles, not Users. Check permissions at the Route AND Resource level.
  • 访问控制失效: 默认拒绝,服务端校验每个请求的权限,不要依赖UI状态。
  • 加密失效: 所有场景使用TLS 1.2+,静态PII/密钥加密,使用标准算法(AES-256、RSA-2048、Ed25519),永远不要自己实现加密算法。
  • 注入: 零容忍查询中的字符串拼接,使用参数化查询(SQL)或ORM绑定,清洗所有HTML/JS输出。
  • SSRF防护: 校验所有用户提供的URL是否在白名单中,禁用fetch客户端的HTTP重定向,阻止访问内部IP(元数据服务、localhost)。
  • 不安全设计: 每个新功能都要做威胁建模,安全失败(默认关闭),而非开放失败。
  • 有漏洞的组件: 锁定依赖版本,CI/CD中扫描CVE。

Input Validation & Sanitization

身份认证与权限控制

  • Principle: "All Input is Evil until Proven Good."
  • Validation: Validate against a strict Schema (Zod/Pydantic) at the Controller/Port boundary.
  • Allowlist: Check for "Good characters" (e.g.,
    ^[a-zA-Z0-9]+$
    ), do not try to filter "Bad characters."
  • Sanitization: Strip dangerous tags from rich text input using a proven library (e.g., DOMPurify equivalent).
  • 密码: 使用Argon2id或Bcrypt哈希(最小成本12),永远不要明文存储。
  • Token:
    • 访问Token: 短有效期(15-30分钟),HS256或RS256算法。
    • 刷新Token: 长有效期(7-30天),使用时轮换,存储在
      HttpOnly; Secure; SameSite=Strict
      cookie中。
  • 限流: 公共端点严格执行限流(登录、注册、密码重置),标准规则:15分钟内5次尝试。
  • MFA: 管理员和敏感数据访问必须启用。
  • RBAC: 权限映射到角色,而非用户,在路由和资源层面都要校验权限。

Logging & Monitoring (Security Focus)

输入校验与清洗

  • Redaction: SCRUB all PII, Secrets, Tokens, and Passwords from logs before writing.
  • Events: Log all failed auth attempts, access denied events, and input validation failures.
  • Format: JSON structured logs with
    correlationId
    ,
    user_id
    , and
    event_type
    .
  • Anti-Tamper: Logs should be write-only for the application.
  • 原则: "所有输入都是恶意的,除非证明是安全的。"
  • 校验:控制器/端口边界使用严格Schema(Zod/Pydantic)校验。
  • 白名单: 检查「合法字符」(例如:
    ^[a-zA-Z0-9]+$
    ),不要尝试过滤「非法字符」。
  • 清洗: 使用成熟的库(例如DOMPurify等价库)剥离富文本输入中的危险标签。

Secrets Management

日志与监控(安全方向)

  • Storage: Never commit secrets to git. Use
    .env
    (local) or Secret Managers (Prod - e.g., Vault/GSM).
  • 脱敏: 写入日志前清除所有PII、密钥、Token和密码。
  • 事件: 记录所有失败的鉴权尝试、拒绝访问事件、输入校验失败事件。
  • 格式: JSON结构化日志,包含
    correlationId
    user_id
    event_type
  • 防篡改: 应用对日志只有写权限。

Related Principles

密钥管理

  • 存储: 永远不要将密钥提交到git,本地使用
    .env
    ,生产使用密钥管理器(例如Vault/GSM)。

关联原则