我的这段代码具有很高的圈复杂度:
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
答案 0 :(得分:5)
在运行时构建这样的查找表会产生反作用,您将生成这个庞大的结构并评估所有这些条件,无论其有效性如何。
也就是说,当你写:
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]
通过这种方式,您可以将查找表存储为类顶部的常量,只需要定义一次,而不是每次方法调用一次。