if 场景的 C++ 代码重构
C++ code refactoring for if scenario
我正在寻求针对 if 条件重构 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被定义为一个struct元素
另一个具有数组 if 条件的示例:
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]等等在...
对于所有此类 if 条件场景,我将减少 100 条 if 语句。我们如何重构这样的代码?
首先,找到代码中的重复项。如您所知 - 以下方案已重复多次:
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 中进行了一些封装:
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;
坦率地说,此时我会考虑使用预处理器 - 我的意思是缩短所有这些数组更新 - 这是因为在左边你有数组 - 在右边你有许多名称相似的字段("indexed"名字...?)
但是使用预处理器是一种糟糕的风格 - 让我们尝试使用纯 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;
等等...
你可以把它放在一些函数中,首先:
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 次”,您可能应该考虑进行更积极的重构。
并为该函数起一个更好的名字。
我正在寻求针对 if 条件重构 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被定义为一个struct元素
另一个具有数组 if 条件的示例:
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]等等在...
对于所有此类 if 条件场景,我将减少 100 条 if 语句。我们如何重构这样的代码?
首先,找到代码中的重复项。如您所知 - 以下方案已重复多次:
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 中进行了一些封装:
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;
坦率地说,此时我会考虑使用预处理器 - 我的意思是缩短所有这些数组更新 - 这是因为在左边你有数组 - 在右边你有许多名称相似的字段("indexed"名字...?)
但是使用预处理器是一种糟糕的风格 - 让我们尝试使用纯 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;
等等...
你可以把它放在一些函数中,首先:
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 次”,您可能应该考虑进行更积极的重构。
并为该函数起一个更好的名字。