处理许多 if 条件的更好方法?
Better way to handle many if conditions?
我们有许多不同类型的提要。一个提要有很多 feed_comments
。根据提要类型,我想 return 一个特定的字符串。
if feed.type == 1
if nested_comment
str = "test"
else if comment
str = "test1"
else
str = "test2"
end
else if feed.type == 2
if nested_comment
str = "test3"
else if comment
str = "test4"
else
str = "test5"
end
else if feed.type == 3
if nested_comment
str = "test6"
else if comment
str = "test7"
else
str = "test8"
end
else if feed.type == 4
if nested_comment
str = "test9"
else if comment
str = "test10"
else
str = "test11"
end
end
编写上面代码的更好方法是什么,这样如果我们有更多的条件,我以后就不必更改现有代码了?
要获得更易于管理和可读的代码,您可以尝试 case statements。除此之外,我看不出你还能如何压缩代码,因为正如有人指出的那样,每种可能性都有不同的结果。
case feed.type
when 1
case
when nested_comment then str = "test"
when comment then str = "test2"
else str = "test3"
end
when 2
case
when nested_comment then str = "test"
when comment then str = "test2"
else str = "test3"
end
# repeat for each feed number type
end
results = {
1 => {
nested_comment: 'test1',
comment: 'test2',
else: 'test3'
}
}
comment_type = nested_comment ? :nested_comment : comment ? :comment : :else
results[feed.type][comment_type]
此代码可以极大地受益于Replace Conditional with Polymorphism Refactoring。
一般来说,您从不在面向对象语言中根本不需要任何条件,因为面向对象语言具有运行时多态消息调度,这比任何条件都更强大.你可以总是用多态替换条件; Smalltalk 是这方面的存在证明,它甚至 没有 语言中的条件,它们是使用消息调度在库中实现的,有点像这样:
class TrueClass
def if_then_else(then_part, else_part)
then_part.()
end
end
class FalseClass
def if_then_else(then_part, else_part)
else_part.()
end
end
(2 < 3).if_then_else(-> { puts 'True' }, -> { puts 'False' })
# True
Ruby 有条件句,但你不需要它们。
那么,运行时多态消息分派到底做了什么?好吧,它基本上根据类型执行不同的代码。例如,如果您说
foo.bar
不同的 bar
方法将 运行 基于 foo
的类型。
在您的情况下,您用来决定执行哪个代码的值 字面意思 称为 type
,因此,您本质上是只是重新实现 Ruby 的一个基本功能:根据类型执行不同的代码 是 只是消息分发,Ruby 无论如何它自己完成。
因此,在您的情况下,您将有 4 个不同的 Feed
类 和 2 个不同的 Comment
类.
现在,就您而言,情况稍微复杂一些,因为结果不仅仅取决于提要类型,还取决于评论类型。 Ruby 没有多重调度,因此,我们要么需要为提要类型和评论类型的每种组合引入新的 类,要么在最终代码中使用一些条件。
所以,让我们开始慢慢改进您的代码。首先,我相信你的意思是 elsif
而不是 else if
在你的代码中:
if feed.type == 1
if nested_comment
str = "test"
elsif comment
str = "test1"
else
str = "test2"
end
elsif feed.type == 2
if nested_comment
str = "test3"
elsif comment
str = "test4"
else
str = "test5"
end
elsif feed.type == 3
if nested_comment
str = "test6"
elsif comment
str = "test7"
else
str = "test8"
end
elsif feed.type == 4
if nested_comment
str = "test9"
elsif comment
str = "test10"
else
str = "test11"
end
end
其次,我们可以利用Ruby中的条件是表达式,而不是语句(实际上,Ruby中的所有内容都是表达式,没有语句),因此评估值:
str = if feed.type == 1
if nested_comment
"test"
elsif comment
"test1"
else
"test2"
end
elsif feed.type == 2
if nested_comment
"test3"
elsif comment
"test4"
else
"test5"
end
elsif feed.type == 3
if nested_comment
"test6"
elsif comment
"test7"
else
"test8"
end
elsif feed.type == 4
if nested_comment
"test9"
elsif comment
"test10"
else
"test11"
end
end
现在,我们将 if
替换为 case
表达式:
str = case feed.type
when 1
case
when nested_comment
"test"
when comment
"test1"
else
"test2"
end
when 2
case
when nested_comment
"test3"
when comment
"test4"
else
"test5"
end
when 3
case
when nested_comment
"test6"
when comment
"test7"
else
"test8"
end
when 4
case
when nested_comment
"test9"
when comment
"test10"
else
"test11"
end
end
现在,让我们重新格式化一下,以便更容易地看到发生了什么:
str = case feed.type
when 1
case
when nested_comment then "test"
when comment then "test1"
else "test2"
end
when 2
case
when nested_comment then "test3"
when comment then "test4"
else "test5"
end
when 3
case
when nested_comment then "test6"
when comment then "test7"
else "test8"
end
when 4
case
when nested_comment then "test9"
when comment then "test10"
else "test11"
end
end
是时候进行重构了:
class Feed1
def magic_string
case
when nested_comment then "test"
when comment then "test1"
else "test2"
end
end
end
class Feed2
def magic_string
case
when nested_comment then "test3"
when comment then "test4"
else "test5"
end
end
end
class Feed3
def magic_string
case
when nested_comment then "test6"
when comment then "test7"
else "test8"
end
end
end
class Feed4
def magic_string
case
when nested_comment then "test9"
when comment then "test10"
else "test11"
end
end
end
str = feed.magic_string
我们可以通过引入一种封装评论检查的方法来进一步减少一些重复(或者,就像我说的,我们可以引入评论类)。
class Feed
def comment_string(nested_comment_string, comment_string, other_string)
case
when nested_comment then nested_comment_string
when comment then comment_string
else other_string
end
end
end
class Feed1 < Feed
def magic_string
comment_string("test", "test1", "test2")
end
end
class Feed2 < Feed
def magic_string
comment_string("test3", "test4", "test5")
end
end
class Feed3 < Feed
def magic_string
comment_string("test6", "test7", "test8")
end
end
class Feed4 < Feed
def magic_string
comment_string("test9", "test10", "test11")
end
end
str = feed.magic_string
我们有许多不同类型的提要。一个提要有很多 feed_comments
。根据提要类型,我想 return 一个特定的字符串。
if feed.type == 1
if nested_comment
str = "test"
else if comment
str = "test1"
else
str = "test2"
end
else if feed.type == 2
if nested_comment
str = "test3"
else if comment
str = "test4"
else
str = "test5"
end
else if feed.type == 3
if nested_comment
str = "test6"
else if comment
str = "test7"
else
str = "test8"
end
else if feed.type == 4
if nested_comment
str = "test9"
else if comment
str = "test10"
else
str = "test11"
end
end
编写上面代码的更好方法是什么,这样如果我们有更多的条件,我以后就不必更改现有代码了?
要获得更易于管理和可读的代码,您可以尝试 case statements。除此之外,我看不出你还能如何压缩代码,因为正如有人指出的那样,每种可能性都有不同的结果。
case feed.type
when 1
case
when nested_comment then str = "test"
when comment then str = "test2"
else str = "test3"
end
when 2
case
when nested_comment then str = "test"
when comment then str = "test2"
else str = "test3"
end
# repeat for each feed number type
end
results = {
1 => {
nested_comment: 'test1',
comment: 'test2',
else: 'test3'
}
}
comment_type = nested_comment ? :nested_comment : comment ? :comment : :else
results[feed.type][comment_type]
此代码可以极大地受益于Replace Conditional with Polymorphism Refactoring。
一般来说,您从不在面向对象语言中根本不需要任何条件,因为面向对象语言具有运行时多态消息调度,这比任何条件都更强大.你可以总是用多态替换条件; Smalltalk 是这方面的存在证明,它甚至 没有 语言中的条件,它们是使用消息调度在库中实现的,有点像这样:
class TrueClass
def if_then_else(then_part, else_part)
then_part.()
end
end
class FalseClass
def if_then_else(then_part, else_part)
else_part.()
end
end
(2 < 3).if_then_else(-> { puts 'True' }, -> { puts 'False' })
# True
Ruby 有条件句,但你不需要它们。
那么,运行时多态消息分派到底做了什么?好吧,它基本上根据类型执行不同的代码。例如,如果您说
foo.bar
不同的 bar
方法将 运行 基于 foo
的类型。
在您的情况下,您用来决定执行哪个代码的值 字面意思 称为 type
,因此,您本质上是只是重新实现 Ruby 的一个基本功能:根据类型执行不同的代码 是 只是消息分发,Ruby 无论如何它自己完成。
因此,在您的情况下,您将有 4 个不同的 Feed
类 和 2 个不同的 Comment
类.
现在,就您而言,情况稍微复杂一些,因为结果不仅仅取决于提要类型,还取决于评论类型。 Ruby 没有多重调度,因此,我们要么需要为提要类型和评论类型的每种组合引入新的 类,要么在最终代码中使用一些条件。
所以,让我们开始慢慢改进您的代码。首先,我相信你的意思是 elsif
而不是 else if
在你的代码中:
if feed.type == 1
if nested_comment
str = "test"
elsif comment
str = "test1"
else
str = "test2"
end
elsif feed.type == 2
if nested_comment
str = "test3"
elsif comment
str = "test4"
else
str = "test5"
end
elsif feed.type == 3
if nested_comment
str = "test6"
elsif comment
str = "test7"
else
str = "test8"
end
elsif feed.type == 4
if nested_comment
str = "test9"
elsif comment
str = "test10"
else
str = "test11"
end
end
其次,我们可以利用Ruby中的条件是表达式,而不是语句(实际上,Ruby中的所有内容都是表达式,没有语句),因此评估值:
str = if feed.type == 1
if nested_comment
"test"
elsif comment
"test1"
else
"test2"
end
elsif feed.type == 2
if nested_comment
"test3"
elsif comment
"test4"
else
"test5"
end
elsif feed.type == 3
if nested_comment
"test6"
elsif comment
"test7"
else
"test8"
end
elsif feed.type == 4
if nested_comment
"test9"
elsif comment
"test10"
else
"test11"
end
end
现在,我们将 if
替换为 case
表达式:
str = case feed.type
when 1
case
when nested_comment
"test"
when comment
"test1"
else
"test2"
end
when 2
case
when nested_comment
"test3"
when comment
"test4"
else
"test5"
end
when 3
case
when nested_comment
"test6"
when comment
"test7"
else
"test8"
end
when 4
case
when nested_comment
"test9"
when comment
"test10"
else
"test11"
end
end
现在,让我们重新格式化一下,以便更容易地看到发生了什么:
str = case feed.type
when 1
case
when nested_comment then "test"
when comment then "test1"
else "test2"
end
when 2
case
when nested_comment then "test3"
when comment then "test4"
else "test5"
end
when 3
case
when nested_comment then "test6"
when comment then "test7"
else "test8"
end
when 4
case
when nested_comment then "test9"
when comment then "test10"
else "test11"
end
end
是时候进行重构了:
class Feed1
def magic_string
case
when nested_comment then "test"
when comment then "test1"
else "test2"
end
end
end
class Feed2
def magic_string
case
when nested_comment then "test3"
when comment then "test4"
else "test5"
end
end
end
class Feed3
def magic_string
case
when nested_comment then "test6"
when comment then "test7"
else "test8"
end
end
end
class Feed4
def magic_string
case
when nested_comment then "test9"
when comment then "test10"
else "test11"
end
end
end
str = feed.magic_string
我们可以通过引入一种封装评论检查的方法来进一步减少一些重复(或者,就像我说的,我们可以引入评论类)。
class Feed
def comment_string(nested_comment_string, comment_string, other_string)
case
when nested_comment then nested_comment_string
when comment then comment_string
else other_string
end
end
end
class Feed1 < Feed
def magic_string
comment_string("test", "test1", "test2")
end
end
class Feed2 < Feed
def magic_string
comment_string("test3", "test4", "test5")
end
end
class Feed3 < Feed
def magic_string
comment_string("test6", "test7", "test8")
end
end
class Feed4 < Feed
def magic_string
comment_string("test9", "test10", "test11")
end
end
str = feed.magic_string