# 通用原则

摘自《Harness 原则 / AGENTS.md》。这一部分可以单独复制到项目的 AGENTS.md 或团队规范中使用。

## 1. 基本原则和设计思路

### 核心行为

改代码前，先理解用户请求、附近代码和现有架构。重要假设要显式说出来。需求有多个合理解释时，先指出分歧，不要静默选择一个高风险方向。

优先使用能正确解决问题的最小改动。不要添加未被要求的功能、配置层、兼容分支或单次使用的抽象。如果实现开始明显大于问题本身，就收缩它。

保持改动外科手术式精准。只碰完成任务必须修改的文件，匹配本地风格，不要顺手重构邻近代码。只删除由你本次改动制造出的无用 import、变量、函数或生成产物。发现无关问题时可以说明，不要静默改写。

把任务转成可验证目标。修 bug 时，实际可行的话先复现或隔离失败，再修复。做功能时，明确可观察行为并检查。做重构时，如果项目有合理命令，尽量在前后验证行为。

### Simple / Short / Straight

Simple：简单是跨越语言、框架和设计模式的最高原则。小即是美。能用一个清楚模块解决的问题，不要拆成多层概念；能用直接数据结构表达的问题，不要引入协议、模板或抽象工厂。

Short：简短不是压缩代码，而是在保证可读性的前提下减少不必要内容。代码越短越好，作用域越短越好，生命周期越短越好。变量、对象、连接、事务和临时状态都应尽早创建、尽快使用、及时结束。

Straight：直接意味着读者不需要记住很远处的定义。假设代码读者只有很短的工作记忆，也应该能顺着当前文件、当前函数、当前作用域看懂。描述和定义尽量靠近使用点；不言自明的代码才是合格代码。

Helper 不是天然的好设计。很多 helper 是 Java 式工程习惯带来的过度间接：一个函数、一个表达式就能说清楚的事情，不要拆成一堆只用过一次两次的小 helper。helper 会把读者的注意力从当前逻辑拉走，只有当它真正减少重复、隔离复杂性或表达稳定概念时才值得存在。

整体方向应从“方便计算机”转向“方便人”。现代编辑器已经提供实时提示、类型跳转、补全和搜索，不要再为了机器或陈旧工具习惯牺牲代码本身的可读性。

设计权衡的最终目标是帮助程序员 focus。人在聚焦时非常强大，所以语言选择、模块边界、命名、复用方式和接口形状，都应减少读者在无关细节上的记忆负担。

### 命名原则

被淘汰的命名习惯不要继承。例如匈牙利命名法中的 `lpsz` 一类前缀，来自指针和编辑器能力都很弱的时代。今天更重要的是表达领域含义、对象职责和动作意图。

静态定义对象、类型、仓库、映射表等名词概念使用首字母大写。推荐“名词类型 + 容器/角色”的形式，例如 `ProductStore`、`IDNameMap`。

方法和函数表示动作，首字母小写。可以使用 `addMember`，也可以按语言习惯使用 `add_member`。独立函数应完整说明动作和对象，例如 `addMember` 表示“增加一个成员”。如果函数已经处在明确对象或作用域中，可以简化，例如 `ProductStore.add`。

命名需要在清晰和短小之间权衡。更长的名字更容易理解，更短的名字能让视觉范围内容纳更多有效信息。短单词不需要缩写；惯用缩写可以保留，例如 `ID`、`pt`。缩写以具有足够区分度为原则，不要制造只有作者知道的暗号。

### 复用原则

DRY 的目标不是消灭所有重复，而是消灭会导致理解和修改成本上升的重复。少量平铺、清楚、稳定、可生成的重复，往往比过早抽象更容易维护。

过程/函数复用只复用算法，不包含环境和数据结构。它简单明了，但隐含环境要求容易失控。只有依赖少、副作用少、输入输出清楚时，才优先使用这种复用。

对象复用把算法和数据结构放在一起，适合表达有稳定状态和行为边界的概念。

继承复用是基于设计的复用。它适用于设计模式固定、需求简单固定的情况，但要求先有父类再有派生类，容易逼迫工程反复重构父类。能不用就不用；必须使用时，类层次不要超过五层。

组合复用是基于工程的复用。它把功能块以对象方式组装起来，更符合人类逐步认识问题的过程，但也会增加装配复杂度。优先使用组合代替继承，但不要为了组合而制造过多小对象。

基于 Interface/Trait 的复用，也可以理解为基于视角、剖面或能力的复用。它抽取的是“这个对象在某个场景下能做什么”，比继承更接近一维重构。语言支持时，优先使用接口或 trait 表达可替换能力。

### 编码、存储和日志

源代码和所有文本文件统一使用 UTF-8 编码。严禁使用带 BOM 的 UTF-8。MySQL 字符集统一使用 `utf8mb4`。

Redis 适合高性能运行期状态、缓存和相对复杂的内存数据结构，例如 KV、HashMap、HashSet、会话、短期索引和热点数据。不要把 Redis 当成没有边界的持久数据库；需要强一致关系查询时，应回到关系数据库或明确的持久层。

MySQL 适合关系数据和有大范围查询需求的业务数据。应用场景中的查询必须建立在索引基础上。所有表和字段都需要注释；表必须有主键；统一使用 InnoDB；字符集使用 `utf8mb4`。禁止使用分区表，优先从业务侧分表。禁止使用外键，关系一致性由业务层实现。禁止在数据库中存储图片、文件等大数据。

消息队列 MQ 用于异步、削峰和应用解耦。只有当业务确实需要跨进程异步处理、失败重试、缓冲压力或隔离上下游时才引入 MQ。可选技术包括 Kafka、RocketMQ、Redis Stream 等；不要为了“架构完整”提前引入队列。

日志要服务于定位问题，而不是制造噪声。关键入口、鉴权失败、参数错误、状态转移、事务失败、外部系统调用失败都应记录足够上下文。不要记录密码、token、私钥、完整个人敏感信息或大体积 payload。日志字段应稳定，便于搜索和聚合。
