# 架构与设计检查项

## SOLID 原则

### SRP（单一职责）

- 一个模块/类同时承担多个独立的变化原因（例如同时处理数据获取、业务规则和格式化输出）
- 单个函数同时做校验、业务计算、持久化和通知，职责杂糅

### OCP（开闭原则）

- 新增一种场景需要修改核心逻辑，而不是通过新增实现或配置完成
- 本应用 strategy/plugin 模式的地方，只能靠堆 if-else / switch 扩展

### LSP（里氏替换）

- 子类覆盖父类方法时，收紧了前置条件或放宽了后置条件，破坏了调用方的期望
- 调用方需要用 `instanceof` 或类型判断来规避某个具体子类的异常行为

### ISP（接口隔离）

- 接口定义了超出调用方实际需要的方法，调用方被迫实现或依赖不需要的部分
- 一个接口同时服务多个差异很大的使用场景，导致任何一方改动都影响所有人

### DIP（依赖倒置）

- 高层业务逻辑直接 `import` 或 `new` 底层实现（数据库、文件系统、第三方 SDK）
- 存储层、网络层或框架细节渗透到核心业务逻辑中，替换底层时必须修改业务代码

## 常见设计坏味道

- **超长函数**：函数超过 50–80 行，或嵌套超过 3 层，很可能承担了太多职责
- **数据泥团（Data Clump）**：多个参数总是一起出现，应该封装成一个对象
- **依恋情结（Feature Envy）**：函数大量使用另一个类的字段，逻辑应该移过去
- **基本类型偏执（Primitive Obsession）**：用 string/int 表示有明确业务含义的概念（如 userId、currency、status），应该引入明确类型
- **散弹式修改（Shotgun Surgery）**：一个需求变化需要修改多处不相关的文件
- **魔法值**：裸数字或字符串字面量，没有命名常量说明含义
- **过度预设计**：为假想的未来需求引入抽象层，当前没有任何实际使用场景

## 重构建议原则

- 优先给出改动最小、风险可控的拆分方案
- 说明调整后的边界为何更清晰，以及对现有调用方的影响
- 改动较大时，给出分步方案（先拆接口 → 再迁移实现 → 再删旧代码）
- 不建议整体重写，除非现有结构无法安全演进

## 排查思路

审查时依次问自己：

- 这些职责为什么会落在同一个模块或函数里？是历史积累还是设计失误？
- 如果再新增一种场景，现有结构是更容易扩展，还是更容易失控？
- 调用方是否已经为了适配当前设计，写了额外的 workaround 逻辑？
- 这次改动暴露的是局部实现问题，还是更上层的边界划分问题？
- 如果判断不能落到具体调用关系、边界混乱点或新增改动带来的实际影响上，不作为正式问题输出。
