我有这段具有高圈复杂度的代码:
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]
这样,您可以将查找表存储为类顶部的常量,并且只需要定义一次,而不是每次方法调用一次。