以下if / elsif声明显然是一个庞然大物。其目的是基于用户是否填写了某些数据来更改某些文本的措辞。我觉得必须有一个更好的方法来做到这一点,而不需要占用30多行代码,但我只是不确定,因为我试图根据可用的数据非常显着地自定义文本。
if !birthdate.blank? && !location.blank? && !joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>"
elsif !birthdate.blank? && !location.blank? && !joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location} and is #{time_ago_in_words(birthdate)} old. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>"
elsif birthdate.blank? && !location.blank? && !joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>"
elsif birthdate.blank? && !location.blank? && !joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>"
elsif birthdate.blank? && location.blank? && !joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}. #{sex} passed away on #{death.strftime("%B %e, %Y")}.</p>"
elsif birthdate.blank? && location.blank? && !joined.blank? && death.blank?
"<p class='birthinfo'>#{name} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>"
elsif !birthdate.blank? && location.blank? && !joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>"
elsif !birthdate.blank? && location.blank? && !joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} and is #{time_ago_in_words(birthdate)} old. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>"
elsif !birthdate.blank? && !location.blank? && joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
elsif !birthdate.blank? && !location.blank? && joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location} and is #{time_ago_in_words(birthdate)} old. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
elsif !birthdate.blank? && location.blank? && joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
elsif !birthdate.blank? && location.blank? && joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} and is #{time_ago_in_words(birthdate)} old. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
elsif birthdate.blank? && !location.blank? && joined.blank? && !death.blank?
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
elsif birthdate.blank? && !location.blank? && joined.blank? && death.blank?
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
else
"<p class='birthinfo'>#{name} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
end
答案 0 :(得分:7)
我认为您希望使所有这些条件更具可读性,并消除逻辑检查和字符串创建中存在的重复。
我注意到的第一件事是你在整个地方重复这个:
<p class='birthinfo'>#{name} was born in
我会尝试将这些因素分解为带参数和返回格式化文本的函数,或者计算成表达式的类。
你根本没有利用筑巢。不要让每个条件都检查四个表达式的值,你应该尝试这样的事情:
if birthdate.blank?
# half of your expressions
else
# other half of your expressions
它可能不会使您的代码更具可读性,但值得尝试。我建议的最后一件事是你可能能够巧妙地重新排列你的文本,这样它很容易分段构造,并且仍然可以很好地读取最终用户。这是一个例子:
notice = "#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location}."
生成此代码的一个代码段可能是:
notice = "#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")}"
if !location.is_blank?
notice += " in #{location}"
end
notice += "."
这更容易理解你所拥有的类似代码,它将分别检查每个条件并根据布尔变量的值创建一个完全不同的字符串。您现在拥有的逻辑最糟糕的部分是,如果添加第五个变量,则必须在代码中添加更多特殊情况。将代码构建为独立的部分将更容易阅读和维护。
答案 1 :(得分:4)
我把它分成几部分。 DRY。仅生成一次给定的文本段。使用StringIO
保持字符串生成可分离。
sio = StringIO.new("")
know_birthdate, know_location, did_join, has_died = [ birthdate, location, joined, death ].map { |s| !s.blank? }
print_death = lambda do
sio.print ". #{sex} passed away on #{death.strftime("%B %e, %Y")}"
end
show_birth = know_birthdate or know_location
sio.print "<p class='birthinfo'>#{name} "
if show_birth
sio.print "was born"
sio.print " on #{birthdate.strftime("%A, %B %e, %Y")}" if know_birthdate
sio.print " in #{location}" if know_location
if has_died
print_death[]
sio.print " at the age of #{calculate_age(birthdate, death)}" if know_birthdate
elsif know_birthdate
sio.print " and is #{time_ago_in_words(birthdate)} old"
end
sio.print ". #{sex} "
end
sio.print "#{(has_died ? "was" : did_join ? "has been" : "is")} a member of #{link_to user.login, profile_path(user.permalink)}'s family"
sio.print " for #{distance_of_time_in_words(joined,death)}" if did_join and has_died
print_death[] if has_died and not show_birth
sio.print ".</p>"
sio.to_s
这使得逻辑更容易理解,并且更容易进行更改。
答案 2 :(得分:2)
您可以将字符串放在数组中,然后根据每个变量是否为空来创建数组索引:
strings = [
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location} and is #{time_ago_in_words(birthdate)} old. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} in #{location} and is #{time_ago_in_words(birthdate)} old. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} and is #{time_ago_in_words(birthdate)} old. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")}. #{sex} passed away on #{death.strftime("%B %e, %Y")} at the age of #{calculate_age(birthdate, death)}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was born on #{birthdate.strftime("%A, %B %e, %Y")} and is #{time_ago_in_words(birthdate)} old. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}.</p>",
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>",
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} passed away on #{death.strftime("%B %e, %Y")}. #{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was born in #{location}. #{sex} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>",
"<p class='birthinfo'>#{name} was a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{distance_of_time_in_words(joined,death)}. #{sex} passed away on #{death.strftime("%B %e, %Y")}.</p>",
"<p class='birthinfo'>#{name} has been a member of #{link_to user.login, profile_path(user.permalink)}'s family for #{time_ago_in_words(joined)}.</p>",
"", # This case was missing from your code. (Where all are blank except 'death'.)
"<p class='birthinfo'>#{name} is a member of #{link_to user.login, profile_path(user.permalink)}'s family.</p>"
]
index = 0
index += 1 unless death.blank?
index += 2 unless joined.blank?
index += 4 unless location.blank?
index += 8 unless birthdate.blank?
return strings[index]
答案 3 :(得分:1)
这是一个剪辑,展示了我将如何做到这一点:
ret = []
ret << "<p class='birthinfo'>#{name}"
ret << "was born on #{birthdate.strftime("%A, %B %e, %Y")}" unless birthdate.blank?
ret << "in #{location}." unless location.blank?
ret << sex
ret << "passed away on #{death.strftime("%B %e, %Y")}" unless death.blank?
ret << "at the age of #{calculate_age(birthdate, death)}"
ret << "#{sex} was a member of #{link_to user.login, profile_path(user.permalink)}'s family"
ret << 'for #{distance_of_time_in_words(joined,death)}" unless joined.blank? || death.blank?
ret << '.</p>'
ret.join(' ')
答案 4 :(得分:0)
您应该能够使用deMorgan's theorem重写查询,以便更有效地进行评估 您还可以将常见的子表达式分解为外部if语句 但是,当您这样做时,您可能会牺牲清晰的意图 如今,写一个清晰的,如果长的if语句而不是一个简短的难以理解的语句可能是更好的形式。
答案 5 :(得分:0)
如果对它们有一个简单的描述性术语,我很想编写描述每种状态的便捷方法。它不会导致更少的代码,但它会导致更可读的代码。这段代码几乎不可能阅读。
但是,看看它,我不确定你能想出什么样的描述性便利方法名称。你可能只需处理你想要做的事情的丑陋。答案 6 :(得分:0)
我能想到的一件事是,不是执行每个查询,而是执行所有查询并分配布尔变量的结果,然后测试布尔值。这并没有减少LOC,但确实减少了线路长度。忘掉我之前所说的关于switch语句的内容,至少没用。您可能尝试做的是将每个条件分解为几种方法。在给定的if语句中检查的第一件事仍然存在,但是这将为下一个条件调用两种方法之一,依此类推。这实际上会扩展LOC(我感觉不那么重要),但可读性会增加。它不是最佳解决方案,但它会起作用。