From ae63b5efe4c37d5f8f5c3bf82822288abfa34f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E8=BD=B2?= Date: Fri, 22 Aug 2025 15:26:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b4c5e2 --- /dev/null +++ b/README.md @@ -0,0 +1,210 @@ +# 编码规范 + +> 目标:统一团队的编码风格、工程结构、质量门槛与评审流程,降低维护成本并提升可读性与安全性。 + +--- + +## 总体原则(适用于所有语言) + +- **一致优先**:团队内以本规范为准;历史代码可在“动则改之”的前提下逐步迁移。 +- **自动化为先**:全部项目必须配置“格式化+ 单元测试”,并在 CI 强制执行。 +- **最小接口**:公开 API 保持最小化,隐藏实现细节;遵循“只暴露需要被依赖的东西”。 +- **可读性**:命名清晰、函数短小(通常 ≤ 40 行),模块单一职责。 +- **防御式编程**:显式边界检查、错误处理、输入校验、超时与重试策略。 +- **不可变优先**:能用不可变结构/值对象则优先使用;避免可变全局状态。 +- **安全默认**:启用严格编译/类型校验、依赖锁定与安全基线(见各语言安全节)。 +- **文档与注释**:公开类型/函数必须有 API 文档;复杂逻辑用块注释解释“为什么”。 +- **提交规范**:见 [Git 管理规范](https://gitea.fireflydt.com/docs/Git-Management)。 +- **代码评审**:至少 1 名 Reviewer;禁止自我合并;高风险改动需 2 人评审与灰度。 + +--- + +## Java 规范 + +### 版本与工具 +- 运行时:**Java 24+**。 +- 构建: Maven;统一使用 Wrapper。 + +### 代码风格 +- 缩进 **4 空格**;最大行宽 **120**;UTF-8;Unix 换行;文件末尾保留换行。 +- 包名 `com.example.app` **全小写**;类/接口/枚举 **PascalCase**;方法/变量 **camelCase**;常量 **UPPER_SNAKE_CASE**。 +- `import` 不使用通配符;分组顺序:`java.*`、`javax.*`、第三方、公司内部,组间空行。 +- 注解每行一个;参数较多时每个参数换行对齐。 + +### 语言与设计实践 +- **可空性**:参数尽量非空;需要可空用 `@Nullable`;返回值可空时优先 `Optional`(集合返回空集合)。 +- **异常**: + - 仅对可恢复情形使用受检异常;不可恢复用 `RuntimeException` 派生。 + - 禁止吞异常;记录日志并保留根因:`throw new FooException("msg", e)`。 +- **集合与不可变**:优先接口类型(`List`, `Map`);尽量使用不可变集合(`List.of()` / Guava Immutable)。 +- **并发**:优先 `Executors`/`CompletableFuture`/`java.util.concurrent`; 避免低层 `synchronized` 共享可变状态。 +- **记录日志**:使用 SLF4J;结构化日志键值对;禁止输出敏感信息。 +- **注释与文档**:公共 API 使用 Javadoc(`/** … */`),首句为概述,包含 `@param`/`@return`/`@throws`。 + +### 工程结构 +``` +app/ + src/main/java/... + src/main/resources/... + src/test/java/... +``` + +### 示例 +```java +public final class UserService { + private final UserRepo repo; + + public UserService(UserRepo repo) { this.repo = Objects.requireNonNull(repo); } + + /** 根据 ID 查询用户,未找到返回 Optional.empty()。 */ + public Optional findById(long id) { + if (id <= 0) throw new IllegalArgumentException("id must be positive"); + return repo.find(id); + } +} +``` + + +### 测试 +- 单元测试覆盖关键分支;使用 Mockito 隔离外部依赖;集成测试使用 Testcontainers。 + +--- + +## Dart / Flutter 规范 + +### 版本与工具 +- Dart **3+**(空安全);格式化:`dart format`;静态检查:`dart analyze`;测试:`dart test`/`flutter test`。 + +### 风格与规则 +- 行宽 **100**;缩进 2 空格;字符串默认 **单引号**;使用 **尾随逗号** 触发友好换行。 +- 命名:类/枚举 **PascalCase**;成员/变量 **lowerCamelCase**;常量 **lowerCamelCase** 或 `kPascalCase`(团队统一其一)。 +- `import` 使用包前缀;避免相对路径越级;公共库通过 `lib/` 暴露 API。 + +### 语言实践 +- **空安全**:用 `T?`、`late` 谨慎;尽量用 `required` 命名参数;返回空集合而非 `null`。 +- **不可变**:优先 `const` 构造与 `final` 字段;值对象使用 `equatable` 或 `records`(Dart 3)。 +- **错误处理**:UI 层捕获并展示;领域/数据层返回 `Result`/`Either` 或抛出受控异常。 + +### Flutter 特定 +- `build()` 保持轻量;提取小部件;避免在 `build` 里做副作用。 +- **状态管理**:使用 Provider,全局一致;不可混搭多套范式。 +- **主题与可访问性**:统一 `ThemeData`;文字遵循最小触达 44x44;支持深色模式与本地化。 + +### 示例 +```dart +class UserTile extends StatelessWidget { + const UserTile({super.key, required this.user}); + final User user; + + @override + Widget build(BuildContext context) { + return ListTile(title: Text(user.name), subtitle: Text(user.email)); + } +} +``` + +### 工程与测试 +- 目录:`lib/`, `test/`, `integration_test/`;导出统一入口 `lib/.dart`。 + +### 安全 +- `flutter_secure_storage` 存放机密;禁用在客户端拼接 SQL。 + +--- + +## PHP 规范 + +### 版本与工具 +- PHP **8.3+**;启用 `declare(strict_types=1);` +- 标准:**PSR-12**(编码风格)、**PSR-4**(自动加载)。 + +### 风格 +- 缩进 4 空格;行宽 120;文件使用 ` */ + public function list(): array { + return $this->repo->all(); + } +} +``` + +### 安全 +- 使用 **PDO**/ORM 预处理;绝不拼接 SQL;`password_hash`/`password_verify`;默认关闭 `display_errors`,仅记录日志。 + +### 测试 +- PHPUnit + Testdouble;对控制器使用特性/内核测试(框架自带)。 + +--- + +## C# / .NET 规范 + +### 版本与工具 +- .NET **8.0+**;启用 **Nullable Reference Types**;项目使用 SDK-style `csproj`。 +- 格式化:`dotnet format`;分析器:Roslyn + StyleCop.Analyzers;测试:xUnit(首选)或 NUnit/MSTest。 + +### 风格 +- 文件作用域命名空间:`namespace Foo.Bar;` +- 命名:类型/属性/方法 **PascalCase**;局部/参数 **camelCase**;私有字段 `_camelCase`;常量 **PascalCase**。 +- `var` 用于显而易见类型;`async` 方法以 **Async** 结尾,返回 `Task`/`Task`。 +- `using` 顶部排序;启用**顶级语句**仅限简单程序。 + +### 语言与设计 +- 优先 **记录(record)** 表示不可变值对象;表达式体成员简化;模式匹配与 `switch` 表达式提升可读性。 +- 依赖注入:`Microsoft.Extensions.DependencyInjection`;配置通过 Options 模式强类型化。 +- 错误处理:显式捕获特定异常;使用 `ILogger` 结构化日志;禁止空 catch。 + +### 示例 +```csharp +public sealed record User(Guid Id, string Name); + +public sealed class UserService +{ + private readonly IUserRepo _repo; + public UserService(IUserRepo repo) => _repo = repo ?? throw new ArgumentNullException(nameof(repo)); + + public async Task FindAsync(Guid id, CancellationToken ct) => await _repo.FindAsync(id, ct); +} +``` + +### 安全 +- 默认启用 HTTPS/HSTS;参数绑定使用验证特性(FluentValidation/DataAnnotations);机密用 `IConfiguration` + Secret Manager/Azure Key Vault。 +- 依赖通过 `Directory.Packages.props` 统一管理;开启 `dotnet list package --vulnerable`。 + +### 测试 +- xUnit:遵循 AAA;使用 `WebApplicationFactory` 做 API 集成测试;使用 `NSubstitute`/`Moq`。 + +--- + +## 安全与隐私基线(通用) + +- 秘密管理:禁止将密钥/令牌写入仓库;使用环境变量与密钥管理服务(Vault/Key Vault/Secrets Manager)。 +- 日志脱敏:邮箱、手机号、身份证、token、cookie 等敏感字段做掩码;遵循最小留存周期。 +- 依赖治理:启用锁文件(`go.sum`/`composer.lock`/`gradle.lockfile`/`Directory.Packages.props`),定期更新并审计。 +- 输入校验:所有外部输入均视为不可信,进行白名单/模式/长度校验。 +- 传输安全:默认 HTTPS/TLS1.2+;启用 HSTS/CSRF 防护/同源策略;Cookie 设置 `HttpOnly`、`Secure`、`SameSite`。 + +--- + +## 代码评审清单(适用于所有 PR) + +1. 语义:命名准确、注释到位、公共 API 有文档。 +2. 架构:单一职责、模块边界清晰、依赖方向正确、可测试性良好。 +3. 风格:符合对应语言规范;无“魔法数”;函数不超长;重复代码已抽取。 +4. 错误与边界:错误处理全面;边界条件测试齐全;超时/重试/幂等等策略明确。 +5. 安全:输入校验、权限校验、敏感信息保护、依赖与许可证合规。 +6. 性能:无不必要的 I/O/分配;关键路径有基准或指标。 +7. 可维护性:日志可观测、告警/指标完善、特性开关与回滚预案。 \ No newline at end of file