# 代码规范与质量

<cite>
**本文引用的文件**
- [.eslintrc.cjs](file://.eslintrc.cjs)
- [.eslintrc.json（客户端）](file://client/.eslintrc.json)
- [.editorconfig](file://.editorconfig)
- [package.json（服务端）](file://package.json)
- [package.json（客户端）](file://client/package.json)
- [tsconfig.json](file://tsconfig.json)
- [tsconfig.lint.json](file://tsconfig.lint.json)
- [jest.config.js](file://jest.config.js)
- [src/index.ts](file://src/index.ts)
- [src/server.ts](file://src/server.ts)
- [client/src/peer.js](file://client/src/peer.js)
- [client/src/sender.js](file://client/src/sender.js)
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
- [client/test/inputremoting.test.js](file://client/test/inputremoting.test.js)
</cite>

## 目录
1. 引言
2. 项目结构
3. 核心组件
4. 架构总览
5. 详细组件分析
6. 依赖分析
7. 性能考虑
8. 故障排查指南
9. 结论
10. 附录

## 引言
本指南面向视频服务器项目的开发者与维护者，系统性阐述代码规范与质量控制策略，覆盖以下方面：
- ESLint 规则与 TypeScript/JavaScript 的差异化配置
- 代码格式化工具与自动格式化设置（EditorConfig）
- 命名约定与变量命名最佳实践
- 注释规范与文档编写标准
- 代码审查流程与质量检查要点
- 常见问题识别与修复方法
- 自动化质量检查工具的配置与使用

## 项目结构
该项目采用前后端分离的多包结构：
- 服务端（TypeScript）：src、test、配置文件（tsconfig、eslint、jest）
- 客户端（前端 JS/TS）：client 目录下包含公共资源、源码与测试
- 全局脚本与工具：根目录 package.json 提供 lint、test、build 等命令

```mermaid
graph TB
subgraph "服务端"
TS["TypeScript 源码<br/>src/*.ts"]
TSTest["测试<br/>test/*.test.ts"]
ESLintCJS[".eslintrc.cjs<br/>TypeScript 规则"]
JestCfg["jest.config.js<br/>测试配置"]
TSConf["tsconfig.json<br/>编译配置"]
LintTSConf["tsconfig.lint.json<br/>ESLint 专用"]
end
subgraph "客户端"
JS["前端源码<br/>client/src/*.js"]
JSTest["前端测试<br/>client/test/*.test.js"]
ESLintJSON[".eslintrc.json<br/>浏览器环境规则"]
end
RootPkg["根 package.json<br/>脚本与依赖"]
RootPkg --> ESLintCJS
RootPkg --> JestCfg
RootPkg --> TSConf
RootPkg --> LintTSConf
TS --> ESLintCJS
TSTest --> JestCfg
JS --> ESLintJSON
JSTest --> JestCfg
```

图表来源
- [.eslintrc.cjs](file://.eslintrc.cjs)
- [.eslintrc.json（客户端）](file://client/.eslintrc.json)
- [jest.config.js](file://jest.config.js)
- [tsconfig.json](file://tsconfig.json)
- [tsconfig.lint.json](file://tsconfig.lint.json)
- [package.json（服务端）](file://package.json)
- [package.json（客户端）](file://client/package.json)

章节来源
- [package.json（服务端）:1-60](file://package.json#L1-L60)
- [package.json（客户端）:1-19](file://client/package.json#L1-L19)

## 核心组件
- 代码检查（ESLint）
  - 服务端：基于 TypeScript ESLint 插件，启用推荐规则集，解析器为 TypeScript，使用独立的 tsconfig.lint.json 以避免 sourceMap 影响性能。
  - 客户端：基于 eslint:recommended 与 jest 插件，针对浏览器与 ES6 环境，强制分号与禁止多余分号。
- 测试框架（Jest）
  - 收集覆盖率、使用 ts-jest 转换 TS/TSX，测试环境为 node；客户端测试使用 jsdom 环境。
- 编辑器配置（EditorConfig）
  - 统一缩进风格、换行符、结尾换行与尾随空白处理。

章节来源
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
- [.eslintrc.json（客户端）:1-23](file://client/.eslintrc.json#L1-L23)
- [tsconfig.lint.json:1-12](file://tsconfig.lint.json#L1-L12)
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
- [.editorconfig:1-20](file://.editorconfig#L1-L20)

## 架构总览
整体质量控制链路如下：
- 开发阶段：编辑器读取 EditorConfig 进行基础格式化；保存时由 IDE 或插件执行 ESLint 校验。
- CI/本地：通过 npm/yarn scripts 执行 lint 与 test；ESLint 针对 src 与 test；Jest 覆盖服务端与客户端测试。
- 发布前：构建产物生成于 build 目录，确保 TypeScript 编译无误。

```mermaid
sequenceDiagram
participant Dev as "开发者"
participant IDE as "编辑器/IDE"
participant ESL as "ESLint"
participant Jest as "Jest"
participant TS as "TypeScript 编译器"
Dev->>IDE : 保存文件
IDE->>ESL : 触发语法与风格检查
ESL-->>Dev : 报告规则违规
Dev->>Jest : 运行测试
Jest-->>Dev : 输出测试结果与覆盖率
Dev->>TS : 执行构建
TS-->>Dev : 生成构建产物
```

图表来源
- [package.json（服务端）:5-12](file://package.json#L5-L12)
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)

## 详细组件分析

### ESLint 配置与规则
- 服务端（TypeScript）
  - 环境：node、jest
  - 继承：eslint:recommended、@typescript-eslint/eslint-recommended、@typescript-eslint/recommended、jest/recommended
  - 解析器：@typescript-eslint/parser
  - 解析选项：module、project 指向 tsconfig.lint.json
  - 关键规则：
    - 禁止 var 的 require 使用
    - any 类型放宽
    - 分号：强制；多余分号：报错
- 客户端（JavaScript）
  - 环境：browser、es6、jest
  - 继承：eslint:recommended、jest/recommended
  - 规则：强制分号、禁止多余分号

章节来源
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
- [.eslintrc.json（客户端）:1-23](file://client/.eslintrc.json#L1-L23)

### 代码格式化与 EditorConfig
- 统一规则：
  - 缩进：空格
  - 行结束符：LF
  - 缩进大小：2
  - 文件末尾插入换行
  - 字符集：UTF-8
  - 去除行尾空白
- 适用范围：ts、js、json、html

章节来源
- [.editorconfig:10-20](file://.editorconfig#L10-L20)

### TypeScript 与 JavaScript 的差异化规则
- TypeScript
  - 使用 @typescript-eslint 推荐规则，强调类型安全与结构一致性
  - 通过 tsconfig.lint.json 优化 ESLint 性能（关闭 sourceMap）
- JavaScript（客户端）
  - 面向浏览器与 ES6，强调语义正确性与简洁性
  - 保留分号一致性，避免多余分号

章节来源
- [.eslintrc.cjs:6-16](file://.eslintrc.cjs#L6-L16)
- [.eslintrc.json（客户端）:3-22](file://client/.eslintrc.json#L3-L22)
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)

### 命名约定与变量命名最佳实践
- 类型与模块
  - 类名：帕斯卡命名（如 RenderStreaming）
  - 接口/类型：帕斯卡命名（如 Options）
  - 模块导出：默认导出或具名导出保持一致，避免混用
- 变量与函数
  - 变量：小驼峰命名（如 connectionId、options）
  - 函数：动词短语或小驼峰（如 getIPAddress、createServer）
  - 常量：全大写蛇形（如 MAX_RETRIES）
- 文件与路径
  - 源文件：按功能分层组织（如 src/class、src/signaling）
  - 测试文件：与被测模块同名或以 .test 后缀
- 前端输入设备类
  - 类名：帕斯卡命名（如 Sender、Observer）
  - 属性与方法：小驼峰（如 devices、onEvent）

章节来源
- [src/index.ts:13-106](file://src/index.ts#L13-L106)
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
- [client/src/peer.js:3-188](file://client/src/peer.js#L3-L188)
- [client/src/sender.js:14-209](file://client/src/sender.js#L14-L209)

### 注释规范与文档编写标准
- 文件级注释
  - 说明模块职责、入口点与关键行为
- 函数/方法注释
  - 参数与返回值：使用 JSDoc 风格（如 @param、@returns）
  - 复杂逻辑：简述目的与边界条件
- 类注释
  - 类的用途、构造参数、事件与生命周期
- 前端类示例
  - 类定义处与关键方法处提供注释，描述事件派发与状态变化

章节来源
- [client/src/sender.js:107-112](file://client/src/sender.js#L107-L112)
- [client/src/sender.js:191-201](file://client/src/sender.js#L191-L201)

### 代码审查流程与质量检查要点
- 代码检查
  - 本地：npm run lint（服务端）与 npm run lint（客户端）
  - CI：集成 lint 与 test 步骤，确保通过后再合并
- 测试覆盖率
  - Jest 启用覆盖率收集，建议设定最小阈值
- 审查清单
  - 类型安全：TS 是否启用严格模式相关规则
  - 命名一致性：是否遵循命名约定
  - 注释完整性：关键函数/类是否具备必要注释
  - 错误处理：异常分支与日志记录
  - 性能与资源：定时任务、事件监听与清理

章节来源
- [package.json（服务端）:5-12](file://package.json#L5-L12)
- [package.json（客户端）:5-8](file://client/package.json#L5-L8)
- [jest.config.js:20-34](file://jest.config.js#L20-L34)

### 常见代码问题与修复方法
- TypeScript
  - any 类型滥用：优先使用具体类型或泛型
  - 导入路径不一致：统一相对路径或别名
  - 未使用的变量/私有成员：删除或标记为私有
- JavaScript（客户端）
  - 事件监听未移除：在组件销毁时解绑
  - 分号缺失：遵循 EditorConfig 与 ESLint 规则
  - 重复逻辑：抽取为函数或工具模块
- 通用
  - 日志与错误：使用统一的日志模块，避免直接 console
  - 资源清理：WebSocket、HTTP 请求、文件句柄等及时释放

章节来源
- [.eslintrc.cjs:18-23](file://.eslintrc.cjs#L18-L23)
- [.eslintrc.json（客户端）:19-22](file://client/.eslintrc.json#L19-L22)
- [src/server.ts:44-57](file://src/server.ts#L44-L57)

### 自动化质量检查工具配置与使用
- ESLint
  - 服务端：npm run lint 检查 src 与 test 下的 TypeScript 文件
  - 客户端：npm run lint 检查 public 与 src、test 下的 JS 文件
- Jest
  - 服务端：npm test 运行所有测试
  - 客户端：npm test 运行前端测试（需 jsdom 环境）
- TypeScript
  - 构建：npm run build 使用 tsconfig.build.json
  - ESLint 专用：tsconfig.lint.json 关闭 sourceMap，提升性能

章节来源
- [package.json（服务端）:5-12](file://package.json#L5-L12)
- [package.json（客户端）:5-8](file://client/package.json#L5-L8)
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
- [tsconfig.lint.json:1-12](file://tsconfig.lint.json#L1-L12)
- [jest.config.js:174-176](file://jest.config.js#L174-L176)

## 依赖分析
- 工具链耦合
  - ESLint 与 TypeScript 解析器耦合，解析选项指向 tsconfig.lint.json
  - Jest 与 ts-jest 耦合，支持 TS/TSX 测试文件
- 环境差异
  - 服务端：Node 环境，Jest 测试环境为 node
  - 客户端：浏览器环境，Jest 使用 jsdom 与自定义环境配置

```mermaid
graph LR
ESLintTS["@typescript-eslint/parser<br/>解析 TS/TSX"]
ESLintCfg[".eslintrc.cjs<br/>规则与插件"]
JestTS["ts-jest<br/>转换 TS/TSX"]
JestCfg["jest.config.js<br/>测试环境与扩展"]
TSConf["tsconfig.json<br/>编译配置"]
LintTSConf["tsconfig.lint.json<br/>ESLint 专用"]
ESLintCfg --> ESLintTS
ESLintCfg --> LintTSConf
JestCfg --> JestTS
JestCfg --> TSConf
```

图表来源
- [.eslintrc.cjs:12-16](file://.eslintrc.cjs#L12-L16)
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)

章节来源
- [.eslintrc.cjs:12-16](file://.eslintrc.cjs#L12-L16)
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)

## 性能考虑
- ESLint 性能
  - 使用 tsconfig.lint.json 关闭 sourceMap，减少解析开销
  - 仅对 src 与 test 目标进行检查，避免 node_modules
- 构建与测试
  - 构建输出至 build 目录，便于缓存与增量编译
  - Jest 使用 v8 覆盖率提供器，平衡速度与准确性

章节来源
- [tsconfig.lint.json:8](file://tsconfig.lint.json#L8)
- [jest.config.js:34](file://jest.config.js#L34)
- [package.json（服务端）:6](file://package.json#L6)

## 故障排查指南
- ESLint 报错
  - 规则冲突：调整 .eslintrc.cjs 或 .eslintrc.json 中的 rules
  - 解析失败：确认 tsconfig.lint.json 与 tsconfig.json 的 include/exclude 一致
- Jest 测试失败
  - 环境问题：检查 jest.config.js 的 testEnvironment 与 jsdom 配置
  - 转换问题：确认 ts-jest 版本与 tsconfig.json 设置匹配
- EditorConfig 不生效
  - 检查文件扩展名是否在 [*.{ts,js,json,html}] 范围内
  - 确认编辑器已加载 EditorConfig 插件

章节来源
- [.eslintrc.cjs:18-23](file://.eslintrc.cjs#L18-L23)
- [.eslintrc.json（客户端）:19-22](file://client/.eslintrc.json#L19-L22)
- [jest.config.js:140-145](file://jest.config.js#L140-L145)
- [.editorconfig:15-18](file://.editorconfig#L15-L18)

## 结论
本指南提供了从工具配置到编码实践的完整质量保障体系。建议团队在开发流程中坚持：
- 保存即检查：利用 EditorConfig 与 ESLint 在本地即时反馈
- 测试驱动：以 Jest 覆盖核心逻辑，持续改进覆盖率
- 文档与注释：关键模块与复杂函数必须具备清晰注释
- 审查与迭代：结合审查清单与自动化检查，逐步完善规则与流程

## 附录

### 示例：WebSocket 信令处理测试流程
```mermaid
sequenceDiagram
participant Test as "测试用例"
participant WSHandler as "WebSocket 处理器"
participant MockWS as "WebSocket 模拟"
participant Signaling as "信令服务"
Test->>MockWS : 建立连接
Test->>WSHandler : add(客户端)
WSHandler->>Signaling : 广播 connect 消息
Test->>WSHandler : onOffer(发送 offer)
WSHandler->>Signaling : 广播 offer 消息
Test->>WSHandler : onAnswer(发送 answer)
WSHandler->>Signaling : 广播 answer 消息
Test->>WSHandler : remove(断开)
WSHandler->>Signaling : 广播 disconnect 消息
```

图表来源
- [test/websockethandler.test.ts:30-99](file://test/websockethandler.test.ts#L30-L99)

### 示例：输入远程控制测试流程
```mermaid
sequenceDiagram
participant Test as "测试用例"
participant Sender as "Sender"
participant Remoting as "InputRemoting"
participant Observer as "Observer"
Test->>Sender : 创建实例
Test->>Remoting : 创建实例并绑定 Sender
Test->>Observer : 创建观察者
Test->>Remoting : subscribe(Observer)
Test->>Remoting : startSending()
Test->>Remoting : stopSending()
```

图表来源
- [client/test/inputremoting.test.js:24-48](file://client/test/inputremoting.test.js#L24-L48)