docs: 新增「类型约定」章节(架构 §4.7)

把"数据类型必须明确"从口头要求变成仓库规则,每个函数都适用。

- 判断顺序表:整数用 (int, np.integer)、浮点用 (float, np.floating)、
  bool 要放在 int 判断之前、数组先 np.asarray 归一化
- 硬规则:非法类型必须 raise TypeError,不许静默兜底
  (静默的后果是"种子被忽略、结果不可复现且无提示",最难查)
- 要求每个公开函数写全 Parameters(含 None 走哪条分支)与 Raises
- docs/03-roadmap.md §3.2 开发纪律加一行指针
This commit is contained in:
guzhujushi committed 2026-10-01 20:04:32 +08:00
1 parent c93810ffb1
commit 98278edd77
3 files changed
+28

No files matched your search

+25
View File
@@ -158,6 +158,31 @@ class Model(Protocol):
**可选依赖缺失时必须给出可读报错**,例如 `sobol_analyze` 在没装 SALib 时提示 `pip install "mcm-toolkit[sensitivity]"`,而不是 `ModuleNotFoundError` 裸抛。
### 4.7 类型约定(每个函数都适用)
公开函数的**参数类型注解必须写全**,并且与 docstring 说的是同一件事:注解给 IDE / pyright 看,
docstring 给人看。两处打架时,合法用法会被标红,真正的错误反而看不见。
判断顺序照抄下表,**不要凭直觉**:
| 值可能来自 | 怎么写 | 为什么 |
|---|---|---|
| 整数 | `isinstance(x, (int, np.integer))`,取值统一 `int(x)` | `np.int64` **不是** `int` 的子类,只写 `int` 会漏 |
| 浮点 | `isinstance(x, (float, np.floating))` | `np.float64` 是 `float` 子类,但 `np.float32` 不是——不统一 |
| 布尔 | `isinstance(x, bool)` 要放在 `int` 判断**之前** | `True` 也是 `int`,顺序反了会当成 1 |
| 数组 / 表 | `np.asarray(x, dtype=float)` 后再校验 | 别假设调用方已经转好类型 |
**非法类型必须 `raise TypeError`,不许静默兜底。** 静默的典型后果是
"种子被忽略、结果不可复现,但没有任何提示"——比直接报错难查一百倍。
配套要求,每个公开函数都要有:
- `Parameters` 写清类型与含义;允许 `None` 时,写明 `None` 会走哪条分支
- `Raises` 写清会抛什么异常
参考实现:`core/random.py` 的 `get_rng`。
---
## 五、测试策略
+1
View File
@@ -86,6 +86,7 @@
1. 先想"这道题里它替代了哪段手写代码"——想不出来就先不写。
2. 先在 `tests/` 里写一条会失败的断言(测已知解析解,不测实现细节)。
- 参数类型注解按 `02-architecture.md` §4.7 写全;非法类型抛 `TypeError`,不静默兜底。
3. 实现到测试通过。
4. 在 `examples/` 里加一行最小用法。
5. 更新 `STATUS.md`。