【问题标题】:Refactor cyclomatic complexity重构圈复杂度
【发布时间】:2017-07-24 21:15:53
【问题描述】:

我有一段圈复杂度很高的代码:

def status_icon_name
  return 'icons/new.png' if mailgun_id.blank?
  return 'icons/hourglass.png' if mailgun_id.present? && log.blank?

  return 'icons/accept.png' if log['event'] == 'delivered'
  return 'icons/exclamation.png' if log['severity'].present? && log['severity'] == 'permanent'
  return 'icons/time.png' if log['event'] == 'accepted'
  return 'icons/error.png' if log['severity'] == 'temporary' 
  return 'icons/question.gif'
end

如何重构它以消除圈复杂度?

我已经阅读了这篇博文 Cyclomatic complexity refactoring tips for javascript developers 并想出了类似的东西,但我觉得它不合适:

def status_icon_name
  lookup = [
    {
      condition: mailgun_id.blank?,
      icon_name: 'icons/new.png'
    },
    {
      condition: mailgun_id.present? && log.blank?,
      icon_name: 'icons/hourglass.png'
    },
    {
      condition: log.present? && log['event'] == 'delivered',
      icon_name: 'icons/accept.png'
    },
    {
      condition: log.present? && log['severity'].present? && log['severity'] == 'permanent',
      icon_name: 'icons/exclamation.png'
    },
    {
      condition: log.present? && log['event'] == 'accepted',
      icon_name: 'icons/time.png'
    },
    {
      condition: log.present? && log['severity'] == 'temporary',
      icon_name: 'icons/error.png'
    },
    {
      condition: true,
      icon_name: 'icons/question.gif'
    }
  ]

  lookup.find { |x| x[:condition] }[:icon_name]
end

【问题讨论】:

    标签: ruby refactoring


    【解决方案1】:

    在运行时构建这样的查找表会适得其反,您正在生成这个巨大的结构并评估所有这些条件,而不管它们的有效性。

    也就是说,当你写的时候:

    lookup = [
      {
        condition: mailgun_id.blank?,
        icon_name: 'icons/new.png'
      }
    ]
    

    这会立即被评估并简化为:

    lookup = [
      {
        condition: true,
        icon_name: 'icons/new.png'
      }
    ]
    

    如果您想要延迟执行,您需要使用Proc

    LOOKUP = [
      {
        condition: Proc.new { mailgun_id.blank? },
        icon_name: 'icons/new.png'
      }
    ]
    

    然后你会像这样执行:

    LOOKUP.find { |x| instance_eval(&x[:condition]) }[:icon_name]
    

    这样,您可以将查找表作为常量存储在类的顶部,并且只需要定义一次,而不是每次方法调用一次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多