代码质量标准¶
文档版本: 1.0.0
最后更新: 2025-08-19
Git 提交: c1aa5b0f
作者: Lincoln
概述¶
JAiRouter 项目采用严格的代码质量标准,通过自动化工具和人工审查相结合的方式,确保代码的可读性、可维护性和安全性。
代码质量工具¶
1. Checkstyle¶
配置文件¶
- 配置文件:
checkstyle.xml
- 规则集: 基于 Google Java Style Guide,结合项目特点定制
主要规则¶
格式规范 - 使用 4 个空格缩进,禁用 Tab - 行长度不超过 120 字符 - 文件长度不超过 2000 行 - 方法长度不超过 150 行
命名规范
// 类名:PascalCase
public class LoadBalancerFactory { }
// 方法名:camelCase
public ServiceInstance selectInstance() { }
// 常量:UPPER_SNAKE_CASE
public static final int DEFAULT_TIMEOUT = 30;
// 包名:小写,点分隔
package org.unreal.modelrouter.adapter;
导入规范
// 正确的导入顺序
import java.util.List; // Java 标准库
import java.util.concurrent.*; // Java 标准库
import org.springframework.*; // 第三方库
import org.unreal.modelrouter.*; // 项目内部包
运行 Checkstyle¶
# 检查代码风格
./mvnw checkstyle:check
# 生成报告
./mvnw checkstyle:checkstyle
open target/site/checkstyle.html
2. SpotBugs¶
配置文件¶
- 包含规则:
spotbugs-security-include.xml
- 排除规则:
spotbugs-security-exclude.xml
检查类别¶
安全问题 - SQL 注入风险 - XSS 攻击风险 - 路径遍历漏洞 - 不安全的随机数生成
性能问题 - 低效的字符串操作 - 不必要的对象创建 - 资源泄漏风险
并发问题 - 线程安全问题 - 死锁风险 - 竞态条件
运行 SpotBugs¶
# 运行 SpotBugs 检查
./mvnw spotbugs:check
# 生成 GUI 报告
./mvnw spotbugs:gui
# 生成 HTML 报告
./mvnw spotbugs:spotbugs
open target/site/spotbugs.html
3. JaCoCo¶
覆盖率要求¶
- 最低覆盖率: 60% (复杂度覆盖率)
- 推荐覆盖率: 80%
- 核心模块: 90% 以上
覆盖率类型¶
- 行覆盖率: 代码行的执行覆盖
- 分支覆盖率: 条件分支的覆盖
- 复杂度覆盖率: 圈复杂度的覆盖
生成覆盖率报告¶
编码规范¶
1. 类设计原则¶
单一职责原则¶
// 好的例子:职责单一
public class TokenBucketRateLimiter implements RateLimiter {
// 只负责令牌桶限流逻辑
}
// 不好的例子:职责混乱
public class ServiceManager {
// 既管理服务,又处理限流,还负责监控
}
开闭原则¶
// 好的例子:对扩展开放,对修改关闭
public abstract class BaseAdapter {
public final Mono<String> processRequest(String serviceType, String requestBody, ServiceInstance instance) {
// 模板方法,子类扩展具体实现
return doProcessRequest(serviceType, requestBody, instance);
}
protected abstract Mono<String> doProcessRequest(String serviceType, String requestBody, ServiceInstance instance);
}
2. 方法设计¶
方法长度¶
- 单个方法不超过 50 行
- 复杂方法拆分为多个小方法
- 使用有意义的方法名
// 好的例子:方法简洁,职责明确
public ServiceInstance selectInstance(List<ServiceInstance> instances, String clientInfo) {
validateInstances(instances);
return doSelect(instances, clientInfo);
}
private void validateInstances(List<ServiceInstance> instances) {
if (instances == null || instances.isEmpty()) {
throw new IllegalArgumentException("Instances cannot be null or empty");
}
}
private ServiceInstance doSelect(List<ServiceInstance> instances, String clientInfo) {
// 具体选择逻辑
}
参数设计¶
- 方法参数不超过 5 个
- 使用对象封装多个相关参数
- 避免使用 boolean 参数
// 好的例子:使用配置对象
public LoadBalancer createLoadBalancer(LoadBalanceConfig config) {
// 实现逻辑
}
// 不好的例子:参数过多
public LoadBalancer createLoadBalancer(String type, int weight, boolean enabled,
long timeout, String strategy, Map<String, Object> properties) {
// 参数过多,难以维护
}
3. 异常处理¶
异常分类¶
// 业务异常:可恢复的错误
public class ServiceUnavailableException extends RuntimeException {
public ServiceUnavailableException(String message, Throwable cause) {
super(message, cause);
}
}
// 系统异常:不可恢复的错误
public class ConfigurationException extends RuntimeException {
public ConfigurationException(String message) {
super(message);
}
}
异常处理最佳实践¶
// 好的例子:具体的异常处理
public Mono<String> processRequest(String requestBody, ServiceInstance instance) {
return webClient.post()
.uri(instance.getBaseUrl() + instance.getPath())
.bodyValue(requestBody)
.retrieve()
.bodyToMono(String.class)
.onErrorMap(WebClientResponseException.class, ex -> {
if (ex.getStatusCode().is5xxServerError()) {
return new ServiceUnavailableException("Service temporarily unavailable", ex);
}
return new InvalidRequestException("Invalid request: " + ex.getMessage(), ex);
})
.timeout(Duration.ofSeconds(30))
.onErrorMap(TimeoutException.class, ex ->
new ServiceTimeoutException("Request timeout", ex));
}
4. 日志规范¶
日志级别¶
- ERROR: 系统错误,需要立即处理
- WARN: 警告信息,可能影响功能
- INFO: 重要的业务信息
- DEBUG: 调试信息,开发环境使用
日志格式¶
// 好的例子:结构化日志
log.info("Load balancer selected instance: type={}, instance={}, clientInfo={}",
balancerType, instance.getName(), clientInfo);
log.error("Failed to process request: serviceType={}, error={}",
serviceType, ex.getMessage(), ex);
// 不好的例子:信息不足
log.info("Selected instance");
log.error("Error occurred", ex);
敏感信息处理¶
// 好的例子:脱敏处理
log.info("User request: userId={}, requestId={}",
maskUserId(userId), requestId);
private String maskUserId(String userId) {
if (userId == null || userId.length() <= 4) {
return "****";
}
return userId.substring(0, 2) + "****" + userId.substring(userId.length() - 2);
}
5. 注释规范¶
类注释¶
/**
* 负载均衡器工厂类
*
* <p>负责创建和管理不同类型的负载均衡器实例。支持以下负载均衡策略:
* <ul>
* <li>随机选择 (random)</li>
* <li>轮询调度 (round-robin)</li>
* <li>最少连接 (least-connections)</li>
* <li>IP哈希 (ip-hash)</li>
* </ul>
*
* <p>该类是线程安全的,可以在多线程环境中使用。
*
* @author 开发者姓名
* @since 1.0.0
* @see LoadBalancer
* @see LoadBalanceConfig
*/
public class LoadBalancerFactory {
// 实现代码
}
方法注释¶
/**
* 根据配置创建负载均衡器实例
*
* <p>根据提供的配置信息创建对应类型的负载均衡器。如果配置中指定的类型
* 不支持,将抛出 IllegalArgumentException 异常。
*
* @param config 负载均衡配置,不能为 null
* @return 负载均衡器实例,永远不会返回 null
* @throws IllegalArgumentException 当配置类型不支持时
* @throws ConfigurationException 当配置参数无效时
* @since 1.0.0
*/
public LoadBalancer createLoadBalancer(LoadBalanceConfig config) {
// 实现代码
}
复杂逻辑注释¶
public ServiceInstance selectByLeastConnections(List<ServiceInstance> instances) {
// 使用最少连接算法选择实例
// 1. 遍历所有可用实例
// 2. 统计每个实例的当前连接数
// 3. 选择连接数最少的实例
// 4. 如果有多个实例连接数相同,则随机选择一个
ServiceInstance selected = null;
int minConnections = Integer.MAX_VALUE;
for (ServiceInstance instance : instances) {
int connections = connectionCounter.getConnections(instance);
if (connections < minConnections) {
minConnections = connections;
selected = instance;
}
}
return selected;
}
代码审查¶
审查检查清单¶
功能性¶
- [ ] 代码实现是否符合需求
- [ ] 边界条件是否正确处理
- [ ] 异常情况是否妥善处理
- [ ] 业务逻辑是否正确
性能¶
- [ ] 是否存在性能瓶颈
- [ ] 资源使用是否合理
- [ ] 是否有内存泄漏风险
- [ ] 算法复杂度是否合理
安全性¶
- [ ] 输入验证是否充分
- [ ] 是否存在安全漏洞
- [ ] 敏感信息是否正确处理
- [ ] 权限控制是否到位
可维护性¶
- [ ] 代码结构是否清晰
- [ ] 命名是否有意义
- [ ] 注释是否充分
- [ ] 是否遵循设计模式
测试¶
- [ ] 单元测试是否充分
- [ ] 测试用例是否覆盖边界条件
- [ ] 集成测试是否完整
- [ ] 测试代码质量是否良好
审查流程¶
- 自审: 开发者提交前自行审查
- 工具检查: 自动化工具检查通过
- 同行审查: 至少一名同事审查
- 技术负责人审查: 重要变更需要技术负责人审查
持续改进¶
质量指标监控¶
代码质量指标¶
- 代码覆盖率趋势
- 代码复杂度分布
- 技术债务统计
- 缺陷密度分析
工具集成¶
# GitHub Actions 质量检查
name: Code Quality
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Run Checkstyle
run: ./mvnw checkstyle:check
- name: Run SpotBugs
run: ./mvnw spotbugs:check
- name: Run tests with coverage
run: ./mvnw clean test jacoco:report
- name: Upload coverage to SonarCloud
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
质量改进计划¶
短期目标 (1-3个月)¶
- 提高测试覆盖率到 85%
- 消除所有 SpotBugs 高优先级问题
- 统一代码风格,消除 Checkstyle 警告
中期目标 (3-6个月)¶
- 引入 SonarQube 进行深度代码分析
- 建立代码质量门禁机制
- 完善代码审查流程
长期目标 (6-12个月)¶
- 建立代码质量文化
- 持续重构和优化
- 技术债务管理
工具配置¶
IDE 配置¶
IntelliJ IDEA¶
<!-- .idea/codeStyles/Project.xml -->
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value=" " />
<option name="RIGHT_MARGIN" value="120" />
<JavaCodeStyleSettings>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="org.unreal.modelrouter" withSubpackages="true" static="false" />
</value>
</option>
</JavaCodeStyleSettings>
</code_scheme>
</component>
VS Code¶
{
"java.format.settings.url": "checkstyle.xml",
"java.checkstyle.configuration": "checkstyle.xml",
"java.spotbugs.enable": true,
"editor.rulers": [120],
"editor.insertSpaces": true,
"editor.tabSize": 4
}
Maven 配置优化¶
快速构建配置¶
<!-- pom.xml -->
<profiles>
<profile>
<id>fast</id>
<properties>
<maven.test.skip>true</maven.test.skip>
<checkstyle.skip>true</checkstyle.skip>
<spotbugs.skip>true</spotbugs.skip>
<jacoco.skip>true</jacoco.skip>
</properties>
</profile>
</profiles>
质量检查配置¶
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<violationSeverity>warning</violationSeverity>
</configuration>
</plugin>
通过遵循这些代码质量标准,JAiRouter 项目能够保持高质量的代码库,提高开发效率和系统稳定性。