[英]Better way to structure/new keyword
前段时间我遇到了以下我很少见过的构造,虽然我比较频繁地使用它。 我通常在检查整个条件列表时使用它,并且它可以防止大量缩进。 基本上它使用for循环来提供一种结构化的goto。 我的问题首先是否有更好的方法来构建它,其次是人们是否喜欢它,第三是java / c ++中的新关键字(例如unit {})是否只会导致中断退出到单元的末尾有用而且更清晰。
ps我意识到它远离无限循环,但我认为我对此的偏执意味着它从未发生过。
编辑:我已经为其他条件添加了一些设置代码,以尝试用链接来解决问题
boolean valid = false;
// this loop never loops
for (;;)
{
if (!condition1)
break;
condition2.setup();
if (!condition2)
break;
condition3.setup();
if (!condition3)
break;
valid = true;
break;
}
if (valid) dosomething();
编辑:
我刚刚发现,实际上有一种方法可以在java中构造它而不会滥用循环等,并且想知道这是否会同样不受欢迎,尽管我猜我错过了这个。
重构的代码看起来像这样。
boolean valid = false;
breakout:
{
if (!condition1)
break breakout;
condition2.setup();
if (!condition2)
break breakout;
condition3.setup();
if (!condition3)
break breakout;
valid = true;
}
if (valid) dosomething();
现在,这消除了导致很多抱怨的for循环的误用,并且实际上是一个解决方案,我认为是非常整洁的,并且是我原本想要找到的。 我猜这个结构可能并不为人所知,因为没有人提到它,人们强烈反对这个?
这个循环是反直觉的,在代码审查中会受到质疑:“如果你总是在第一次迭代中破解,为什么还需要一个循环呢?”
为什么不用这个?
boolean valid = true;
if (!condition1)
valid = false;
else if (!condition2)
valid = false;
else if (!condition3)
valid = false;
if (valid) dosomething();
您可能已经听说过现代编程语言所具有的这些东西,称为函数 ;)不再使用goto
一个关键原因是我们现在可以将代码分解为单独的函数,而是调用它们。
为您解决问题的一种方法是将代码放在一个单独的函数,而是和返回 ,而不是从伪开断:
void safedosomething() {
if (!condition1)
return;
condition2.setup();
if (!condition2)
return;
condition3.setup();
if (!condition3)
return;
dosomething();
}
或编写辅助函数(如bool checkcondition1() { condition1.setup(); return condition1; }
)设置然后测试条件,并使用布尔标志:
bool valid = true;
if (!checkcondition1())
valid = false;
if (!checkcondition2())
valid = false;
if (!checkcondition3())
valid = false;
if (!checkcondition4())
valid = false;
if (valid) dosomething();
或者更简洁一点:
bool valid = true;
valid &&= checkcondition1();
valid &&= checkcondition2();
valid &&= checkcondition3();
valid &&= checkcondition4();
if (valid) dosomething();
要不就
if (checkcondition1()
&& checkcondition2()
&& checkcondition3()
&& checkcondition4())
dosomething();
有很多方法可以表达这一点,没有违反直觉的循环 - 不要循环。
这种结构的原因是因为goto
是编程中的一个脏词。 但是让我们面对它,你正在有效地使用循环结构来做同样的事情。 我对此的看法要么是诚实的,要么使用goto
或重构代码。
我不认为这是最可读的方式。 链接if
- else if
看起来好多了。 但是如果你想坚持下去并且不想接近无限循环,你可以这样做:
do
{
if (...)
break;
...
} while (false);
不幸的是,只有C ++:
if ( condition1
&& (condition2.setup(), condition2)
&& (condition3.setup(), condition3) )
{
dosomething();
}
对于java兼容的东西(但我还在编写C ++!)我会回到这个问题的路上。 (显然,某些上下文可能需要传递给CheckConditions()
。)
bool CheckConditions()
{
if (!condition1)
return false;
condition2.setup();
if (!condition2)
return false;
condition3.setup();
if (!condition3)
return false;
return true;
}
//...
if (CheckConditions())
{
dosomething();
}
//...
您似乎担心评估条件2需要一些设置,而您不知道将它放在何处。 将其重构为一个单独的布尔方法,然后使用几乎所有人在这里描述的方式。 例如:
if (checkCondition1() && checkCondition2(someInput) && checkCondition3()) {
doSomething();
}
和..
private boolean checkCondition2(Object someInput) {
//setup condition 2
return condition2;
}
我觉得这个问题
if (condition1 && condition2 && ...)
很简单,如果有很多条件,它可能会变得难以阅读和编辑,尽管你总是这样写:
if ( condition1 &&
condition2 &&
condition3 ... )
doStuff();
你怎么样把循环变成一个函数:
bool all()
{
if (!condition1) return false;
if (!condition2) return false;
if (!condition3) return false;
....
return true;
}
如果你想保持缩进,这是一种妥协:
boolean valid = true; // optimistic start
if (!valid || !condition1)
valid = false;
if (!valid || !condition2)
valid = false;
if (!valid || !condition3)
valid = false;
if (valid)
doSomething();
第一个if
语句中的!valid
是超级流畅但不会造成伤害,可以保留以便于阅读。 else/if
更优雅,我认为,但这只是一个意见。
但我真的不会(ab-)使用for循环,我从来没有找到一种廉价的方法来实现伪goto。 总有一个更好的解决方案。
如果在循环结束时有一个break语句,我不确定为什么你需要一个循环。 不管情况如何,你只是迭代一次吗?
无论如何,你通常会在SO上找到两个不同的意见,一个是断言不应该被使用,一个是它取决于情况。
我倾向于使用后一组,但循环的工作方式使用多余的break语句。 我宁愿构造这样的循环:
bool valid = true;
for(... ; .... && valid == true ; ....)
{
if (!condition1)
valid = false;
if (!condition2)
valid = false;
if (!condition3)
valid = false;
}
这允许循环退出,我认为更优雅。
拥有如此长的if语句很可能是错误的编码。
这使得测试非常困难,并且很可能是代码味道。
如果可能,您应该重构以利用多态性。
如何将设置重定位到Condition类的operator bool? 这使得它更具可读性并隐藏了机制。
class Condition
{
bool _isSet;
public:
Condition() : _isSet(false) {
}
void setup() {
_isSet = true;
}
operator bool () {
if (!_isSet) {
setup();
}
return rand() & 1;
}
};
void doSomething()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Condition cond1, cond2, cond3;
if (cond1 && cond2 && cond3) {
doSomething();
}
return 0;
}
您可以将该代码输出到单独的函数并使用多个return语句。 无论如何,您可能需要将if
语句的长列表重构为单独的函数。
bool isValid()
{
if (!condition1)
return false;
condition2.setup();
if (!condition2)
return false;
condition3.setup();
if (!condition3)
return false;
return true;
}
然后你可以在你的代码中使用它:
if (isValid()) dosomething();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.