建议重构以下表格的if语句?

问题描述 投票:1回答:2

我试图让它尽可能通用。让我们假设在if语句中,我正在检查某个布尔表达式A是否为真。假设有一个特定的情况,A是真的,A.a和A.b,它们是相互排斥的。对于另一个布尔表达式B也是如此。然后,请考虑以下代码:

if (A) {
  if (A.a) {
    somethingSpecificToAa();
    foo();
  }
} else if (B) {
  if (B.a) {
    somethingSpecificToBa();
    foo();
  }
} else {
    foo();
}

在我的实际代码中,foo()不是单个函数,而是多行代码。多次重复它们对我来说似乎很臭,所以我假设有些重构是有道理的。

由于foo()在以下情况下执行:

  • A.a是真的
  • B.a是真的
  • A和B都不是真的

我想到了以下几点:

if (A.a) {
  somethingSpecificToAa();
} else if (B.a) {
  somethingSpecificToBa();
}

if (A.a || B.a || !(A || B)) {
  foo();
}

它应该具有相同的行为。这是最好的方式吗?请注意,第二个例子的第二个if语句中的条件在现实中最终变得非常长,这就是为什么我的代码看起来仍然像第一个例子(我讨厌在几行中分解单个if。)我也想过制作一个lambda,返回一个等于boolA.a || B.a || !(A || B),然后将lambda插入到第二个if语句中。或者,我可以保留第一个例子的结构,但用一个(foo())lambda替换每个void的许多行,虽然我不确定这能解决气味。

在这一点上我是否过度工程,想着lambdas?哪种方法最好保持干净的代码?

编辑:似乎我太过通用了。我正在处理STL容器,而不是我自己的类,一个更“准确”的例子是:

int shirtACleanliness = calculateCleanliness(shirtA);
if (itemsToWash.contains(shirtA)) { //itemsToWash is a std::set
  if (shirtA.cleanliness > shirtACleanliness) {
    itemsToWash.erase(shirtA);
    shirtA.cleanliness = shirtACleanliness;
    itemsToWash.insert(shirtA); //the set is ordered on cleanliness, so this re-inserts in the correct position
    doSomeOtherStuff(shirtA);
  }
} else if (itemsToDry.contains(shirtA)) { //itemsToDry is a std::vector
  if (shirtA.cleanliness > shirtACleanliness) {
    itemsToDry.erase(shirtA);
    shirtA.cleanliness = shirtACleanliness;
    itemsToWash.insert(shirtA);
    doSomeOtherStuff(shirtA);
  }
} else {
  shirtA.cleanliness = shirtACleanliness;
  itemsToWash.insert(shirtA);
  doSomeOtherStuff(shirtA);
}
//am aware aware contains() is not a method for either type
//and std::vector does not have erase() by value, this is just conceptual
c++ if-statement refactoring theory
2个回答
0
投票

根据您最近的评论,这里有一些伪代码可能与您的用例相匹配。

Element* element=nullptr;

if(vectorA.contains(X)){
   element = vectorA.get(X);
}else if(setB.contains(X)){
   element = setB.get(X);
}

if(element != nullptr && element->a){
   something(element);
}

if(element == nullptr || element->a){
    foo();
}

0
投票

由于那里有一些常见的代码,为什么不把它分解成函数呢?你可以有类似的东西

template<typename T, typename F>
bool doSomething(T const& t, F f)
{
    if (t && t.a)
    {
        f();
        foo();
    }

    return static_cast<bool>(t);
}

并使用它

if (!doSomething(A, &somethingSpecificToAa) && !doSomething(B, &somethingSpecificToBa))
{
    foo();
}
© www.soinside.com 2019 - 2024. All rights reserved.