12 KiB
HealthLink-HIS 代码库优化实施计划
For agentic workers: REQUIRED SUB-SKILL: Use compose:subagent (recommended) or compose:execute to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 修复健康检查发现的 Critical/High 级别问题,提升代码质量和可维护性
Architecture: 保持现有分层架构(Controller → AppService → Service → Mapper → Entity),重点解决 God Classes、重复代码、测试覆盖等结构性问题
Tech Stack: Java 25, Spring Boot 4.0.6, MyBatis-Plus 3.5.16, JUnit 5, Mockito
任务概览
| 优先级 | 任务 | 预计时间 | 影响范围 |
|---|---|---|---|
| P0 | 删除重复文件 | 30分钟 | 2个文件 |
| P0 | 修复脆弱断言 | 1小时 | 8个测试文件 |
| P1 | 提取测试基类 | 2小时 | 新建1个基类 |
| P1 | 清理过期TODO | 1小时 | ~20个文件 |
| P2 | 拆分IChargeBillServiceImpl | 8小时 | 1个God Class |
| P2 | 添加单元测试框架 | 4小时 | 新建测试结构 |
Task 1: 删除重复文件(消除classpath冲突风险)
Covers: 架构维度 Finding 2
Files:
-
Delete:
healthlink-his-yb/src/main/java/com/healthlink/his/yb/util/YbParamBuilderUtil.java -
Delete:
healthlink-his-yb/src/main/java/com/healthlink/his/yb/dto/Yb4401InputBaseInfoDto.java -
Modify:
healthlink-his-yb/pom.xml(确认依赖) -
Step 1: 确认重复文件存在
# 验证两个文件内容相同
diff healthlink-his-domain/src/main/java/com/healthlink/his/yb/util/YbParamBuilderUtil.java healthlink-his-yb/src/main/java/com/healthlink/his/yb/util/YbParamBuilderUtil.java
- Step 2: 检查yb模块是否直接使用这些文件
# 搜索yb模块中的引用
rg "YbParamBuilderUtil" healthlink-his-yb/src --include="*.java" | grep -v "^.*YbParamBuilderUtil.java:"
rg "Yb4401InputBaseInfoDto" healthlink-his-yb/src --include="*.java" | grep -v "^.*Yb4401InputBaseInfoDto.java:"
- Step 3: 删除重复文件
rm healthlink-his-yb/src/main/java/com/healthlink/his/yb/util/YbParamBuilderUtil.java
rm healthlink-his-yb/src/main/java/com/healthlink/his/yb/dto/Yb4401InputBaseInfoDto.java
- Step 4: 验证编译通过
mvn clean compile -DskipTests
- Step 5: Commit
git add -A
git commit -m "fix: remove duplicate files to prevent classpath conflicts"
Task 2: 修复脆弱断言(提高测试可信度)
Covers: 测试维度 Finding 5A
Files:
-
Modify:
healthlink-his-application/src/test/java/com/healthlink/his/web/doctorstation/DoctorWorkstationTest.java -
Modify:
healthlink-his-application/src/test/java/com/healthlink/his/web/registration/RegistrationApiTest.java -
Modify:
healthlink-his-application/src/test/java/com/healthlink/his/web/report/ReportApiTest.java -
Step 1: 修复DoctorWorkstationTest中的脆弱断言
// 修改前 (line 221-226):
assertTrue("未授权应返回401/403", code == 401 || code == 403 || code == 200);
// 修改后:
assertTrue("未授权应返回401或403", code == 401 || code == 403);
assertFalse("未授权不应返回200", code == 200);
- Step 2: 修复RegistrationApiTest中的空断言
// 修改前 (line 221-229):
if (result.path("code").asInt() == 200) {
// If 200, check msg
}
// 修改后:
int code = result.path("code").asInt();
assertTrue("退号失败应返回错误码", code != 200 || result.path("msg").asText().contains("失败"));
- Step 3: 修复ReportApiTest中的永真断言
// 修改前 (line 126-129):
assertTrue("...", result.path("code").asInt() != 500 || result.path("code").asInt() == 500);
// 修改后:
int code = result.path("code").asInt();
assertTrue("应返回成功或业务错误", code == 200 || code == 500 || (code >= 400 && code < 500));
- Step 4: 运行测试验证
cd healthlink-his-application && mvn test -Dtest="DoctorWorkstationTest,RegistrationApiTest,ReportApiTest"
- Step 5: Commit
git add -A
git commit -m "fix(test): replace fragile assertions with meaningful validations"
Task 3: 提取测试基类(消除重复代码)
Covers: 测试维度 Finding 5D
Files:
-
Create:
healthlink-his-application/src/test/java/com/healthlink/his/web/BaseApiTest.java -
Modify: 8个测试文件(继承基类)
-
Step 1: 创建BaseApiTest基类
package com.healthlink.his.web;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class BaseApiTest {
protected static String token;
@BeforeAll
void setUp() {
// 登录获取token
Response loginResponse = RestAssured.given()
.contentType("application/json")
.body("{\"username\":\"admin\",\"password\":\"admin123\"}")
.post("/auth/login");
token = loginResponse.jsonPath().getString("token");
}
protected Response get(String path) {
return RestAssured.given()
.header("Authorization", "Bearer " + token)
.get(path);
}
protected Response post(String path, Object body) {
return RestAssured.given()
.header("Authorization", "Bearer " + token)
.contentType("application/json")
.body(body)
.post(path);
}
}
- Step 2: 修改DoctorWorkstationTest继承基类
// 修改前:
public class DoctorWorkstationTest {
// ... 重复的登录代码
// 修改后:
public class DoctorWorkstationTest extends BaseApiTest {
// 删除重复的登录代码
- Step 3: 对其他7个测试文件执行相同修改
# 批量替换(示例)
sed -i 's/public class RegistrationApiTest {/public class RegistrationApiTest extends BaseApiTest {/' RegistrationApiTest.java
- Step 4: 运行所有测试验证
mvn test -pl healthlink-his-application
- Step 5: Commit
git add -A
git commit -m "refactor(test): extract BaseApiTest to eliminate login duplication"
Task 4: 清理过期TODO(消除技术债务标记)
Covers: 技术债务维度 Finding 3
Files:
-
Modify:
healthlink-his-domain/src/main/java/com/healthlink/his/yb/util/TenantOptionUtil.java -
Modify: 其他过期TODO文件
-
Step 1: 搜索所有过期TODO
rg "TODO.*2025|FIXME|HACK" healthlink-his-domain/src healthlink-his-application/src --include="*.java" -l
- Step 2: 修复TenantOptionUtil中的过期TODO
// 修改前 (line 36):
// TODO:2025/10/17 李永兴提出的sys_option切换TenantOption临时防止报错方案,最晚2025年11月底删除
// 修改后: 直接删除这行注释(代码逻辑已正确)
- Step 3: 评估其他TODO并分类
# 统计TODO数量
rg "TODO" healthlink-his-domain/src healthlink-his-application/src --include="*.java" -c | awk -F: '{sum+=$2} END {print sum}'
- Step 4: 为高风险TODO创建issue跟踪
# 示例:为YbServiceImpl中的TODO创建备忘
echo "TODO:YbServiceImpl:274-后续处理需等待门诊住院开发完全后" >> docs/TODO_TRACKING.md
- Step 5: Commit
git add -A
git commit -m "chore: clean up expired TODOs and create tracking document"
Task 5: 拆分IChargeBillServiceImpl(解决God Class问题)
Covers: 架构维度 Finding 1, 技术债务维度 Finding 1
Files:
-
Split:
IChargeBillServiceImpl.java(2764行) → 多个服务类 -
Create:
ChargeBillQueryService.java -
Create:
ChargeBillCalculationService.java -
Create:
ChargeBillStatisticsService.java -
Step 1: 分析IChargeBillServiceImpl的方法职责
# 列出所有public方法
rg "public .* \w+\(" healthlink-his-application/src/main/java/com/healthlink/his/web/paymentmanage/appservice/impl/IChargeBillServiceImpl.java | head -20
- Step 2: 创建ChargeBillQueryService(查询相关)
package com.healthlink.his.web.paymentmanage.appservice;
import org.springframework.stereotype.Service;
@Service
public class ChargeBillQueryService {
public Page<ChargeBillDto> getChargeBills(ChargeBillQueryDto query) {
// 从IChargeBillServiceImpl迁移查询逻辑
}
public ChargeBillDetailDto getChargeBillDetail(Long billId) {
// 从getDetail()方法迁移
}
}
- Step 3: 创建ChargeBillCalculationService(计算相关)
@Service
public class ChargeBillCalculationService {
public ChargeBillSummary calculateSummary(List<ChargeItem> items) {
// 从getTotal()方法迁移
}
public BigDecimal calculateInsurance(ChargeBillSummary summary, Contract contract) {
// 从getTotalCommen()方法迁移
}
}
- Step 4: 创建ChargeBillStatisticsService(统计相关)
@Service
public class ChargeBillStatisticsService {
public StatisticsDto getStatistics(DateRange range) {
// 从getTotalCcu()方法迁移
}
}
- Step 5: 重构IChargeBillServiceImpl使用新服务
@Service
public class ChargeBillAppServiceImpl implements IChargeBillAppService {
@Autowired
private ChargeBillQueryService queryService;
@Autowired
private ChargeBillCalculationService calculationService;
@Autowired
private ChargeBillStatisticsService statisticsService;
@Override
public Page<ChargeBillDto> getChargeBills(ChargeBillQueryDto query) {
return queryService.getChargeBills(query);
}
}
- Step 6: 运行测试验证功能不变
mvn test -pl healthlink-his-application -Dtest="BillingApiTest,PaymentApiTest"
- Step 7: Commit
git add -A
git commit -m "refactor: split IChargeBillServiceImpl into query/calculation/statistics services"
Task 6: 添加单元测试框架(建立测试基础设施)
Covers: 测试维度 Finding 4
Files:
-
Create:
healthlink-his-domain/src/test/java/com/healthlink/his/BaseUnitTest.java -
Create:
healthlink-his-domain/src/test/java/com/healthlink/his/payment/ChargeBillCalculationServiceTest.java -
Step 1: 创建BaseUnitTest基类
package com.healthlink.his;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public abstract class BaseUnitTest {
// Mockito配置
}
- Step 2: 创建ChargeBillCalculationService的单元测试
package com.healthlink.his.payment;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ChargeBillCalculationServiceTest extends BaseUnitTest {
@InjectMocks
private ChargeBillCalculationService service;
@Test
void calculateSummary_withValidItems_returnsCorrectTotal() {
// Given
List<ChargeItem> items = Arrays.asList(
new ChargeItem("药品A", new BigDecimal("100.00")),
new ChargeItem("药品B", new BigDecimal("200.00"))
);
// When
ChargeBillSummary summary = service.calculateSummary(items);
// Then
assertEquals(new BigDecimal("300.00"), summary.getTotalAmount());
}
@Test
void calculateSummary_withEmptyItems_returnsZero() {
// Given
List<ChargeItem> items = Collections.emptyList();
// When
ChargeBillSummary summary = service.calculateSummary(items);
// Then
assertEquals(BigDecimal.ZERO, summary.getTotalAmount());
}
}
- Step 3: 运行单元测试
mvn test -pl healthlink-his-domain -Dtest="ChargeBillCalculationServiceTest"
- Step 4: Commit
git add -A
git commit -m "test: add unit test framework and calculation service tests"
执行顺序
- Task 1(删除重复文件)- 立即执行,风险最低
- Task 2(修复脆弱断言)- 立即执行,提高测试可信度
- Task 3(提取测试基类)- 短期执行,消除重复
- Task 4(清理过期TODO)- 短期执行,减少噪音
- Task 5(拆分God Class)- 中期执行,需要仔细设计
- Task 6(添加单元测试)- 长期执行,建立测试文化
验证标准
每个Task完成后必须验证:
mvn clean compile -DskipTests编译通过mvn test测试通过- 无新增编译警告
- git commit 包含清晰的变更说明