假设我有这样的代码:
def set_reminder(cond_one: false, cond_two: false)
if cond_two
if cond_one
outcome_a
else
outcome_b
end
else
if cond_one
outcome_c
else
outcome_d
end
end
end
如何更优雅地编写这样一个函数,它有4个可能的结果(cond_one
和cond_two
值的每个组合对应一个结果)?
我对这个版本不太满意,它在两个分支中都使用了一个if/else语句,在实际代码中,outcome
已经是复杂的表达式了,所以编写类似return outcome_a if cond_one && cond_two
的东西(针对所有4个结果)会很笨拙。
4条答案
按热度按时间lc8prwob1#
Ruby有一个非常强大的case expression,可以用于这类事情。
正如评论中所指出的,考虑让你的论证表达的不仅仅是“布尔对”,参见Boolean blindness以获得关于这个问题的讨论。
ldfqzlk82#
你可以像下面这样,把嵌套的if扁平化成一系列的保护语句。
这样做更简洁,并允许进一步重构。
Sandi梅斯等人关于重构的书99 Bottles of OOP我怎么推荐都不为过。有一个Ruby版本。整本书带你经历了这种重构。从多个if到提取的类。
c0vxltue3#
可以在构造函数中将其设置为散列:
那么你的方法就是
避免通过复合对象进行索引的一个替代方案是创建散列的散列:
我做了以下基准测试来比较各种建议的方法:
在M1 MacBook Pro上使用Ruby 3.2.0生成的结果如下:
使用
--yjit
:在我看来,user3574603的guard语句方法确实是赢家,而hash的hash方法则紧随其后,两者都主导了hash查找和case语句方法。
rqdpfwrv4#
我想说的是,你不能在现有的基础上再改进了。你的方法有以下几个特点:
cond_two
和cond_one
每个仅被检查一次;以及方法中的代码行数可以减少,但如果这会对可读性或测试的简易性产生负面影响,我建议不要这样做。
下面是一些或多或少等价的方法,我认为在这些方法中进行选择纯粹是一种风格上的选择。
case
语句 *