加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – DRY if语句

发布时间:2020-12-16 10:31:28 所属栏目:百科 来源:网络整理
导读:我有一个C程序,在许多不同的.cpp文件中,我做这样的事情: if (!thing1.empty() !thing2.empty()){ if (thing1.property thing2.property) return func1(); else if (thing2.property thing1.property) return func2(); else return func3();}else if (!thing
我有一个C程序,在许多不同的.cpp文件中,我做这样的事情:

if (!thing1.empty() && !thing2.empty())
{
    if (thing1.property < thing2.property)
        return func1();
    else if (thing2.property < thing1.property)
        return func2();
    else
        return func3();
}
else if (!thing1.empty())
{
    return func1();
}
else if (!thing2.empty())
{
    return func2();
}
else
{
   return func4();
}

如果thing1大于thing2,我试图以某种方式执行func,如果情况相反,我会尝试向后执行func,但如果不存在那么我只会为那一半执行func.如果两者都不存在,我会做一些完全不同的事情.每次使用此模式时,属性,函数和返回类型都不同.对于我想做的事情有没有比这个丑陋的嵌套if语句更好的设计?

编辑:实现我的示例代码过于简单化.这里有一些我真正的代码,希望能更好地解释这个问题(虽然它更麻烦):

if (!diamondsOnly.empty() && !clubsOnly.empty())
{
    if (diamondsOnly.size() < clubsOnly.size())
    {
        if (passHighCards(player.hand,getHighCards(Card::DIAMONDS),result))
            return result;
        if (passHighCards(player.hand,getHighCards(Card::CLUBS),result))
            return result;
    }
    else if (clubsOnly.size() < diamondsOnly.size())
    {
        if (passHighCards(player.hand,result))
            return result;
    }
    else
    {
        if (diamondsOnly.back().value > clubsOnly.back().value)
        {
            if (passHighCards(player.hand,result))
                return result;
            if (passHighCards(player.hand,result))
                return result;
        }
        else
        {
            if (passHighCards(player.hand,result))
                return result;
        }
    }
}
else if (!diamondsOnly.empty())
{
    if (passHighCards(player.hand,result))
        return result;
}
else if (!clubsOnly.empty())
{
    if (passHighCards(player.hand,result))
        return result;
}

解决方法

决定然后做

看一下真正的代码,我注意到的第一件事就是有很多几乎相同的调用只有一个常数变化.我会使用在复杂逻辑中设置的参数在一个地方进行调用.

// Decide what to do.
std::vector<Card::Suit> passOrder;
if (!diamondsOnly.empty() && !clubsOnly.empty()) {
    // .. complicated logic that adds suits to passOrder ..
}

// Do it.
for (auto suit : passOrder) {  // This is C++11 style -- alter as needed
    if (passHighCards(player.hand,getHighCards(suit),result))
        return result;
}

(如果它总是只有一个或两个,使用向量可能是过度的,但我假设真正的代码可能会处理所有的诉讼.)

这使得阅读更容易.程序员可以看到,首先你决定通过卡的顺序,然后你实际上是通过它们.两个单独的步骤将更加清晰.只有一个调用passCards的地方使得它更容易产生愚蠢的拼写错误,而不是让它的副本分散在整个决策逻辑中.它也会使调试变得更容易,因为您可以在非常特定的情况下设置断点,或者您可以在循环开始时设置断点并检查passOrder.

简化逻辑

接下来我们想简化决策逻辑.

选项:

> Sentinels:复杂的部分原因在于,在某些情况下,您需要取消引用其中一个容器中的最后一张卡,如果容器为空,则无法取消.有时候值得考虑在容器中添加一个标记,这样你就不需要测试空壳了 – 你可以保证它永远不会空着.这可能是可行的,也可能是不可行的.您需要使处理容器的所有其他代码了解哨兵.
>只是例外:你可以通过选择默认订单来消除一些条款,例如,钻石然后是球杆,然后只测试你需要球杆然后钻石的情况.
>使用Temporaries进行表达:创建名称极佳的临时工具,简化您必须进行的比较,并根据这些临时表达比??较.请注意,如果将空/非空案例分解为临时案例,则可以通过选择适当的SENTINEL_VALUE(如0或-1)来消除某些情况.

把它们放在一起:

// For readability.
const bool fewerClubs = clubsOnly.size() < diamondsOnly.size();
const bool sameNumber = clubsOnly.size() == diamondsOnly.size();
const int lastDiamondValue =  diamondsOnly.empty() ? -1 : diamondsOnly.back().value;
const int lastClubValue    =  clubsOnly   .empty() ? -1 : clubsOnly   .back().value;

// Decide what order to select cards for passing.
std::vector<Card::Suit> passOrder;
passOrder.push_back(Cards::DIAMONDS);  // default order
passOrder.push_back(Cards::CLUBS);

// Do we need to change the order?
if (fewerClubs || (sameNumber && lastClubValue > lastDiamondValue)) {
    // Yep,so start with the clubs instead.
    passOrder[0] = Cards::CLUBS;
    passOrder[1] = Cards::DIAMONDS;
}

// Do it.
for (auto suit : passOrder) {  // This is C++11 style -- alter as needed
    if (passHighCards(player.hand,result))
        return result;
}

这假设getHighCards处理可能为空的容器作为输入.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读