You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何降低Java代码认知复杂度 解决Sonar超15阈值问题

代码认知复杂度超标原因及优化方案

为什么复杂度会超过15阈值

Sonar的认知复杂度不是只统计嵌套if条件,循环、条件分支、try/catch、逻辑与/或运算符都会累加分数,且结构嵌套层级越深,单次加分越高。
你认为代码里没有嵌套条件是判断失误:内层for循环、try/catch块都属于嵌套结构,叠加内部的if判断、逻辑运算符,累加后刚好到16分,超过15的阈值。

优化方案

1. 先修正明显的逻辑错误

你现在代码里isHls.set(true)写在了try/catch块外面,是无条件执行的——只要进入内层文件循环,不管有没有找到m3u8格式的HLS文件,isHls都会被设为true,完全不符合注释里“循环判断媒体是否为HLS”的设计目的,正确的写法是把这行代码移到isMediaHls判断为true的分支内,只有真的检测到HLS文件时才标记为true。
另外注意:如果某个路径对应的目录不存在,你现在直接return会终止整个方法,后续剩下的所有路径都不会被处理,如果不是预期逻辑,应该改成continue跳过当前无效路径即可。

2. 最低成本降复杂度(直接满足Sonar要求)

认知复杂度最通用的优化方式就是拆分子方法,把内层循环里单个文件的处理逻辑抽成独立的私有方法,原来嵌套在两层循环里的try/catch、if分支、逻辑运算符的复杂度都会被算到子方法里,主方法的复杂度会直接降到阈值以下。
抽离后的主方法代码示例:

private void processMedia(Integer mediaId, List<String> hiresPhysicalPaths) {
    final AtomicBoolean isHls = new AtomicBoolean(false);
    String mediaIdString = mediaId.toString();
    // 固定路径提到循环外,避免重复调用
    String rootPath = MediaRepositoryTools.getCurrentMediaPhysicalRootPath(App.getApplicationSession());
    
    for (String hiresPhysicalPath : hiresPhysicalPaths) {
        REPORT.info("Process media version {} for media {} ", hiresPhysicalPath, mediaId);
        String folderName = StringUtils.substringBefore(hiresPhysicalPath, "/");
        File dir = new File(rootPath, folderName);
        REPORT.info("Dir : {}", dir);
        
        File[] directoryListing = dir.listFiles();
        if (directoryListing == null) {
            REPORT.warn("Dir is not really a directory");
            // 根据业务需求决定是return终止整个流程,还是continue跳过当前无效路径
            return;
        }

        for (File child : directoryListing) {
            // 单文件处理逻辑抽离到子方法
            processSingleMediaChild(child, mediaIdString, hiresPhysicalPath, mediaId, isHls);
        }
    }
    App.getService(TransactionService.class).withTransaction(() -> this.updatePreviewGeneratedFlagForMedia(mediaId, isHls.get()));
}

对应的单文件处理子方法:

private void processSingleMediaChild(File child, String mediaIdString, String hiresPhysicalPath, Integer mediaId, AtomicBoolean isHls) {
    String ext = FilenameUtils.getExtension(child.getName()).toLowerCase();
    String childFileName = FilenameUtils.getBaseName(child.getName());
    
    try {
        if (isMediaHls(mediaIdString, childFileName, ext)) {
            miseAJourFichierHLS(child);
            isHls.set(true);
            REPORT.info("Le fichier m3u8 a été mis à jour pour la version : {} du média {} ", hiresPhysicalPath, mediaId);
        } else {
            REPORT.info("Le fichier m3u8 n'a pas été mis à jour pour la version : {} du média {} ", hiresPhysicalPath, mediaId);
        }
    } catch (IOException e) {
        REPORT.error("Unable to update the HLS file for media " + mediaId, e);
    }

    if (childFileName.startsWith(mediaIdString) && isFileNeededToBeDeleted(child.getName(), isHls.get())) {
        this.copyOrDelete(child);
    }
}

额外优化点

这个方法里没有多线程并发修改isHls的场景,完全没必要用AtomicBoolean,换成普通可变布尔值即可,不过这个不影响复杂度,属于代码规范层面的优化。

内容的提问来源于stack exchange,提问作者JhinKazama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:48:25