1

次のようなコードを書きました。

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 ステートメント内の状態を変更します。しかし、私の同僚はこれを非常に嫌っていました。

これは有害な行為ですか?そうする理由はありますか?

4

14 に答える 14

15

はい。これは明らかに可読性を低下させます。次のコードの何が問題になっていますか?

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 の引用を常に覚えておくとよいでしょう。

デバッグは、最初にコードを書くよりも 2 倍大変です。したがって、コードをできるだけ賢く書いたとしても、定義上、それをデバッグするほど賢くはありません。

于 2009-11-25T22:33:31.963 に答える
4

...しかし、私の同僚はこれを非常に嫌っていました...

はい、そうです。そのようにコーディングできるからというだけでなく、そうしなければなりません。

そのコードは最終的に誰かが維持する必要があることを忘れないでください(誰かが8か月であなた自身になる可能性があります)

if、make内の状態を変更すると、読みにくく、理解しにくくなります(主に一般的ではないため)

マーティンファウラーの引用:

愚か者なら誰でも、コンピューターが理解できるコードを書くことができます。優れたプログラマーは、人間が理解できるコードを記述します

于 2009-11-25T22:49:11.567 に答える
2

問題は、コードがコードレビューセッションで複数のWTFを生成することです。人々を「待たせる、何?」行かなければなりません。

読みやすいコードでもバグを作成するのは悲しいことに簡単です。それをさらに簡単にする理由はありません。

于 2009-11-25T22:35:16.157 に答える
2

これを行わないのには十分な理由があります。それは、コードの理解と推論を非常に難しくするからです。

于 2009-11-25T22:33:51.687 に答える
1

それの唯一の間違いは、それを書いていなかった人々にとって、それが理解している間、少なくとも1分間はなじみがなく、混乱しているということです。読みやすくするために、おそらく次のように記述します。

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

if (list.length >= 2 && (list[0] + "/" + list[1]).equals(SKIP_SECOND)) {
    return 2;
}
于 2009-11-25T22:36:16.413 に答える
1

cppreference.comから借用:

演算子の優先順位に関連する C++ の重要な側面の 1 つは、評価の順序と式の副作用の順序です。状況によっては、物事が起こる順序が定義されていません。たとえば、次のコードを考えてみましょう。

float x = 1;
x = x / ++x;

x の値は、コンピューターが除算の左側と右側のどちらを最初に評価する必要があるかが明確でないため、異なるコンパイラ間で一貫性があるとは限りません。どちら側が最初に評価されるかに応じて、x は異なる値を取る可能性があります。

さらに、++x は x+1 に評価されますが、その新しい値を x に実際に格納することによる副作用が異なるタイミングで発生し、結果として x の値が異なる可能性があります。

肝心なのは、上記のような表現は恐ろしく曖昧であり、絶対に避けるべきだということです。疑わしい場合は、1 つのあいまいな式を複数の式に分割して、評価の順序が正しいことを確認してください。

于 2009-11-25T22:45:02.523 に答える
1

これは有害な行為ですか?

はいぜったいに。コードがわかりにくい。著者以外の誰でも2、3回読む必要があります。理解するのが難しく、より簡単に理解しやすい方法で書き直すことができるコードは、そのように書き直す必要があります。

あなたの同僚は絶対に正しいです。

そうする理由はありますか?

そのようなことを行う唯一の理由として考えられるのは、アプリケーションを広範囲にプロファイリングし、コードのこの部分が重大なボトルネックであることが判明したことです。次に、上記の嫌悪感を実装し、プロファイラーを再実行すると、パフォーマンスが本当に向上することがわかりました。

于 2009-11-26T00:26:16.397 に答える
1

はい、コードをレビューするときに副作用を追跡するのは困難です。

そうする理由について:いいえ、そうする本当の理由はありません。副作用なしで損失なしに書き換えることができない if ステートメントにまだ出くわしていません。

于 2009-11-25T22:33:38.067 に答える
0

さて、何が起こっているのかわからないまま、上記を読んで時間を過ごしました。だから私は間違いなくそれが理想的ではないことをお勧めします。if()ステートメント自体が状態を変更することは実際には期待していません

于 2009-11-25T22:37:41.487 に答える
0

非常に正当な理由がない限り、副作用のあるif条件はお勧めしません。私にとって、この特定の例では、何が起こっているのかを理解するためにいくつかの調査を行いました。確かに思いつかないのですが、それほど悪くない場合もあるかもしれません。

于 2009-11-25T22:38:02.557 に答える
0

複数のリターンを避けるために、三項を取得することもできます。

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);
}

この例は読みにくいですが。

于 2009-11-25T23:32:29.597 に答える
0

理想的には、各コードは 1 つのことを行う必要があります。複数のことを実行させると混乱する可能性があり、混乱はまさにコードで望ましくないことです。

if ステートメントの条件のコードは、ブール値を生成することになっています。値を割り当てるというタスクは、2 つのことを行うことになり、これは一般的に悪いことです。

さらに、人々は条件が単なる条件であることを期待しており、コードが何を行っているかの印象を得るときに、それらを一瞥することがよくあります。必要があると判断するまで、すべてを慎重に解析するわけではありません。

私がレビューしているコードにそれを貼り付けてください。欠陥としてフラグを立てます。

于 2009-11-25T22:44:31.400 に答える
0

C では、if ステートメント内で状態を変更することはかなり一般的です。一般的に言えば、これが許容される場所について、いくつかの不文律があることがわかりました。たとえば、次のようになります。

  • 変数を読み込んで結果をチェックしています。

    int a;
    ...
    if ((a = getchar()) == 'q') { ... }
    
  • 値を増やして結果を確認する:

    int *a = (int *)0xdeadbeef;
    ...
    if (5 == *(a++)) { ... }
    

そして、それが受け入れられない場合:

何らかの理由で、コードとしてマークしようとしているセクションのフォントは SO では固定幅ではありませんが、固定幅フォントでは、if式内の割り当てが適切で明確な場合があります。

于 2009-11-25T23:16:29.927 に答える
0

多くの保守プログラミングを行う者として言えば、もし私がこれに出くわしたら、私はあなたをののしり、泣いてから変更します。

このようなコードは悪夢です - それは 2 つのことのいずれかを叫びます

  1. 私はここに来たばかりで、正しいことをするために助けが必要です。
  2. コード行を節約したり、コンパイラをだまして高速にしたりしたので、私は非常に賢いと思います。賢くない、最適でない、面白くない

;)

于 2009-11-25T23:55:48.647 に答える