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

如何重构C#函数以降低SonarCube检测的认知复杂度?

重构方案:将认知复杂度降至15以下

把重复逻辑、独立职责的代码拆成单一功能的小方法,同时减少嵌套层级,就能快速降低认知复杂度。以下是具体步骤和重构后的代码:

1. 抽通用方法:根据ID/Guid获取产品

原代码里有两次几乎一致的产品查询逻辑(获取Tile和Edge),抽成泛型方法消除重复分支:

private T GetProductByIdOrGuid<T>(string id) where T : class
{
    if (Guid.TryParse(id, out var guid))
    {
        return ProductUtilities.GetProduct<T>(guid);
    }
    
    if (int.TryParse(id, out var intId))
    {
        return ProductUtilities.GetProduct<T>(intId);
    }
    
    return null;
}

2. 抽参数验证方法

把开头的ProductId合法性校验抽出来,提前返回错误,减少主方法的嵌套:

private IActionResult ValidateProductId(string productId)
{
    if (string.IsNullOrWhiteSpace(productId))
    {
        return new ObjectResult(new { Error = "You need to specify a product id" })
        { StatusCode = (int)HttpStatusCode.InternalServerError };
    }
    
    return null;
}

3. 抽SizeId解析方法

把sizeId的拆分、数值解析逻辑独立出来,处理格式异常:

private (double? Length, double? Width) ParseSizeId(string sizeId)
{
    if (string.IsNullOrWhiteSpace(sizeId))
    {
        return (null, null);
    }
    
    var split = sizeId.Split('-');
    if (split.Length != 2)
    {
        return (null, null);
    }
    
    if (double.TryParse(split[0], out var length) && double.TryParse(split[1], out var width))
    {
        return (length, width);
    }
    
    return (null, null);
}

4. 抽变体筛选逻辑

把Imperial/Metric两种单位下的维度筛选条件拆成独立方法,消除主方法的分支嵌套:

private IQueryable<RockstarProductTileVariant> FilterVariantsByDimensions(IQueryable<RockstarProductTileVariant> variants, 
                                                                         double? length, double? width, double? thickness, 
                                                                         bool isImperial)
{
    if (isImperial)
    {
        return variants
            .Where(x => length == null || x.Rockstar_RockstarProductTileVariant_TileLengthInches == length || x.Rockstar_RockstarProductTileVariant_TileLengthFeet == length)
            .Where(x => width == null || x.Rockstar_RockstarProductTileVariant_TileWidthInches == width || x.Rockstar_RockstarProductTileVariant_TileWidthFeet == width)
            .Where(x => thickness == null || x.Rockstar_RockstarProductTileVariant_TileThicknessInches == thickness || x.Rockstar_RockstarProductTileVariant_TileThicknessFeet == thickness);
    }
    else
    {
        return variants
            .Where(x => length == null || x.Rockstar_RockstarProductTileVariant_TileLengthInches == length)
            .Where(x => width == null || x.Rockstar_RockstarProductTileVariant_TileWidthInches == width)
            .Where(x => thickness == null || x.Rockstar_RockstarProductTileVariant_TileThicknessInches == thickness);
    }
}

5. 抽结果构建方法

把获取Edge、组装返回对象的逻辑独立出来,简化主方法流程:

private IActionResult BuildTileViewerResult(RockstarProductTile product, RockstarProductTileVariant variant, string edgeId)
{
    var commerceService = new CommerceService();
    var tileViewer = commerceService.GetRelatedEntries(variant, CommerceAssociationGroups.TileViewer).FirstOrDefault() as RockstarTileViewer;
    var images = tileViewer?.Rockstar_TileViewer_Images?.Items.Select(x => _urlUtilities.GetRelativeUrl(x.ContentLink)).ToList();
    
    var edge = GetProductByIdOrGuid<RockstarProductEdge>(edgeId);
    var label = edge?.Rockstar_RockstarProductEdge_EdgeName?.SupAndSubOnly() ?? product.DisplayName;
    
    return images != null 
        ? new JsonResult(new TileViewerDataObject { Label = label, Images = images }) 
        : new JsonResult(new TileViewerDataObject { Label = label });
}

重构后的主方法

现在主方法流程线性、逻辑清晰,嵌套层级大幅减少,认知复杂度会降到15以下:

[HttpGet]
public IActionResult GetTileViewer(string productId = "", string edgeId = "", string sizeId = "", double? thickness = null)
{
    var validationResult = ValidateProductId(productId);
    if (validationResult != null)
    {
        return validationResult;
    }

    var commerceService = new CommerceService();
    var isImperial = commerceService.IsImperialMeasure();
    
    var product = GetProductByIdOrGuid<RockstarProductTile>(productId);
    if (product == null)
    {
        return new JsonResult(new TileViewerDataObject());
    }

    try
    {
        var (length, width) = ParseSizeId(sizeId);
        
        var variants = product.Variants
            .Where(x => string.IsNullOrWhiteSpace(edgeId) || commerceService.GetRelatedEntries(x, CommerceAssociationGroups.Edge)
                .Any(y => y.ContentLink.ID.ToString() == edgeId || y.ContentGuid.ToString() == edgeId));

        variants = FilterVariantsByDimensions(variants, length, width, thickness, isImperial);
        
        var variant = variants.FirstOrDefault();
        if (variant != null)
        {
            return BuildTileViewerResult(product, variant, edgeId);
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error during get tile viewer: {Message}", ex.Message);
    }

    return new JsonResult(new TileViewerDataObject());
}

复杂度降低的核心原因

  • 消除了重复的分支逻辑(两次解析ID/Guid的代码)
  • 把嵌套的if分支拆到独立方法中,大幅减少主方法的嵌套层级
  • 每个小方法只负责单一职责,分支和判断被隔离,主方法流程更线性
  • 移除了冗余的变量声明和临时变量,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 14:46:07