この記事は、HUAWEI CLOUDコミュニティ「ネストされた条件付きをガード句に置き換える」、作成者:JavaEdgeから共有されています。
動機
条件式には通常、次の2つの種類があります。
- 両方の条件分岐は正常な動作です
- 1つの条件付き分岐のみが正常な動作であり、もう1つの分岐は異常です
これらの2つのタイプの条件式は、異なる目的を果たします。これは、コードに表示する必要があります。
-
両方のブランチが正常な動作である場合は、if ...else...という形式の条件式を使用する必要があります
-
条件が非常にまれな場合は、個別にチェックして、条件が真になったらすぐに関数から返す必要があります
このような個別のチェックは、「ガード条項」と呼ばれることがよくあります。
ネストされた条件式をガードに置き換えることの本質は、ブランチに特別な注意を払うことです。if-then-else構文を使用する場合は、ifブランチとelseブランチに同じ重みを置きます。このようなコード構造の読者へのメッセージは、各ブランチが等しく重要であるということです。ガードステートメントは、読者に次のように伝えています。「この状況は、この関数のコアロジックが気にするものではありません。発生した場合は、必要なクリーンアップを実行して終了してください。」
「すべての関数は1つのエントリと1つの出口しか持てない」という概念は、一部のプログラマーに深く根付いています。彼らが書いたコードを扱うとき、ネストされた条件式の代わりにガードステートメントを使用する必要があることがよくあります。今日のプログラミング言語では、関数ごとに1つのエントリしか適用されておらず、「単一終了」ルールはそれほど有用ではありません。コードを明確に保つことが重要です。単一の出口で関数が読みやすくなる場合は、単一の出口を使用します。それ以外の場合は、そうではありません。
練習
置き換える必要のある最も外側の条件付きロジックを選択し、ガードステートメントに置き換えます。
テスト。
必要に応じて、上記の手順を繰り返します。
すべてのガードステートメントが同じ結果を生成する場合は、[条件式のマージ]を使用してそれらを組み合わせることができます。
場合
従業員に支払われる賃金を計算します。まだ会社で働いている従業員だけが支払われる必要があるので、この手紙
番号は、2つの「従業員がもう仕事をしていない」状況をチェックする必要があります。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
} else {
if (employee.isRetired) {
result = 0;
} else {
// logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
}
} return result;
}
ネストされた条件付きロジックは、コードが実際に何を意味するのかを理解するのを困難にします。現在の2つの条件式のどちらも真でない場合にのみ、このコードは実際に主な作業を開始します。したがって、ガードステートメントを使用すると、コードでその意図をより明確に表現できます。いつものように、私は小さな一歩を踏み出すのが好きなので、最初に最上位の条件付きロジックを扱います。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
result = 0;
}
if (employee.isRetired) {
result = 0;
} else { // logic to compute amount
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed.do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
} return result;
}
この変更を行った後、テストを実行して次のステップに進みます。
public Long payAmount(Employee employee) {
long result;
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
result = someFinalComputation();
return result;
}
この時点では、結果変数は役に立たないので、削除します。
public Long payAmount(Employee employee) {
if (employee.isSeparated) {
return 0l;
}
if (employee.isRetired) {
return 0l;
}
lorem.ipsum(dolor.sitAmet);
consectetur(adipiscing).elit();
sed. do.eiusmod = tempor.incididunt.ut(labore) && dolore(magna.aliqua);
ut.enim.ad(minim.veniam);
return someFinalComputation();
}
1つの可変変数を減らすことができるのは常に良いことです。
状態を逆転させる
多くの場合、条件式を逆にして、ネストされた条件式をガードに置き換えることができます。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital > 0) {
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
}
return result;
}
1つずつ交換してください。しかし、今回はガードステートメントを挿入するときに、対応する条件を逆にする必要があります。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate > 0 && anInstrument.duration > 0) {
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
return result;
}
次の条件はもう少し複雑なので、2つのステップで反転を行います。最初に論理NOT演算を追加します。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (!(anInstrument.interestRate > 0 && anInstrument.duration > 0)) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
しかし、このような条件式に論理否定を残すと頭がおかしくなるので、次のように簡略化しました。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0) {
return result;
}
if (anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
これらの2行のロジックは同じ結果を生成するため、[条件式のマージ]と組み合わせることができます。
public int adjustedCapital(Instrument anInstrument) {
int result = 0;
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return result;
}
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
return result;
}
この時点で、結果変数は2つのことを行います。最初は0に設定します。これは、ガードステートメントがトリガーされたときの戻り値を表します。次に、最終的な計算の結果を割り当てます。この変数を完全に削除し、1つの変数との二重の責任を回避し、別の変数変数を減らすことができます。
public int adjustedCapital(Instrument anInstrument) {
if (anInstrument.capital <= 0 || anInstrument.interestRate <= 0 || anInstrument.duration <= 0) {
return 0;
}
return (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
参照する
- 「復興」
- 「クリーンアーキテクチャ」