docs(agents): pointerize duplicated DB rules and add index width guard

18 个服务与公共模块重复复制的 314 字符数据库访问约束改为指向后端根唯一定义,并给索引门禁增加防退化校验。

- 18 处重复段落合并为一句指针,规则正文只在后端根 AGENTS.md 维护
- 门禁新增路由表行宽上限(根/Admin/Client/后端根/海外 PDA),防止业务规则重新回流表格
- 同步包含此前未提交的链接与锚点、表格存在性校验
- 仅索引文档与门禁脚本,未改动业务代码
This commit is contained in:
2026-10-20 12:45:41 +08:00
parent e829519044
commit 19745e46c1
19 changed files with 84 additions and 37 deletions
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 模块定位
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责边界
+66 -1
View File
@@ -74,11 +74,63 @@ function Assert-MarkdownTableUnique([string]$path, [string]$heading, [int]$keyCo
if ($keyColumn -ge $cells.Count -or $cells[$keyColumn] -match '^:?-{3,}:?$') { continue }
$keys.Add($cells[$keyColumn])
}
if (-not $inside) {
Add-Failure "$scope 缺少章节: $heading"
return
}
if ($keys.Count -lt 2) {
Add-Failure "$scope 缺少表头或入口行: $heading"
}
$keys | Group-Object | Where-Object Count -gt 1 | ForEach-Object {
Add-Failure "$scope 存在重复索引键: $($_.Name)($($_.Count) 次)"
}
}
# 只检查指定文档的本地 Markdown 链接与标题锚点,不递归读取目录或把代码片段当路径。
function Assert-MarkdownLinks([string]$path, [string]$text, [string]$scope) {
foreach ($link in [regex]::Matches($text, '(?<!!)\[[^\]\r\n]+\]\((?<target><[^>\r\n]+>|[^\s)]+)\)')) {
$target = $link.Groups['target'].Value.Trim([char[]]'<>')
if ($target -match '^[a-zA-Z][a-zA-Z0-9+.-]*:') { continue }
$parts = $target -split '#', 2
$linkedPath = if ($parts[0]) { Join-Path (Split-Path -Parent $path) ([Uri]::UnescapeDataString($parts[0])) } else { $path }
$script:checked++
if (-not (Test-Path -LiteralPath $linkedPath -PathType Leaf)) {
Add-Failure "$scope 链接目标不存在: $target"
continue
}
if ($parts.Count -lt 2 -or -not $parts[1] -or [IO.Path]::GetExtension($linkedPath) -ne '.md') { continue }
$script:checked++
$linkedText = if ($linkedPath -eq $path) { $text } else { Get-Content -LiteralPath $linkedPath -Raw }
$headingIds = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal)
foreach ($heading in [regex]::Matches($linkedText, '(?m)^#{1,6}[ \t]+(.+?)\r?$')) {
$title = $heading.Groups[1].Value -replace '[ \t]+#+[ \t]*$', ''
$slug = [regex]::Replace($title.Trim().ToLowerInvariant(), '[^\p{L}\p{M}\p{N}_\s-]', '') -replace '\s+', '-'
$headingId = $slug
$suffix = 0
while ($headingIds.Contains($headingId)) { $suffix++; $headingId = "$slug-$suffix" }
[void]$headingIds.Add($headingId)
}
if (-not $headingIds.Contains([Uri]::UnescapeDataString($parts[1]))) {
Add-Failure "$scope 标题锚点不存在: $target"
}
}
}
# 路由表只放定位,不放规则;单行过宽意味着业务规则又回流到表格。
function Assert-TableRowWidth([string]$path, [string]$heading, [int]$maxLength, [string]$scope) {
$script:checked++
$inside = $false
foreach ($line in Get-Content -LiteralPath $path) {
if ($line -eq $heading) { $inside = $true; continue }
if ($inside -and $line.StartsWith('## ')) { break }
if (-not $inside -or -not $line.StartsWith('|')) { continue }
if ($line -match '^\|[\s\-:|]+\|$') { continue }
if ($line.Length -gt $maxLength) {
Add-Failure "$scope 路由行过宽($($line.Length) > $maxLength):$($line.Substring(0, 40))…"
}
}
}
$rootAgentsPath = Join-Path $workspaceRoot 'AGENTS.md'
$adminAgentsPath = Join-Path $workspaceRoot 'apps/admin-web/AGENTS.md'
$clientAgentsPath = Join-Path $workspaceRoot 'apps/client-web/AGENTS.md'
@@ -90,6 +142,7 @@ $rootAgents = Read-RequiredText $rootAgentsPath
$businessIndexPath = Join-Path $workspaceRoot 'docs/业务快速索引.md'
$businessIndex = Read-RequiredText $businessIndexPath
Assert-Contains $rootAgents 'docs/业务快速索引.md' '根按需业务索引入口'
Assert-MarkdownLinks $rootAgentsPath $rootAgents '根导航与文档链接'
Assert-MarkdownTableUnique $businessIndexPath '## 业务快速路由表' 0 '详细业务路由表'
Assert-MarkdownTableUnique $businessIndexPath '## 常用说法与歧义分流' 0 '业务歧义分流表'
Assert-Contains $businessIndex '## 业务快速路由表' '详细业务表存在'
@@ -138,6 +191,13 @@ foreach ($applicationDetailIndex in @(
Assert-Path "$($applicationDetailIndex.Base)/docs/../AGENTS.md"
}
Assert-MarkdownTableUnique $adminAgentsPath '## 模块快速路由' 0 'Admin 短入口表'
Assert-TableRowWidth $rootAgentsPath '## 业务快速路由表' 260 '根业务快速路由表'
Assert-TableRowWidth $rootAgentsPath '## 项目快速入口' 260 '根项目快速入口'
Assert-TableRowWidth $rootAgentsPath '## 专项约束按需入口' 200 '根专项约束表'
Assert-TableRowWidth $adminAgentsPath '## 模块快速路由' 200 'Admin 短入口表'
Assert-TableRowWidth $clientAgentsPath '## 模块快速查询' 160 'Client 短入口表'
Assert-TableRowWidth $backendAgentsPath '## 服务路由(按关键词定位)' 160 '后端根服务路由表'
Assert-TableRowWidth $overseasPdaAgentsPath '## 页面与能力快速索引' 200 '海外 PDA 入口表'
Assert-MarkdownTableUnique $adminIndexPath '## 模块快速路由' 0 'Admin 详细索引表'
Assert-MarkdownTableUnique $clientAgentsPath '## 模块快速查询' 0 'Client 短入口表'
Assert-MarkdownTableUnique $clientIndexPath '## 模块快速查询' 0 'Client 详细索引表'
@@ -615,7 +675,12 @@ Assert-Contains $rootAgents 'baiyue-firstleg/' '根 AGENTS.md'
Assert-MarkdownTableUnique $rootAgentsPath '## 项目快速入口' 0 '根项目表'
Assert-MarkdownTableUnique $rootAgentsPath '## 项目快速入口' 1 '根项目目录'
Assert-MarkdownTableUnique $rootAgentsPath '## 业务快速路由表' 0 '根业务路由表'
Assert-MarkdownTableUnique $rootAgentsPath '## 原型入口索引' 0 '根原型表'
Assert-Contains $rootAgents 'docs/业务快速索引.md#原型入口索引' '根按需原型入口'
Assert-MarkdownTableUnique $businessIndexPath '## 原型入口索引' 0 '按需原型入口表'
$prototypeRoutes = (($businessIndex -split '(?m)^## 原型入口索引\r?$', 2)[1] -split '(?m)^## ', 2)[0]
$prototypeFiles = [regex]::Matches($prototypeRoutes, '`([^`]+\.(?:md|html|json|js|vue))`') |
ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique
foreach ($prototypeFile in $prototypeFiles) { Assert-Path $prototypeFile }
# 前端当前全部业务模块必须能从应用级索引命中。
$applications = @(
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界
+1 -2
View File
@@ -2,8 +2,7 @@
## 数据库访问与中文注释约束
- 强制遵守根 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则:正常业务访问统一为 `Controller → Service → Repository → Mapper`,不得省略 Repository 或跨层直调;生产 SQL 由 Mapper 执行,Repository 不得直接使用 JdbcTemplate 或原生 JDBC。非 HTTP 入口从 Service 进入;无数据库模块不引入数据库访问。
- 每个手写方法及构造器须有简短中文说明;核心业务规则、复杂 SQL、事务、锁、幂等、并发及失败处理须补充适量中文注释,重点说明原因和边界。新增、修改方法立即执行,触及的存量代码同步整改。
- 强制继承 `../AGENTS.md` 的“数据库访问与中文代码注释”全部规则;该节是分层、SQL 执行和方法/核心逻辑中文注释的唯一维护处,本模块不另设例外。
## 职责与边界