如何重构Java代码将SonarQube认知复杂度从16降至允许的15?
解决SonarQube认知复杂度过高问题:Excel负数单元格字体设红代码重构
问题背景
SonarQube抛出高优先级告警:
高优先级:重构此方法,将其认知复杂度从16降低至允许的15。
需要重构以下实现Excel负数单元格字体设为红色的Java代码,降低认知复杂度:
private void changeFontColorInMinusValue(final AssetContent content) throws IOException { if (!Objects.isNull(content)){ try (final FileInputStream inputStream = new FileInputStream(content.getTemporaryFile()); final XSSFWorkbook workbook = new XSSFWorkbook(inputStream); final ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) { final CellStyle style = workbook.createCellStyle(); XSSFFont font = workbook.createFont(); font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex()); style.setFont(font); for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); ++sheetIndex) { final XSSFSheet sheetAt = workbook.getSheetAt(sheetIndex); for (Row row : sheetAt) { Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); if(cell.getCellType() == NUMERIC && cell.getNumericCellValue() < 0){ cell.setCellStyle(style); } } } } workbook.write(byteStream); content.setTemporaryFile(AssetContentUtils.createAssetContentTempFile(new ByteArrayInputStream(byteStream.toByteArray()))); content.setContentLength(byteStream.size()); } } }
重构方案
认知复杂度超标核心原因是嵌套层级过多(外层判断+资源块+三层循环+内层判断),通过提取单一职责的子方法、提前返回的方式拆解嵌套:
重构后代码
private void changeFontColorInMinusValue(final AssetContent content) throws IOException { // 提前返回,减少嵌套层级 if (Objects.isNull(content)) { return; } try (final FileInputStream inputStream = new FileInputStream(content.getTemporaryFile()); final XSSFWorkbook workbook = new XSSFWorkbook(inputStream); final ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) { final CellStyle negativeCellStyle = createRedFontCellStyle(workbook); applyNegativeCellStyleToAllSheets(workbook, negativeCellStyle); workbook.write(byteStream); updateAssetContentWithNewData(content, byteStream); } } // 单独负责创建红色字体样式 private CellStyle createRedFontCellStyle(XSSFWorkbook workbook) { final CellStyle style = workbook.createCellStyle(); XSSFFont font = workbook.createFont(); font.setColor(HSSFColor.HSSFColorPredefined.RED.getIndex()); style.setFont(font); return style; } // 遍历所有工作表 private void applyNegativeCellStyleToAllSheets(XSSFWorkbook workbook, CellStyle style) { for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); ++sheetIndex) { applyNegativeCellStyleToSheet(workbook.getSheetAt(sheetIndex), style); } } // 遍历单张表的所有行 private void applyNegativeCellStyleToSheet(XSSFSheet sheet, CellStyle style) { for (Row row : sheet) { applyNegativeCellStyleToRow(row, style); } } // 遍历单行的所有单元格,设置样式 private void applyNegativeCellStyleToRow(Row row, CellStyle style) { Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); if (cell.getCellType() == NUMERIC && cell.getNumericCellValue() < 0) { cell.setCellStyle(style); } } } // 单独负责更新AssetContent的内容 private void updateAssetContentWithNewData(AssetContent content, ByteArrayOutputStream byteStream) throws IOException { content.setTemporaryFile(AssetContentUtils.createAssetContentTempFile(new ByteArrayInputStream(byteStream.toByteArray()))); content.setContentLength(byteStream.size()); }
优化说明
- 提前返回:将原方法的
if (!Objects.isNull(content))改为if (Objects.isNull(content)) return;,直接减少一层嵌套。 - 子方法拆分:把创建样式、遍历工作表/行/单元格、更新内容这些独立逻辑抽成单独方法,每个子方法只做一件事,大幅降低主方法的嵌套深度和认知负担。
- 可读性提升:子方法命名清晰,代码逻辑更直观,后续维护也更方便。
内容的提问来源于stack exchange,提问作者Sajith dilshan
相关产品推荐
相关产品推荐

