针对if场景的C ++代码重构

时间:2015-09-22 18:34:21

标签: c++ arrays if-statement refactoring

我希望重构c ++代码,以确定是否会减少代码行数以及最小复杂度的条件。

以下是示例:

if (xyz->a != cmd->aa)
{
   xyz->a = cmd->aa;
   obj->isFound = true;  //common code for all ifs
}


if (xyz->b != cmd->bb)
{
    xyz->b = cmd->bb;
    obj->isFound = true; 
}

依此类推。这里a,b,aa,bb被定义为结构元素。

另一个带有数组条件的示例:

 if (abc->r16[0] != cmd->r0m)
    {
        abc>r16[0] = cmd->r0m;
        obj->isFound = true; //some common code for all ifs
    }


if (abc->r16[1] != cmd->r1m)
        {
            abc>r16[1] = cmd->r1m;
            obj->isFound = true; //some common code for all ifs
        }

对于r16 [0]到r16 [15]等等。这里r16 [15]在struct中定义。

最后一种情况适用于具有多维数组的if条件:

     if (pqr->c_0_15_r_0_15[0][0] != cmd->obj0000)
           {
              pqr->c_0_15_r_0_15[0][0] = cmd->obj0000
              obj->isFound = true; //some common code for all ifs
           }

if (pqr->c_0_15_r_0_15[1][0] != cmd->obj0100)
           {
              pqr->c_0_15_r_0_15[1][0] = cmd->obj0100
              obj->isFound = true; //some common code for all ifs
           }

if (pqr->c_0_15_r_0_15[2][0] != cmd->obj0000)
           {
              pqr->c_0_15_r_0_15[2][0] = cmd->obj0200
              obj->isFound = true; //some common code for all ifs
           }

这里c_0_15_r_0_15 [2] [0]将经过[0] [0]至[15] [0],然后是[0] [1]至[15] [1],依此类推......

对于所有这样的条件情形,我会有100个if语句应该减少。我们如何重构这些代码?

2 个答案:

答案 0 :(得分:1)

首先,在代码中找到重复项。如您所知 - 以下方案多次重复:

if (a != b)
{
    a = b;
    found = true;
}

所以 - 将它封装在一个函数中(模板,如果有多种类型:

template <typename Dst, typename Src>
inline void updateIfNeeded(Dst& dst, const Src& src, bool& wasNeeded)
{
    if (dst != src)
    {
        dst = src;
        wasNeeded = true;
    }
}

请参阅 - 它有何帮助:

updateIfNeeded(abc->r16[0], cmd->r0m, obj->isFound);
updateIfNeeded(abc->r16[1], cmd->r1m, obj->isFound);
// ...
updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000, obj->isFound);
updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100, obj->isFound);
// ...

到目前为止 - 减少量非常大 - 并且它在此代码中的可读性更高。

我看到更多 - obj->isFound重复多次 - 也许 - 这次在课堂上进行了一些封装:

class Updater
{
public:
    bool anyUpdateWasNeeded = false;

    template <typename Dst, typename Src>
    void  updateIfNeeded(Dst& dst, const Src& src)
    {
       if (dst != src)
       {
           dst = src;
           anyUpdateWasNeeded = true;
       }
   }
};

你知道 - 不需要多次通过obj->isFound

Updater upd;

upd.updateIfNeeded(abc->r16[0], cmd->r0m);
upd.updateIfNeeded(abc->r16[1], cmd->r1m);
// ...
upd.updateIfNeeded(pqr->c_0_15_r_0_15[0][0], cmd->obj0000);
upd.updateIfNeeded(pqr->c_0_15_r_0_15[1][0], cmd->obj0100);
// ...
obj->isFound = upd.anyUpdateWasNeeded;

坦率地说,在这一点上我会考虑使用预处理器 - 我的意思是缩短所有这些数组更新 - 这是因为在左边你有数组 - 在右边你有很多相似名称的字段(&#34;索引&#34 ;名字......?)

但是使用预处理器是不好的样式 - 让我们尝试用纯C ++更新数组:

class Updater
{
public:
    bool anyUpdateWasNeeded = false;

    template <typename Dst, typename Src>
    void  updateIfNeeded(Dst& dst, const Src& src);

    template <typename Dst, typename Src1, typename ...Src>
    void  updateArrayIfNeeded(Dst* dst, const Src1& src1, const Src& ...src)
    {
       updateIfNeeded(*dst, src1);
       updateArrayIfNeeded(dst + 1, src...);
   }
    template <typename Dst>
    void  updateArrayIfNeeded(Dst* dst) 
    {
        // nothing left
    }
};

所以 - 这就是剩下的:

upd.updateArrayIfNeeded(abc->r16, cmd->r0m, cmd->r1m, ....);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[0], cmd->obj0000, cmd->obj0001, ...);
upd.updateArrayIfNeeded(pqr->c_0_15_r_0_15[1], cmd->obj0100, ...);
// ...
obj->isFound = upd.anyUpdateWasNeeded;

等等......

答案 1 :(得分:1)

你可以把它放在某个功能中,作为开始:

template<typename Lhs, typename Rhs>
void flagSetIfNEq(Lhs & lhs, Rhs const & rhs, bool & flag) {
  if (lhs != rhs) {
    lhs = rhs;
    flag = true;
  }
}
// call it like
flagSetIfNEq(xyz->a, uvw->aa, obj->found)!

我假设代码中的found类型为bool

虽然如果你的代码中有“100次”,你可能应该考虑更积极的重构。

并为该功能提供更好的名称。