重构大条件语句

时间:2014-08-20 23:30:12

标签: refactoring conditional-statements

有没有更好的方法来编写像这样的条件逻辑?

if (dog == 'alive' && cat == 'alive')
    ...
elsif (dog != 'alive' && cat == 'alive')
    ...
elsif (dog == 'alive' && cat != 'alive')
    ...    
elsif (dog != 'alive' && cat != 'alive')
    ...    
end

如果我要添加另一种动物或另外一种动物,事情会变得无法控制。肯定有更好的办法!

编辑:我的实际代码与猫狗没有任何关系。我只是想尽可能保持一般。不确定这是否会影响答案,但是你走了。 (它的Rails。)

    if params[:search]
        @requests = Request.search(params[:search], @cookies_city, @cookies_category).order('created_at DESC')
    elsif cookies[:city_select]
        if @cookies_city != "ALL" && @cookies_category != "ALL"

            @requests = Request.all.where(:city => @cookies_city).where(:category => @cookies_category).order('created_at DESC')
        elsif @cookies_city != "ALL" && @cookies_category == "ALL"
            @requests = Request.all.where(:city => @cookies_city).order('created_at DESC')

        elsif @cookies_city == "ALL" && @cookies_category != "ALL"
            @requests = Request.all.where(:category => @cookies_category).order('created_at DESC')

        elsif @cookies_city == "ALL" && @cookies_category == "ALL"

            @requests = Request.all.order('created_at DESC')
        end
    elsif cookies[:category_select]
        if @cookies_city != "ALL" && @cookies_category != "ALL"
            @requests = Request.all.where(:city => @cookies_city).where(:category => @cookies_category).order('created_at DESC')

        elsif @cookies_city != "ALL" && @cookies_category == "ALL"
            @requests = Request.all.where(:city => @cookies_city).order('created_at DESC')

        elsif @cookies_city == "ALL" && @cookies_category != "ALL"
            @requests = Request.all.where(:category => @cookies_category).order('created_at DESC')

        else
            @requests = Request.all.order('created_at DESC')

        end
    end
end

4 个答案:

答案 0 :(得分:1)

如果您可以构建代码以便从每个分支返回,那么它可以更清晰。有时这可能需要提取方法。如果您的语言支持它们,那么三元运算符如果明智地使用,可以使事情变得更清楚

if (dog == 'alive')
  return cat == 'alive' ? 'bothLiving' : 'justDog';

return cat == 'alive' ? 'justCat' : 'bothDead';  

答案 1 :(得分:1)

您可以使用不同的位来表示动物的状态(活着或死亡)。然后它是一个简单的开关语句,如

switch (state) {
case 0: // None alive
...
break;
case 1: // 0th bit alive only(say dog)
...
break;
case 2: // 1st bit alive only (say cat)
....
break;
case 3: // 0th and 1st bit alive (dog and cat)
}

当你想要添加更多时,只需使用下一位并在switch语句中添加'case'。

答案 2 :(得分:1)

您的原始编码风格通常称为Decision Table (DT)

DT很好,因为很容易修改每个动作的条件。

当你手工编写代码时,它们看起来像你一样大而笨重。 (你为什么关心?)

一个反对意见可能是代码效率不高(对您的特定情况是否重要?),因为它会重复评估子条件。这可能是也可能不是真的;它是你的编译器决定的优化能力;一个好的编译器可以选择有用的子表达式并评估一小组。

对于性能,人们可能想要一个决策树。好消息是他们很快;坏消息是他们很难更新。如果您坚持使用决策树,最好将测试编写为可维护性的决策表,并让某些工具将条件转换为决策树。然后你最终得到了可维护的结果和快速的表现。

答案 3 :(得分:0)

首先你应该从一个普通的类中派生所有这些 public class Animal {public bool Alive{get; set;}}

将它们全部放入“列表”

然后通过2 for for循环(伪代码)运行它们

for(int x = 0;x < animals.Count;x++)
{
   for(int y = 0;y < animals.Count;y++)
   {
     if(animals[x].Alive == animals[y].Alive)....
   }
}

抱歉,但是因为你正在寻找一种没有结束的手段,所以可以用这个答案去做

我不确定你如何收集和使用比较每个动物活着状态的数据,但这应该让你开始

如果您不想比较相同的动物,只需测试x和y是否相同