Java 在if语句中更改状态是一种不好的做法吗?

Java 在if语句中更改状态是一种不好的做法吗?,java,if-statement,state,Java,If Statement,State,我编写了一些类似于以下内容的代码: String SKIP_FIRST = "foo"; String SKIP_SECOND = "foo/bar"; int skipFooBarIndex(String[] list){ int index; if (list.length >= (index = 1) && list[0].equals(SKIP_FIRST) || list.length >= (index = 2) &

我编写了一些类似于以下内容的代码:

String SKIP_FIRST = "foo";
String SKIP_SECOND = "foo/bar";

int skipFooBarIndex(String[] list){
    int index;
    if (list.length >= (index = 1) && list[0].equals(SKIP_FIRST) ||
        list.length >= (index = 2) && 
        (list[0] + "/" + list[1]).equals(SKIP_SECOND)){
        return index;
    }

    return 0;
}

String[] myArray = "foo/bar/apples/peaches/cherries".split("/");
print(skipFooBarIndex(myArray);
这将通过分配索引来更改if语句内部的状态。然而,我的同事们非常不喜欢这个


这是一种有害的做法吗?有什么理由这样做吗?

是的。这明显降低了可读性。以下代码有什么问题

int skipFooBarIndex(String[] list){
    if(list.length >= 1 && list[0].equals(SKIP_FIRST)) 
        return 1;
    if(list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND))
        return 2;
    return 0;
}
这更容易理解。通常,不鼓励在表达式中产生副作用,因为您将依赖于子表达式的求值顺序

假设您将其视为“聪明”代码,那么最好记住Brian Kernighan的名言:

调试的难度是编写代码的两倍。因此,如果您尽可能巧妙地编写代码,那么根据定义,您还不够聪明,无法调试它


对。这明显降低了可读性。以下代码有什么问题

int skipFooBarIndex(String[] list){
    if(list.length >= 1 && list[0].equals(SKIP_FIRST)) 
        return 1;
    if(list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND))
        return 2;
    return 0;
}
这更容易理解。通常,不鼓励在表达式中产生副作用,因为您将依赖于子表达式的求值顺序

假设您将其视为“聪明”代码,那么最好记住Brian Kernighan的名言:

调试的难度是编写代码的两倍。因此,如果您尽可能巧妙地编写代码,那么根据定义,您还不够聪明,无法调试它


是的,在查看代码时很难了解副作用


关于这样做的理由:不,没有真正的理由这样做。我还没有偶然发现一个if语句,它不能在没有副作用的情况下重写,也不会有任何损失。

是的,在查看代码时很难理解副作用


关于这样做的理由:不,没有真正的理由这样做。我还没有偶然发现一个if语句,它不能在没有任何损失的情况下无副作用地重写。

有一个很好的理由不这样做:它使您的代码很难理解和推理

有一个很好的理由不这么做:这会让你的代码很难理解和推理

问题在于,代码将在代码审查会话中生成多个WTF。任何能让人们“等等,什么?”的东西都必须离开


不幸的是,即使在易读的代码中也很容易产生bug。没有理由让它变得更简单。

问题在于,代码将在一次代码审查会话中生成多个WTF。任何能让人们“等等,什么?”的东西都必须离开


不幸的是,即使在易读的代码中也很容易产生bug。没有理由让它变得更简单。

它唯一的错误是,对于那些没有写它的人来说,它是陌生和令人困惑的,至少在他们理解它的一分钟内。我可能会这样写,让它更具可读性:

if (list.length >= 1 && list[0].equals(SKIP_FIRST)) {
    return 1;
}

if (list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) {
    return 2;
}

唯一的问题是,对于那些没有写它的人来说,它是陌生和令人困惑的,至少在他们弄明白它的时候有一分钟是这样的。我可能会这样写,让它更具可读性:

if (list.length >= 1 && list[0].equals(SKIP_FIRST)) {
    return 1;
}

if (list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) {
    return 2;
}

嗯,我花了一些时间阅读上面的内容,却没有意识到发生了什么。所以我肯定认为这并不理想。我真的不希望if()语句本身改变状态。

好吧,我花了一些时间阅读上面的内容,却没有意识到发生了什么。所以我肯定认为这并不理想。我真的不希望if()语句本身改变状态。

如果没有很好的理由,我不建议if条件有副作用。对我来说,这个特殊的例子需要看几眼才能弄清楚到底发生了什么。可能有一种情况并不那么糟糕,尽管我肯定想不出有什么。如果没有很好的理由,我不会推荐有副作用的if条件。对我来说,这个特殊的例子需要看几眼才能弄清楚到底发生了什么。可能有一种情况并不那么糟糕,尽管我肯定想不出一种。

理想情况下,每段代码都应该做一件事。让它做不止一件事可能会让人困惑,而让人困惑恰恰是您不希望在代码中看到的

if语句条件下的代码应该生成布尔值。赋予它赋值的任务是让它做两件事,这通常是不好的

此外,人们期望条件只是条件,当他们对代码的作用有了印象时,他们经常会浏览这些条件。在他们决定需要解析之前,他们不会仔细解析所有内容


在我正在审阅的代码中坚持这一点,我会将其标记为缺陷。

理想情况下,每段代码都应该做一件事。让它做不止一件事可能会让人困惑,而让人困惑恰恰是您不希望在代码中看到的

if语句条件下的代码应该生成布尔值。赋予它赋值的任务是让它做两件事,这通常是不好的

此外,人们期望条件只是条件,当他们对代码的作用有了印象时,他们经常会浏览这些条件。在他们决定需要解析之前,他们不会仔细解析所有内容

将其粘贴到我正在审阅的代码中,我会将其标记为缺陷。

借用自:

< > C++中与操作符优先级相关的一个重要方面是表达式的顺序和副作用的顺序。在某些情况下,事情发生的顺序没有定义。例如,考虑下面的代码:

float x = 1;
x = x / ++x;
x的值不能保证在不同的编译器中是一致的,因为不清楚计算机应该首先计算除法的左侧还是右侧。根据首先计算哪一侧,x可以取不同的值

此外,虽然++x的计算结果为x+1,但在x中实际存储新值的副作用可能会在不同的时间发生,结果是
int a;
...
if (a = 5) { ... } // this is almost always unintentional
int a = 0, b;
...
if (b || a++) { ... }    // BAD!
int skipFooBarIndex(String[] list) {
    return (list.length > 0 && list[0].equals(SKIP_FIRST)) ? 1 :
       ((list.length > 1 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) ? 2 : 0);
}