重构此方法以将其认知复杂度从 16 降低到允许的 15。如何重构和降低复杂度?

Posted

技术标签:

【中文标题】重构此方法以将其认知复杂度从 16 降低到允许的 15。如何重构和降低复杂度?【英文标题】:Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed. How to refactor and reduce the complexity? 【发布时间】:2021-10-31 17:02:57 【问题描述】:

如何降低下面这段代码的复杂性? 我在 SonarQube 中收到此错误:

重构此方法以将其认知复杂度从 16 降低到 允许 15 个。

(function () 
  window.dm = window.dm ||  AjaxData: [] ;
  window.dm.AjaxEvent = function (et, d, ssid, ad) 
    dm.AjaxData.push(
      et, d, ssid, ad,
    );
    window.DotMetricsObj && DotMetricsObj.onAjaxDataUpdate();
  ;
  const d = document;
  const h = d.getElementsByTagName('head')[0];
  const s = d.createElement('script');
  let t = 'inews';
  s.type = 'text/javascript';
  s.async = true;

  if (window.PageContext.categories) 
    for (let category of window.PageContext.categories) 
      if (Utils.categoryMap[category.slug]) 
        t = Utils.categoryMap[category.slug];
        break;
      
    
  

  if (window.PageContext.post && window.PageContext.post.breadcrumbs) 
    for (let category of window.PageContext.post.breadcrumbs.reverse()) 
      if (Utils.categoryMap[category.slug]) 
        t = Utils.categoryMap[category.slug];
        break;
      
    
  

());

export default () =>  ;

【问题讨论】:

【参考方案1】:

例如,您可以提取复杂的 if 块以分离方法。

我的意思是这些if 块:

提取到方法1(例如handleCategories):

  if (window.PageContext.categories) 
    for (let category of window.PageContext.categories) 
      if (Utils.categoryMap[category.slug]) 
        t = Utils.categoryMap[category.slug];
        break;
      
    
  

提取到方法2(例如handleBreadcrumbs):

  if (window.PageContext.post && window.PageContext.post.breadcrumbs) 
    for (let category of window.PageContext.post.breadcrumbs.reverse()) 
      if (Utils.categoryMap[category.slug]) 
        t = Utils.categoryMap[category.slug];
        break;
      
    
  

这将从原始方法移动大约 3 个复杂度级别 (if + for + if) 到每个提取的方法。

【讨论】:

【参考方案2】:

SonarQube 应该会告诉您每个复杂点的来源。您将看到那些内部 if 语句中累积的最复杂性。因此,您可以采取任何措施来减少它们的复杂性,这将大有帮助。

倒转状态和提前回归是我最喜欢的策略。以下是它在这种情况下的帮助:

(function () 
  window.dm = window.dm ||  AjaxData: [] ;
  window.dm.AjaxEvent = function (et, d, ssid, ad) 
    dm.AjaxData.push(
      et, d, ssid, ad,
    );
    window.DotMetricsObj && DotMetricsObj.onAjaxDataUpdate();
  ;
  const d = document;
  const h = d.getElementsByTagName('head')[0];
  const s = d.createElement('script');
  let t = 'inews';
  s.type = 'text/javascript';
  s.async = true;

  if (!window.PageContext.categories) 
    for (let category of window.PageContext.categories) 
      if (Utils.categoryMap[category.slug]) 
        t = Utils.categoryMap[category.slug];
        break;
      
    
  

  if (!window.PageContext.post || !window.PageContext.post.breadcrumbs) 
    return;
  
  for (let category of window.PageContext.post.breadcrumbs.reverse()) 
    if (Utils.categoryMap[category.slug]) 
      t = Utils.categoryMap[category.slug];
      break;
    
  

());

【讨论】:

以上是关于重构此方法以将其认知复杂度从 16 降低到允许的 15。如何重构和降低复杂度?的主要内容,如果未能解决你的问题,请参考以下文章

重构此函数以降低其在 if else 条件下的认知复杂性

Sonar:Cognitive Complexity认知复杂度

代码重构规范

重构 ViewController 代码以将返回 UIImage 的方法移动到相关子类中

爱数Data+AI定位后最新动作,正式开源认知智能开发框架KWeaver

如何重置 kafka 以将其集成到 JUnit 测试过程中?