Files
his/healthlink-his-server/docs/compose/plans/2026-06-21-codebase-optimization.md

12 KiB
Raw Blame History

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"

执行顺序

  1. Task 1删除重复文件- 立即执行,风险最低
  2. Task 2修复脆弱断言- 立即执行,提高测试可信度
  3. Task 3提取测试基类- 短期执行,消除重复
  4. Task 4清理过期TODO- 短期执行,减少噪音
  5. Task 5拆分God Class- 中期执行,需要仔细设计
  6. Task 6添加单元测试- 长期执行,建立测试文化

验证标准

每个Task完成后必须验证

  • mvn clean compile -DskipTests 编译通过
  • mvn test 测试通过
  • 无新增编译警告
  • git commit 包含清晰的变更说明