【发布时间】:2019-04-09 14:21:26
【问题描述】:
我正在尝试使其尽可能通用。假设在 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 分成几行。)我也有考虑过制作一个返回 bool 的 lambda,它等效于 A.a || B.a || !(A || B),并将 lambda 插入到第二个 if 语句中。或者,我可以保留第一个示例的结构,但将每个 foo() 的许多行替换为具有相同作用的 (void) lambda,尽管我不确定这是否能解决异味。
此时我是否过度设计,考虑 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
【问题讨论】:
-
如果例如
A和B是指针(这意味着你确实有A->a和B->a)然后你总是必须首先检查A和B。 -
请记住,如果出于任何原因,您必须在分支中使用略微不同的
foo(),那么您将不得不创建一个额外的foo2()。我不会更改if的格式,而是将foo()分解成更小的、可管理的函数/类,这样每个if子分支看起来就足够小了。 -
@Someprogrammerdude 它们不是指针,只是我正在尝试做的事情的抽象表示。但是,是的,即使在我的实际代码中,我也应该检查
A && A.a和B && B.a,而不仅仅是A.a和B.a。 -
@Tetix
foo()根据我上面的代码,无论何时调用它都是一样的;我已将所有特定于分支的内容放在somethingSpecificToAa()和somethingSpecificToBa()中。除非我误解了你的意思? -
@ampharos 我只是提前考虑,以防
foo()在其中一种场景中变得不同,而somethingspecificA/B无法合并。然后需要一个新的foo2()等等。这就是为什么我建议尽可能将foo()分解为更小的函数/类。
标签: c++ if-statement refactoring theory