web-dev-qa-db-ja.com

すべての条件をキャッチするはずのif-elseラダー-冗長なfinal句を追加する必要がありますか?

これは私が最近よくしていることです。

例:

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else if (i > current) {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

多くの場合、if/elseラダーはこれよりもはるかに複雑です...

最後の条項をご覧ください。それは冗長です。はしごは最終的にすべての可能な条件をキャッチすることになっています。したがって、次のように書き直すことができます。

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

これまでコードを書いていた方法ですが、このスタイルは嫌いです。私の不満は、コードの最後の部分が実行される条件がコードから明らかではないということです。したがって、この条件をより明確にするために、この条件を明示的に記述し始めました。

しかしながら:

  • 最終的な完全な状態を明示的に書くことは私自身のアイデアであり、私は自分のアイデアで悪い経験をしています-通常、私がやっていることがどれほど恐ろしいかについて人々は私に悲鳴を上げます次善;
  • これが悪い考えである理由の1つのヒント:JavaScriptには適用できませんが、他の言語では、コンパイラーは関数の終わりに到達するコントロールについて警告またはエラーを発行する傾向があります。そのようなことをすることのヒントはあまり人気ではないかもしれませんし、私はそれを間違っています。
    • コンパイラの不満のためにコメントに最終条件を書き込むことがありましたが、コードとは異なり、コメントは実際のプログラムのセマンティクスに影響を与えないため、そうすることは恐ろしいことだと思います。
    } else { // i > current
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }

何か不足していますか?それとも、私が説明したことをしても大丈夫ですか、それとも悪い考えですか?

10
gaazkam

どちらのアプローチも有効です。しかし、長所と短所を詳しく見てみましょう。

このような些細な条件を持つifチェーンの場合、それは実際には重要ではありません。

  • 最後のelseを使用すると、elseがどの条件でトリガーされるかを読者が知るのは明らかです。
  • 最後のelse if、すべてをカバーしたので、追加のelseが不要であることは読者にとって明らかです。

ただし、より複雑な条件に依存する多くのifチェーンがあり、複数の変数の状態を、おそらく複雑な論理式と組み合わせます。この場合、それほど明白ではありません。そして、ここで各スタイルの結果:

  • 最終else:分岐の1つが確実に取られます。 1つのケースを忘れた場合は、最後のブランチを通過するため、デバッグ中に、最後のブランチが選択されていて、別のブランチが予期されていた場合は、すぐにわかります。
  • 最後の else if:コードに冗長な条件を導出する必要があります。これにより、すべてのケースをカバーしないというリスクを伴う潜在的なエラーソースが作成されます。さらに、ケースを逃した場合は何も実行されず、何かが欠落していることを見つけるのがより困難になる可能性があります(たとえば、設定することが予想されたいくつかの変数が以前の反復の値を保持している場合)。

したがって、最後の冗長な状態がリスクの原因になります。これが私がむしろ最終的なelseに行くことを提案する理由です。

編集:高信頼性コーディング

高い信頼性を念頭に置いて開発している場合は、別のバリアントに興味がある可能性があります。冗長な明示的なfinal else if最後のelseを付けて、予期しない状況をキャッチします。

これは防御コーディングです。 SEI CERT または [〜#〜] misra [〜#〜] などの一部のセキュリティ仕様で推奨されています。一部の静的分析ツールでは、これを rule として実装し、体系的にチェックします(これにより、コンパイラの警告が説明される場合があります)。

6
Christophe

これまでの回答に欠けているのは、どのような失敗が害が少ないかという問題です。

ロジックが適切であれば、何をしてもかまいません。重要なケースは、バグがある場合に何が起こるかです。

最後の条件を省略します。それが正しくない場合でも、最後のオプションが実行されます。

最後の条件を追加するだけです。状況に応じて、何かが表示されない(害が少ない)ことを意味する場合もあれば、後の時点でnull参照例外を意味する場合もあります(デバッグの場合もあります)。疼痛。)

最後の条件と例外を追加します:スローします。

これらのオプションのどれが最適かを判断する必要があります。開発コードでは、これは非常に簡単であると考えています。ただし、スローする前に、circle.srcをエラー画像に設定し、circle.altをエラーメッセージに設定します。誰かが後でアサーションをオフにすると、無害に失敗します。

考慮すべきもう1つのこと-回復オプションは何ですか?回復パスがない場合もあります。これの究極の例は、アリアンVロケットの最初の打ち上げだと思います。キャッチされていない/ 0(実際には除算オーバーフロー)エラーが発生し、ブースターが破壊されました。実際には、クラッシュしたコードはその時点では何の役にも立ちませんでした。軌道またはブームになったら、できる限り最善を尽くします。エラーは許されません。 (これによりロケットが迷った場合、射程安全担当者が鍵を回します。)

5
Loren Pechtel

私がお勧めするのは、最後のelseでassertステートメントを次の2つのスタイルのいずれかで使用することです。

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else {
        assert i > current
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    }
}

またはデッドコードアサーション:

setCircle(circle, i, { current }) {
    if (i == current) {
        circle.src = 'images/25CE.svg'
        circle.alt = 'Now picking'
    } else if (i < current) {
        circle.src = 'images/25C9.svg'
        circle.alt = 'Pick failed'
    } else if (i > current) {
        circle.src = 'images/25CB.svg'
        circle.alt = 'Pick chance'
    } else {
        assert False, "Unreachable code"
    }
}

多くの場合、コードカバレッジツールは、カバレッジレポートから "falseをアサート"のようなコードを無視するように構成できます。


条件をアサーションに入れると、ブランチの条件を効果的に明示的に文書化できますが、コメントとは異なり、アサーション条件は実際にチェックでき、開発中または本番環境でアサーションを有効にしておくと失敗します(アサーションを有効にしておくことをお勧めしますパフォーマンスにあまり影響しない場合は、本番環境で)。

4
Lie Ryan

条件を評価する「アサート」されたマクロを定義しました。デバッグビルドでは、デバッガーに分類されます。

したがって、3つの条件のうちの1つが真でなければならないことを100%確信している場合は、

If condition 1 ...
Else if condition 2 .,,
Else if asserted (condition3) ...

これにより、1つの条件が真であることが明確になり、アサート用の追加の分岐は必要ありません。

0
gnasher729