Skip to content

技术规范

本文档用于说明 PCL CE 启动器开发过程中应遵循的基础规范,包括命名规范、项目开发规范、提交信息规范以及文件格式要求等内容。

🚧 文档尚未完善

本文仍在完善中,欢迎开发者提交 PR 补充或修正文档内容。

规范用语说明

本文中的规范性用语含义如下:

用语含义
必须 / 不得强制要求,提交内容应严格遵守
应 / 不应默认要求,除非有明确理由,否则应遵守
建议 / 推荐非强制要求,但通常有助于提升可维护性
可以允许的做法,可根据实际情况选择

基本命名规范

命名规范的目标是提高代码可读性,使开发者可以直接从名称判断符号的作用域、类型或用途,减少对 IDE 上下文提示的依赖,并尽可能避免因作用域或类型混淆导致的问题。

PCL CE 代码库中仍存在部分历史遗留的不规范命名。新增代码应优先遵循本文规范;修改旧代码时,应在不引入额外风险的前提下逐步修正。

变量、字段、属性与事件

本节适用于局部变量、参数、字段、属性、事件等可绑定或保存值的符号。除非特别说明,下表中的成员均指非静态成员。

类别命名规范示例
局部变量、方法参数、构造器参数camelCasename runningThread resourceMap
私有属性、私有只读字段_PascalCase_Items _PageMap
私有字段、静态私有字段_camelCase_parameters _runningThreads _hasDisposed
主构造器属性(record)、事件及其他成员PascalCaseName CurrentThread ActivePageCollection

提示

此处的“字段”包含部分历史文档或旧代码中称为“全局变量”的成员级变量。

方法

本文将面向对象中的函数类型成员统一称为方法。除局部函数外,大多数托管式面向对象语言中的函数通常都以方法形式存在。

类别命名规范示例
非私有方法、静态非私有方法、局部方法PascalCaseStart() ComposeMessage() WriteLogItem()
私有方法_PascalCase_StartInternal() _RaiseChanged()

类型

类型包括但不限于类、接口、枚举、记录、委托等可以作为类型使用的符号。

类别命名规范示例
接口IPascalCaseICollection ILifecycleService IConfig
其他类型PascalCaseLaunchProfile ConfigSource PageState

特殊命名要求

类别要求
事件不应以 On 开头
AutoResetEventManualResetEventManualResetEventSlim 等事件同步对象应以 Event 结尾

项目开发规范

本节说明项目开发中的标准用法和注意事项。新增代码应优先遵循本节要求;修改旧代码时,应在保持兼容性的前提下逐步迁移。

代码变更范围

每次提交或 PR 应尽量只处理一个问题或一类修改。若同时包含多个不相关的修改,会增加 review 难度,也不利于后续回滚和问题定位。

提交内容不应包含与本次修改无关的文件变更,包括但不限于:

  • IDE 自动格式化产生的大量无关 diff;
  • 与功能修改无关的缩进、空格、换行符调整;
  • 本地配置文件、临时文件或构建产物;
  • 未说明原因的批量重排、重命名或迁移。

若某些看似无关的修改确有必要,应在提交信息或 PR 描述中说明原因。

旧代码风格处理

修改已有文件时,应在符合规范的前提下尽量保留原有代码风格,包括缩进、空行、成员排列位置等,以减少无关 diff。

若原文件明显不符合本文规范,可以先单独提交一次格式修正,再在后续提交中进行功能修改。格式修正提交应使用 style 类型。

不应在功能提交中混入大量格式化修改。若功能修改与格式化修改混在一起,维护者可能会要求拆分提交。

可维护性要求

新增代码应优先保证可读性和可维护性,不应为了减少行数或追求技巧性写法而牺牲清晰度。

以下写法应尽量避免:

  • 过深的嵌套逻辑;
  • 难以判断状态来源的隐式副作用;
  • 重复实现项目中已有的工具方法;
  • 为单一场景引入过度复杂的抽象;
  • 无必要的全局状态或静态可变状态;
  • 没有明确生命周期管理的后台任务、事件订阅或资源占用。

若新增逻辑较复杂,应通过合理拆分方法、添加必要注释或补充测试来降低维护成本。

goto 与代码标签

不得在新增代码中使用 goto 语句和代码标签,除非该场景存在非常明确且无法替代的技术理由。

如果某个功能看起来只能通过 goto 实现,通常说明流程设计需要重新整理。由于跳转结构维护成本较高,包含 goto 的 PR 很可能会被维护者拒绝。

测试与提交前检查

与业务逻辑有关的代码,应在本地完成基本测试后再提交。仅修改文档、注释或 README 等文本内容时,可以根据修改范围决定是否需要运行完整测试。

提交前应至少检查以下内容:

  • 项目能否正常构建;
  • 修改过的功能是否能基本运行;
  • 是否存在与本次修改无关的文件变更;
  • 是否误提交临时文件、构建产物或本地配置;
  • 提交信息是否符合本文的提交信息规范;
  • 所有提交是否附带已验证签名。

若使用 IDE 或图形化 Git 工具提交,也应在提交前逐个文件检查 diff,确认所有变更都属于本次修改范围。

AI 工具使用规范

项目允许贡献者合理使用 AI 工具,例如 GitHub Copilot、ChatGPT、DeepSeek、Claude 等,以提升开发效率。

AI 只能作为辅助工具。提交者必须理解、审查并维护自己提交的全部内容,不得将未经确认的 AI 生成结果直接作为最终代码提交。

重要

若 PR 不符合本节要求,维护者可能会关闭该 PR。若多次提交不符合要求的 PR,维护者有权限制相关贡献者继续参与仓库活动。

注明使用的模型及版本

若提交内容包含 AI 生成或 AI 实质性改写的代码,提交者必须明确注明所使用的模型及版本。

可以在提交信息末尾或 PR 标题末尾添加模型标识,例如:

text
[DeepSeek-V3.2]
[Claude-Opus-4.6]
[GPT-5.1]

示例:

text
fix(scope): 修复某功能在特定情况下的异常 [GPT-5.1]

若同一 PR 中使用了多个模型,应在 PR 描述中说明各模型的大致用途。

禁止直接提交 AI 生成的大型 PR

大型 PR 的判定标准如下:

  • 一次性新增或修改代码超过 200 行;
  • 或一次性修改超过 5 个 .cs.xaml 文件。

对于此类 PR,不得将 AI 生成的代码未经拆分、理解和重构就直接提交。

提交者应将大型任务拆分为多个较小的提交,并确保每一处逻辑变更都已被人工理解、审查和验证。否则,维护者可能会拒绝或关闭该 PR。

禁止提交未审查的低质量 AI 代码

AI 生成的代码可能存在虚构 API、逻辑漏洞、重复造轮子、过度设计、风格不一致或性能问题。提交者必须自行审查并修正这些问题。

提交前应至少检查以下内容:

  • 代码风格是否符合本文规范;
  • 是否存在未处理的 TODO 注释;
  • 是否使用了不存在的 API、参数或类型;
  • 是否重复实现了项目中已有的工具;
  • 是否引入了不必要的依赖;
  • 是否存在明显性能问题;
  • 设计是否过度复杂;
  • 是否能够解释新增代码的实现思路和行为边界。

维护者没有义务帮助提交者审查未经整理的 AI 生成代码。若代码明显由 AI 生成且缺乏人工审查痕迹,相关 PR 可能会被直接关闭。

生命周期与服务

生命周期管理

生命周期系统的基本概念参见 生命周期简介

调用服务相关内容时,必须确保被调用服务已经完成初始化。若调用顺序无法保证,可能会引发 NullReferenceExceptionInvalidOperationException 等异常。

对于同步服务,应满足以下条件之一:

  • 在更晚的生命周期状态中调用;
  • 在相同生命周期状态的异步服务初始化中调用;
  • 在相同生命周期状态中,由优先级更低的同步服务初始化逻辑调用。

对于异步服务,只应在更晚的生命周期状态中调用,不应在相同生命周期状态中假定其已经完成初始化。

配置系统

配置系统的基本概念参见 应用配置系统简介

为方便维护,新增配置项应尽可能统一声明在核心库的 Config.cs 文件中,并为配置项添加必要注释。

若可以明确确认某个配置项只在单一体系内部使用,则可以在该体系内部声明。

注册配置项事件前,应确认事件处理逻辑具有足够好的性能。配置系统的所有事件都会同步执行,以保证配置值的全局一致性。因此,性能较差、耗时较长或可能阻塞的事件处理逻辑会直接影响配置读写流程。

编译期代码生成优化

新增代码应尽可能使用 .NET 提供的编译期源生成能力,减少运行时反射、动态初始化和重复编译带来的开销。

正则表达式

.NET 7 引入了 GeneratedRegexAttribute,用于在编译期预生成正则表达式匹配逻辑,以提升运行时性能。

新增的正则匹配逻辑应遵循以下要求:

  • 新增的非既有体系正则匹配必须使用 GeneratedRegex
  • 不应动态初始化可静态确定的正则表达式;
  • 新增的正则参数方法,除非有特殊需求,否则应接收 Regex 实例,而不是接收字符串形式的正则表达式;
  • 推荐将新的正则表达式声明添加到核心库的 Utils/RegexPatterns.cs 文件中。

GeneratedRegex 的规范用法可参考核心库中的 Utils/RegexPatterns.cs

外部库调用(P/Invoke)

.NET 7 引入了 LibraryImportAttribute,用于在编译期预生成静态封送代码,并使 P/Invoke 调用可以被 inline 优化。

新增 P/Invoke 调用应遵循以下要求:

  • 必须使用 LibraryImport 替代 DllImport
  • 使用 LibraryImport 时,应使用 partial 关键字,而不是 extern
  • 推荐优先使用静态封送特性;
  • 在适合的场景中,可以使用 Span<T> 等类型安全地处理指针导出数据,以提高安全性和性能;
  • 除非确有必要,不应将 P/Invoke 声明暴露到当前类范围之外。

提示

LibraryImport 要求方法使用 partial 关键字;DllImport 常见写法中的 extern 不适用于该模式。

提示

官方示例中 P/Invoke 声明的可见性可以放宽到 internal,但为了提升可维护性,项目中仍推荐将 LibraryImport 声明为 private

提交信息规范

提示

本节部分内容来自仓库原 CONTRIBUTING.md 文件,感谢原作者 @WorldHim、@wyc-26、@3gf8jv4dv 的贡献。

提交签名要求

PCL CE 仓库要求 PR 中的所有提交都附带已验证签名。

提交者应使用 GitHub 支持的 GPG 签名或 SSH 签名,并确保提交邮箱与 GitHub 账户中已验证的邮箱一致。

未附带已验证签名的提交可能无法合并。若提交显示为 Unverified,应先修复签名配置,再重新提交或修正提交历史。

简单格式

简单格式适用于单行提交信息和 PR 标题。

text
type(scope?): digest

各字段含义如下:

字段要求
type必须使用英文小写,表示提交类型
scope可选,应使用英文说明影响的模块或子系统
digest应使用中文概括提交内容,并以动词原型开头

scope 应使用英文小写。若包含多个单词,应使用短横线连接,例如 profilelifecyclejava-managerpc

digest 应说明提交具体做了什么。必要的专业名词可以使用英文。推荐写法包括:

text
feat(profile): 支持可选的高级材质
fix(java-manage): 修复 Java 8 及以前的版本无法被正确识别
imp(rpc): 默认启用 RPC 服务

提示

scope 后面的冒号与 digest 之间必须保留一个空格。

提交类型

类型说明
feat / feature引入新特性。通常是用户可感知的更改,例如深色模式、Java 管理;也可以是仅开发者可感知的能力,例如引入生命周期管理
fix修复线上或开发中发现的 bug,使程序行为恢复预期
imp / improve优化现有功能的交互体验、可读性等,通常是用户可感知的更改
ref / refactor重构现有代码结构或实现方式,不大幅改变外部功能,主要改善可维护性
docs仅修改文档内容,例如 README、注释、API 文档等,不涉及程序逻辑
style与功能无关的代码格式调整,包括但不限于空格、缩进、分号、命名风格等
perf / performance专门针对性能的优化,例如算法改进、缓存方案、渲染优化等
test添加或修改单元测试、集成测试、测试脚本等
chore构建流程维护、依赖升级、项目配置调整等与业务逻辑无关的杂项
bump版本相关更改,例如发布新 release 版本
ci修改 CI/CD 配置文件、自动化脚本、构建管道等

提交类型应尽量选择最贴近修改内容的类型。部分类型较为泛用,但在存在更具体分类时,不应使用泛用分类。

例如:

  • 修复 CI 构建失败时,应使用 ci,而不是 fix
  • 修复可通过提升设备性能缓解的问题时,应优先考虑是否属于 perf
  • 修改构建配置或添加依赖项时,应使用 chore,而不是 feat

digest 编写要求

digest 应简洁、明确,并能直接看出本次提交的实际修改内容。

digest 不应使用以下写法:

  • 过去时或将来时;
  • 单纯的名词短语;
  • 含糊不清、无法看出具体关联的描述;
  • 末尾句号。

错误示例:

text
docs: 深色模式
fix: 更正了 typo
imp: 一个高占用功能现在会默认关闭

推荐写法:

text
docs: 补充深色主题适配说明
fix: 更正下载页面的 NeoForge 拼写错误
imp: 默认关闭资源扫描中的高占用检查

一个清晰的 digest 通常不应超过 30 个汉字或 50 个英文字母。

多行格式

多行格式适用于需要详细说明修改内容的提交信息。

text
type(scope?): subject

body

footer

第一行的规则与简单格式基本一致,但 subject 不需要完整展开所有细节。

body 用于详细描述提交内容,应包含修改动机,以及与之前行为的差异。

footer 可包含破坏性改动、合作作者信息或关联 issue。若没有对应内容,可以省略。

关联 issue 可使用以下格式:

text
Close #234
Close #234, #114, #514

若存在破坏性改动,应在 footer 中明确说明。

回滚提交

回滚某个提交或 PR 时,提交信息应以 revert: 开头。

text
revert: digest (hash)

其中:

字段说明
digest原提交信息首行
hash原提交节点 hash,或原 PR ID。PR ID 应以 # 开头

示例:

text
revert: feat(profile): 支持可选的高级材质 (#123)

杂项规范

换行符与编码

换行符与文件编码差异可能导致大量无意义更改,增加 review 和后期溯源成本。

新增文件必须使用以下格式:

项目要求
换行符LF
文件编码标准 UTF-8
BOM不附带 BOM

修改已有文件时,应尽量遵循原文件格式。若原文件使用不同换行符或编码,不应为了统一格式而产生大量无关 diff,以免与其他分支中的修改产生冲突。

因换行符或编码变化造成大量无意义更改的 PR,可能会被要求重新提交,严重时可能被直接关闭。

Git 换行符处理

Git 可以自动处理提交内容的换行符,一般不需要手动管理本地文件换行符。详情可参考 GitHub 文档页面

Rider 编码设置

Rider 可以在设置中指定默认使用标准 UTF-8 编码。部分编辑器或 IDE 可能会自动添加 BOM,因此提交前应注意检查文件首行是否出现无意义更改。若文件首行产生异常 diff,通常需要检查是否被添加了 BOM。

Released under the Creative Commons Attribution-ShareAlike 4.0 International Public License (CC BY-SA 4.0).