engineering-principles
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseArchitecture and Engineering Principles
架构与工程原则
Optimise for local reasoning. A developer should be able to find, understand, change and verify a capability by examining a small, obvious part of the codebase, without navigating layers of indirection or hidden dependencies.
Language-independent defaults for small projects maintained by one person and future coding agents. Prefer the simplest coherent design meeting actual requirements. Apply rigour proportionately, never mechanically. See for what to build with, and for AI risk and permission boundaries.
tech-preferencesverifiable-trust以局部可推理为核心优化目标。 开发者只需检查代码库中一小部分明确的内容,就能找到、理解、修改并验证某项能力,无需在层层间接调用或隐藏依赖中来回跳转。
这是面向单人维护的小型项目及未来编码Agent的语言无关默认准则。优先选择能满足实际需求的最简单自洽设计。适度应用严谨性,切勿机械套用。技术选型请参考 ,AI 风险与权限边界请参考 。
tech-preferencesverifiable-trustStructure and navigation
结构与导航
- Organise by capability, not architectural layer. Packages and directories describe what software does, not generic labels such as ,
ports,adaptersormodels, unless an architectural term truly is the clearest domain-specific name.services - Make names and navigation obvious. Meaningful package, file, type and function names should let a contributor predict where code belongs.
- Prefer fewer cohesive packages. Keep related responsibilities together; use descriptive separate files within a package before creating new package boundaries.
- High cohesion, loose coupling. Code that changes for the same reason usually belongs together; unrelated capabilities have minimal explicit dependencies.
- Keep structure shallow. No nesting, fragmentation or extra layers without a real boundary.
- Avoid dumping grounds. No catch-all ,
utils,commonorhelpers. Assign behaviour a clear owner.misc - Separation of concerns does not require separation into packages. Package count and file size are not goals.
- 按能力而非架构层组织代码。 包和目录应描述软件的实际功能,而非使用 、
ports、adapters、models这类通用标签——除非某个架构术语确实是最清晰的领域特定名称。services - 让命名与导航清晰直观。 有意义的包、文件、类型和函数名称应能让贡献者预判代码的归属位置。
- 优先使用少量内聚的包。 将相关职责放在一起;在创建新的包边界之前,先在同一个包内使用具有描述性的独立文件拆分。
- 高内聚,低耦合。 因相同原因变更的代码通常应放在一起;不相关的能力之间仅保留最少的显式依赖。
- 保持结构扁平。 没有真实边界的情况下,不要嵌套、拆分或增加额外层级。
- 避免“垃圾桶”式目录。 不要使用 、
utils、common、helpers这类万能收纳目录。为每一项行为明确归属。misc - 关注点分离不意味着必须拆分为不同的包。 包的数量和文件大小不是目标。
Implementation and dependencies
实现与依赖
- Design APIs for consumers. Expose small predictable operations; hide implementation detail consumers needn't understand.
- Prefer concrete dependencies. Use direct calls unless a meaningful boundary, substitutable implementation or test requirement justifies an interface. Don't create interfaces by habit.
- Make effects explicit. No hidden mutable global state, surprising side effects or magic wiring.
- Clarity over cleverness or speculative reuse. A little duplication can be preferable to a shared abstraction coupling unrelated features. Don't build imaginary extension points.
- Handle errors deliberately. Fail clearly, retain useful context, clean up resources and explain recovery behaviour.
- Use concurrency only when worth its complexity. Start sequential; if warranted, make ownership, cancellation, timeouts and shutdown comprehensible.
- Keep deployable service boundaries coherent. A service owns an obvious capability with explicit contracts across services; independent deployment does not require excessive internal layering.
- 面向使用者设计API。 暴露少量可预测的操作;隐藏使用者无需了解的实现细节。
- 优先使用具体依赖。 除非存在有意义的边界、可替换的实现或测试需求需要接口,否则直接调用。不要出于习惯创建接口。
- 让副作用显式化。 不要有隐藏的可变全局状态、意料之外的副作用或魔法式自动装配。
- 清晰优先于巧妙或投机性复用。 少量重复可能比耦合无关功能的共享抽象更好。不要为假想的需求构建扩展点。
- 有意识地处理错误。 失败时提示清晰,保留有用的上下文,清理资源,并说明恢复行为。
- 仅在复杂度值得时使用并发。 先从顺序执行开始;如果确实需要并发,要让所有权、取消机制、超时和关闭逻辑都清晰易懂。
- 保持可部署服务的边界内聚。 一个服务应拥有一项明确的能力,服务间通过显式契约交互;独立部署不需要过度的内部层级。
Configuration, runtime and operations
配置、运行时与运维
- Separate code from deployment settings. Externalise secrets and environment-dependent values. Prefer reviewable version-controlled structured configuration for application policy when appropriate. Never embed credentials.
- Reproducible builds and releases. Declare/pin dependencies, build once, promote immutable identifiable artefacts.
- Replaceable processes, intentional durable state. Predictable startup, graceful shutdown, recovery. Distinguish temporary process state from durable user data, identity and repositories.
- Meaningfully consistent environments. Comparable paths/dependencies in development, CI and deployment; explicit differences.
- Observable and operable. Useful errors, structured logs, health checks and documented repeatable validation/recovery commands over manual ritual.
- 代码与部署配置分离。 将密钥和环境相关的值外置。适当时,应用策略优先使用可评审、纳入版本控制的结构化配置。绝不要硬编码凭证。
- 可复现的构建与发布。 声明并锁定依赖版本,一次构建,推进不可变的可识别制品。
- 进程可替换,持久状态有规划。 启动可预测,关闭优雅,支持恢复。区分临时进程状态与持久化的用户数据、身份和存储库。
- 环境保持有意义的一致性。 开发、CI和部署环境的路径/依赖应具有可比性;差异要显式说明。
- 可观测,易运维。 提供有用的错误信息、结构化日志、健康检查,以及有文档记录的可重复验证/恢复命令,而非依赖人工操作惯例。
Verification and evolution
验证与演进
- Test observable behaviour, not incidental implementation. Prefer test-first red → green vertical slices at agreed public seams for behaviour changes; exercise important success, failure and recovery paths with independently grounded expectations. Don't write brittle implementation-coupled or tautological tests just to satisfy a process. Static checks must enforce real invariants.
- Small complete changes. Solve the problem without unrelated refactoring, hypothetical infrastructure or abandoned compatibility layers. Preserve contracts unless deliberately changing them.
- Durable discoverable decisions. Document non-obvious constraints, rationale and operations where maintainers will look, not only in chat. Avoid verbose or duplicated instructions.
- Make the codebase teach its own architecture. Clear layout, contracts and executable conventions should reduce agent instruction needs. If agents repeatedly fail, improve structure, documentation or checks before adding standing rules.
- Self-explanatory over instruction-dependent systems. Documentation should preserve intent and non-obvious choices, not compensate for confusing code.
- Proportionate rigour. Fast reversible learning for experiments; stronger security, observability, verification and recovery for production or consequential changes.
- 测试可观测的行为,而非偶然的实现细节。 对于行为变更,优先在约定的公共接缝处采用测试先行的红→绿垂直切片方法;基于独立合理的预期,覆盖重要的成功、失败和恢复路径。不要为了满足流程要求,编写脆弱的、与实现强耦合的或同义反复的测试。静态检查必须强制执行真实的不变量。
- 小而完整的变更。 解决问题时不要夹带无关的重构、假想的基础设施或废弃的兼容层。除非刻意修改契约,否则应保持契约不变。
- 持久且可发现的决策记录。 将不直观的约束、设计理由和运维说明记录在维护者会查看的地方,而不是只放在聊天记录里。避免冗长或重复的说明。
- 让代码库自身传递架构知识。 清晰的布局、契约和可执行的约定应能减少对Agent指令的依赖。如果Agent反复出错,应先改进结构、文档或检查机制,再添加固定规则。
- 自解释优先于依赖指令的系统。 文档应记录设计意图和不直观的选择,而非用来弥补代码的混乱。
- 适度的严谨性。 实验性工作允许快速可逆的试错;生产环境或有重大影响的变更则需要更强的安全性、可观测性、验证和恢复能力。
Quick design check
快速设计检查
Before adding a package, dependency, abstraction or process, consider:
- Where would someone naturally look for this capability?
- Can it be understood and changed without tracing unrelated files or hidden wiring?
- Does this boundary correspond to a real responsibility or independent reason to change?
- Is this abstraction/dependency truly simpler than a direct approach?
- Can key behaviour and failures be verified, and the change recovered?
This is a lightweight decision aid, not a mandatory checklist for every edit. When a convention harms navigation, name the trade-off and choose the simpler design.
在新增包、依赖、抽象或流程之前,先思考以下问题:
- 人们会自然地去哪里寻找这项能力?
- 无需追踪无关文件或隐藏的装配逻辑,就能理解和修改它吗?
- 这个边界是否对应真实的职责或独立的变更原因?
- 这个抽象/依赖真的比直接实现更简单吗?
- 关键行为和故障能否被验证,变更能否被回滚?
这是一个轻量级的决策辅助工具,不是每次编辑都必须遵守的检查清单。当某项约定损害了导航性时,明确权衡利弊后选择更简单的设计。
Influences, not mandatory frameworks
参考来源,而非强制框架
- Effective Go, Go Code Review Comments, Go Proverbs: expressive names, small consumer-oriented interfaces, explicit errors and avoiding needless abstraction.
- The Twelve-Factor App: clean configuration, repeatable builds, environment consistency, disposable processes and operational visibility.
These inspirations do not mandate Go, environment variables for every setting, or statelessness where durable state is intentional.
- Effective Go、Go Code Review Comments、Go Proverbs:富有表现力的命名、面向使用者的小型接口、显式错误处理,以及避免不必要的抽象。
- 十二要素应用:清晰的配置、可复现构建、环境一致性、进程可随时启停、运维可观测性。
这些参考理念并不强制要求使用Go、所有配置都用环境变量,或者在需要持久状态的场景下强行保持无状态。