重构圈复杂度



我有这段具有高圈复杂度的代码:

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

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

我已经阅读了这篇博客文章 JavaScript开发人员的圈复杂性重构技巧 并提出了这样的东西,但对我来说感觉不对:

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

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

也就是说,当您编写:

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]

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

最新更新