🎨 style(markdown): format all markdown files with prettier
- 使用 prettier 格式化所有 markdown 文件 - prose-wrap: always, print-width: 80 - 保持代码块和表格格式 - 提升可读性和一致性 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+52
-25
@@ -12,14 +12,18 @@
|
||||
### 1.1 单一职责
|
||||
|
||||
- 一个文件只做一件事;职责明确。
|
||||
- `.tsl` 建议作为“入口/编排层”:聚合参数/配置、串起流程;可复用逻辑下沉到 `.tsf`(`unit`/`class`/`function`)中。
|
||||
- 当一个顶层声明同时承担“协议适配 + 业务计算 + I/O/环境依赖 + 临时代码”时,优先拆分边界:核心纯逻辑 → 工具函数 → 边界适配(I/O)。
|
||||
- `.tsl` 建议作为“入口/编排层”:聚合参数/配置、串起流程;可复用逻辑下沉到
|
||||
`.tsf`(`unit`/`class`/`function`)中。
|
||||
- 当一个顶层声明同时承担“协议适配 + 业务计算 +
|
||||
I/O/环境依赖 + 临时代码”时,优先拆分边界:核心纯逻辑 → 工具函数 → 边界适配(I/O)。
|
||||
|
||||
### 1.2 文件名与顶层声明(硬约束)
|
||||
|
||||
- TSL 语法要求(仅 `.tsf`):每个 `.tsf` 文件只能有一个顶层声明,且文件基名必须与顶层声明同名。
|
||||
- TSL 语法要求(仅 `.tsf`):每个 `.tsf`
|
||||
文件只能有一个顶层声明,且文件基名必须与顶层声明同名。
|
||||
- `.tsl` 允许直接写语句,不要求顶层声明;文件名不强制,但建议清晰可检索。
|
||||
- 推荐文件名使用 `PascalCase` 以提升检索与协作一致性;扩展名按类型使用 `.tsl`/`.tsf`(两者都属于 TSL 源文件,风格规则一致)。
|
||||
- 推荐文件名使用 `PascalCase` 以提升检索与协作一致性;扩展名按类型使用
|
||||
`.tsl`/`.tsf`(两者都属于 TSL 源文件,风格规则一致)。
|
||||
- 详细约束与命名细则见 `docs/tsl/naming.md`。
|
||||
|
||||
### 1.3 依赖与分层
|
||||
@@ -34,9 +38,11 @@
|
||||
### 1.4 推荐布局(读者视角)
|
||||
|
||||
- 同类代码按“对外 API → 核心实现 → 辅助工具 → 测试/示例”的顺序组织。
|
||||
- 对外 API:尽量靠前,读者先看到“怎么用”;实现细节与 helper 放到后面(例如 `unit` 的 `interface`、`class` 的 `public`)。
|
||||
- 对外 API:尽量靠前,读者先看到“怎么用”;实现细节与 helper 放到后面(例如
|
||||
`unit` 的 `interface`、`class` 的 `public`)。
|
||||
- 对外声明尽量“收口”:
|
||||
- `unit` 的 `interface` 只放对外 `const/type/function` 声明与必要注释;实现细节与 helper 放在后部。
|
||||
- `unit` 的 `interface` 只放对外 `const/type/function`
|
||||
声明与必要注释;实现细节与 helper 放在后部。
|
||||
- `class` 的对外 API 放在 `public`;内部状态与实现细节放在 `private`。
|
||||
- 测试/示例:优先独立文件/目录,避免夹在核心实现中间(减少无关 diff 干扰 review)。
|
||||
|
||||
@@ -70,7 +76,8 @@ begin
|
||||
end
|
||||
```
|
||||
|
||||
- 多语句分支使用 `begin/end` 包裹:在 `then/else` 后换行写 `begin`,`end` 单独成行。
|
||||
- 多语句分支使用 `begin/end` 包裹:在 `then/else` 后换行写 `begin`,`end`
|
||||
单独成行。
|
||||
- `else/elseif` 等分支关键字另起一行,与上一块的 `end` 对齐。
|
||||
- 单语句分支可省略 `begin/end`(保持清晰优先;一旦分支变复杂就回退到块结构):
|
||||
|
||||
@@ -88,7 +95,8 @@ else DoOther()
|
||||
|
||||
### 2.5 控制流
|
||||
|
||||
- 多语句分支必须使用 `begin/end`;单语句分支可省略 `begin/end`,写成单行(如 `if cond then stmt`)。
|
||||
- 多语句分支必须使用 `begin/end`;单语句分支可省略 `begin/end`,写成单行(如
|
||||
`if cond then stmt`)。
|
||||
- 复杂条件拆分为具名布尔变量或小函数。
|
||||
- 早返回优于深层嵌套:
|
||||
|
||||
@@ -155,12 +163,16 @@ count = count + 1 // bad: obvious
|
||||
|
||||
## 4. 代码实践(Best Practices)
|
||||
|
||||
> 本节偏“实践建议”(should),用于提升可读性/可测试性;若目标项目有更严格的约束与检查命令,以项目落地的工具链为准(参考 `docs/tsl/toolchain.md`)。如需给自动化/AI 代理配置强约束,可参考 `.agents/tsl/code_quality.md` 与 `.agents/tsl/testing.md`。
|
||||
> 本节偏“实践建议”(should),用于提升可读性/可测试性;若目标项目有更严格的约束与检查命令,以项目落地的工具链为准(参考
|
||||
> `docs/tsl/toolchain.md`)。如需给自动化/AI 代理配置强约束,可参考
|
||||
> `.agents/tsl/code_quality.md` 与 `.agents/tsl/testing.md`。
|
||||
|
||||
### 4.1 变量与常量
|
||||
|
||||
- 默认使用不可变/只读:能用 `const` 就用 `const`;可变状态尽量压到最小作用域,并让“更新点”集中且明显。
|
||||
- 对外 API 优先只读:对外暴露用只读 property(只有 `read`,不写 `write`),内部用私有成员保存。
|
||||
- 默认使用不可变/只读:能用 `const` 就用
|
||||
`const`;可变状态尽量压到最小作用域,并让“更新点”集中且明显。
|
||||
- 对外 API 优先只读:对外暴露用只读 property(只有 `read`,不写
|
||||
`write`),内部用私有成员保存。
|
||||
|
||||
```tsl
|
||||
type User = class
|
||||
@@ -179,7 +191,9 @@ end;
|
||||
|
||||
- 签名尽量自解释:对外 API 的参数/返回值建议显式写类型注解;并用注释写清契约(可复用 3.2 的模板)。
|
||||
- 类型注解不支持 `xxx.xxx` 形式;使用单一类型名。
|
||||
- 若需标注类型来源,允许在类型名前用块注释写 `{Unit.}` 前缀,例如 `style_: {DocxML.}Style;`。该前缀仅为注释,不参与语义或类型检查,工具可能忽略;类型名仍是 `Style`(建议紧贴类型名书写)。
|
||||
- 若需标注类型来源,允许在类型名前用块注释写 `{Unit.}` 前缀,例如
|
||||
`style_: {DocxML.}Style;`。该前缀仅为注释,不参与语义或类型检查,工具可能忽略;类型名仍是
|
||||
`Style`(建议紧贴类型名书写)。
|
||||
- 示例(`{Unit.}` 前缀仅用于阅读,不改变类型名):
|
||||
|
||||
```tsl
|
||||
@@ -193,18 +207,23 @@ end;
|
||||
function RenderParagraph(para_: {DocxML.}Paragraph): void;
|
||||
```
|
||||
|
||||
- 无返回值函数显式标注返回类型为 `void`;`create`/`destroy` 作为构造/析构函数不写返回类型。
|
||||
- 无返回值函数显式标注返回类型为 `void`;`create`/`destroy`
|
||||
作为构造/析构函数不写返回类型。
|
||||
|
||||
```tsl
|
||||
function Func(a: string; b: ClassName): void;
|
||||
```
|
||||
|
||||
- 参数默认可读写(引用语义);输入参数如果不应被修改,优先使用 `const` 修饰符让意图与约束更明确。
|
||||
- 单一职责:函数过长说明拆分点已出现(建议 ≤ 40–60 行);把“纯计算”与“I/O/环境依赖(文件/网络/数据库/全局状态)”分离,降低耦合、便于测试。
|
||||
- 参数默认可读写(引用语义);输入参数如果不应被修改,优先使用 `const`
|
||||
修饰符让意图与约束更明确。
|
||||
- 单一职责:函数过长说明拆分点已出现(建议 ≤
|
||||
40–60 行);把“纯计算”与“I/O/环境依赖(文件/网络/数据库/全局状态)”分离,降低耦合、便于测试。
|
||||
- 参数组织与顺序:
|
||||
- 输入参数在前;可选配置/选项(如 `*Options`/`*Config`)居中;输出/回调在后。
|
||||
- 避免堆叠多个布尔开关参数;优先收敛到 `*Options`/`*Config`(按需在 `class` 或 `unit` 中定义)。
|
||||
- 示例:避免多个布尔开关参数(调用点难以理解 `true/false` 的含义),改为 `*Options`/`*Config`:
|
||||
- 避免堆叠多个布尔开关参数;优先收敛到 `*Options`/`*Config`(按需在 `class` 或
|
||||
`unit` 中定义)。
|
||||
- 示例:避免多个布尔开关参数(调用点难以理解 `true/false` 的含义),改为
|
||||
`*Options`/`*Config`:
|
||||
|
||||
```tsl
|
||||
// 注:参数类型名按项目实际替换(此处 bool/Any 仅为示例占位)。
|
||||
@@ -237,17 +256,23 @@ function ExportReport(path: string; data: Any; options: ExportOptions): void;
|
||||
### 4.3 错误处理
|
||||
|
||||
- 错误必须显式处理:返回失败/错误、抛出异常、或记录并降级(best-effort)。禁止“看起来成功了但其实失败了”的隐式路径。
|
||||
- **不设默认策略**:按场景选择返回/抛出/降级,并在对外注释里写清契约(参考 3.2 模板的 `Errors`)。
|
||||
- **不设默认策略**:按场景选择返回/抛出/降级,并在对外注释里写清契约(参考 3.2 模板的
|
||||
`Errors`)。
|
||||
- **返回失败/错误**:调用方有能力恢复/重试/改参数时(参数不合法、外部输入解析失败、依赖不可用等)。
|
||||
- **抛出异常**:不应发生的内部错误/不变量被破坏,继续执行风险更大时。
|
||||
- **记录并降级**:功能可选、失败不影响主流程时(例如缓存读取失败 → 当作 cache miss),必须在代码旁注释说明“为什么允许”。
|
||||
- 不要吞掉异常/错误:`try/except` 之后如果继续执行,必须有明确替代行为(返回/重试/降级)以及理由;否则应将错误继续向上抛出或返回。
|
||||
- **记录并降级**:功能可选、失败不影响主流程时(例如缓存读取失败 → 当作 cache
|
||||
miss),必须在代码旁注释说明“为什么允许”。
|
||||
- 不要吞掉异常/错误:`try/except`
|
||||
之后如果继续执行,必须有明确替代行为(返回/重试/降级)以及理由;否则应将错误继续向上抛出或返回。
|
||||
- 错误信息与日志(允许在库里打日志,但要克制):
|
||||
- 错误/日志至少包含:**做什么失败** + **关键上下文(脱敏)**,便于定位;避免只有“failed”。
|
||||
- 禁止把 Token/密码/个人数据等敏感信息写入日志、注释或错误信息(参考 `.agents/tsl/auth.md`)。
|
||||
- 错误/日志至少包含:**做什么失败** +
|
||||
**关键上下文(脱敏)**,便于定位;避免只有“failed”。
|
||||
- 禁止把 Token/密码/个人数据等敏感信息写入日志、注释或错误信息(参考
|
||||
`.agents/tsl/auth.md`)。
|
||||
- 避免重复记录:同一个错误链路尽量只在**边界层**记录一次(库里记录后,上层通常不再重复打一遍同等级日志)。
|
||||
- 示例:`try/except/end` + 降级(best-effort):
|
||||
- 注:示例中的 `Any`/`nil`/`LogWarn`/`ReadCacheFromFile` 为占位,按项目实际类型与函数替换。
|
||||
- 注:示例中的 `Any`/`nil`/`LogWarn`/`ReadCacheFromFile`
|
||||
为占位,按项目实际类型与函数替换。
|
||||
|
||||
```tsl
|
||||
// 读取可选缓存:失败允许降级为 cache miss(必须可观测,并说明原因)。
|
||||
@@ -265,8 +290,10 @@ end;
|
||||
|
||||
### 4.4 性能与可测试性
|
||||
|
||||
- 避免过早优化:先写清晰正确的代码,再用数据(profile/trace/log/基准)定位瓶颈并做最小化改动(参考 `.agents/tsl/performance.md`)。
|
||||
- 复杂逻辑要可测试:把“纯计算/解析/规则”与“I/O/环境依赖(文件/网络/DB/全局状态)”分离;I/O 层做薄封装,核心逻辑保持可单测(参考 `.agents/tsl/testing.md`)。
|
||||
- 避免过早优化:先写清晰正确的代码,再用数据(profile/trace/log/基准)定位瓶颈并做最小化改动(参考
|
||||
`.agents/tsl/performance.md`)。
|
||||
- 复杂逻辑要可测试:把“纯计算/解析/规则”与“I/O/环境依赖(文件/网络/DB/全局状态)”分离;I/O 层做薄封装,核心逻辑保持可单测(参考
|
||||
`.agents/tsl/testing.md`)。
|
||||
- 避免在热路径里做隐式昂贵操作:循环内重复 I/O、重复解析/格式化、无界缓存、隐式复制等;缓存如必须引入,明确生命周期与上限(大小/TTL/清理点)。
|
||||
- 示例:薄 I/O + 厚纯逻辑(便于测试与复用):
|
||||
- 注:示例中的 `Any`/`ReadAllText` 为占位,按项目实际类型与函数替换。
|
||||
|
||||
Reference in New Issue
Block a user