ビジネスコードにおけるIF-ELSEプラクティスの最適化について話します


はじめに:単純で反復的なビジネスコードを使用している場合は、成長できるように、方法論を考え、要約し続ける必要があります。

IF-ELSE分岐判定は、ビジネスコードを書く上で避けられないプログラムステートメントであり、分岐判定の解決に役立ちますが、メソッド内のビジネスが少し複雑な場合、IF-ELSE分岐が多くなり、さまざまなネストされた判定が発生する可能性があります。プロセス処理。

ここに画像の説明を挿入
この記事にはベストプラクティスは含まれていません。私の日常業務の概要について説明します。合計6つのポイントがあります。これらの6つのポイントは、段階的な最適化ではありません。良いことも悪いこともありません。重要なことは、特定のビジネスに適用することです。コードプロセス。適切でシンプルな方法を選択することが最も重要です。

1.ブランチの判断を避けるのが最善です

分岐判定は面倒なので、分岐判定は避けた方がいいでしょう。しかし、これは理想的すぎるように思われますが、いくつかの単純な判断ロジックでは分岐判断を回避できます。ここで説明する回避は、分岐判断ではありませんが、次のような独自のビジネスコードに分岐判断が埋め込まれないようにするために既存のツールを使用する方法を学びます。数値を比較するため、JDKのMathツールクラスを使用して数値を処理できます。さらに、一部の収集操作は、収集ツールキットでも処理できます。

【普通】

 double result;
  if (value <= MIN_LIMIT) {
    
    
      result = MIN_LIMIT;
  } else {
    
    
      result = value;
  }

【最適化】

double result = Math.max(MIN_LIMIT, value);
2.条件の範囲を最小限に抑える

条件の範囲を最小限に抑え、共通の処理コードを提案してみてください。共通の変数を使用して同じ論理コードを処理できます
[通常]

  Result result = service.doWork();
  if (result.isSuccess()) {
    
    
      String message = "任务处理成功";
      smsService.sendMessage(user.getPhone(), message);
  } else {
    
    
      String message = "任务处理失败:" + result.getMessage();
      log.warn(message);
      smsService.sendMessage(user.getPhone(), message);
  }

【最適化】

 String message;
 Result result = service.doWork();
 if (result.isSuccess()) {
    
    
     message = "任务处理成功";
 } else {
    
    
     message = "任务处理失败:" + result.getMessage();
     log.warn(message);
 }
 smsService.sendMessage(user.getPhone(), message);
3.条件付きフィルターの場所

条件付きスクリーニングの場所は、コードのスケーラビリティと読みやすさに関係していませんが、IF-ELSEの最適化に関係しています。複数の条件付きスクリーニング判定がある場合は、ほとんどのデータを除外できる判定ブランチを前面に配置します。これにより、コード処理の効率が向上します。

特別な状況を事前に除外し、コアビジネスロジックにさらに注意を払います

4.保護者の文章

Guardianステートメントは、複雑な条件式を複数の条件式に分割することです。たとえば、複数のif-elseif-elseがネストされている場合、それらを複数のifに分割できます。次のコードなど

【普通】

 public void test () {
    
    
     if (isWeekend()) {
    
    
         if (isRest()) {
    
    
             System.out.println("看书学习");
         } else {
    
    
             System.out.println("加班");
         }
     } else {
    
    
         //这里省略了周一到周五的分支判断
     }
 }

[最適化]
説明:
2つのポイントがあります:
1。複数のIFを設定して複数のネストされたIF-ELSEを置き換えます。複数のIFを設定すると、コードが読みやすくなり、各IFの処理ロジックについても作成できます。次のコードのように、コード抽出を介して個別にメソッドを実行すると見栄えが良くなります

public Object test() {
    
    
    if (!isWeekend()) {
    
    
      return doSomething1();
    }
    if (isRest()) {
    
    
     return   doSomething2();
    }
    if (other()) {
    
    
     return   doSomething3();
    }
    return   doSomething4();
}

2.文章を保護する方法により、事前特殊情况除外して、コアビジネスコードの実現により集中できるようにします。

public void test() {
    
    
    // 提前过滤掉`特殊情况`
    if (!isWeekend()) {
    
    
        System.out.println("XXX");
        return; // 提前return
    }
    //提前过滤掉`特殊情况`
    if (isRest()) {
    
    
        System.out.println("XXX");
        return; // 提前return
    }
    //更关注于 `核心业务`代码实现
     doSomething();
}
5.ブランチを選択し、if-elseステートメントの代わりにswitchステートメントを使用することをお勧めします

if-elseステートメント。if条件ステートメントがtrueになるまで、各if条件ステートメントに計算を装備する必要があります。switchステートメントはジャンプ用に最適化されており、Javaではtableswitchまたはlookupswitch命令を使用して、複数定数の選択ブランチ処理の効率を高めています。実験によると、各ブランチの発生確率が同じである場合、ブランチが5つ未満の場合はif-elseステートメントの方が効率的であり、ブランチが5つを超える場合はswitchステートメントの方が効率的です。
【普通】

if (i == 1) {
    
    
    ...; // 分支1
} else if (i == 2) {
    
    
    ...; // 分支2
} else if (i == ...) {
    
    
    ...; // 分支3
} else {
    
    
    ...; // 分支n
}

【最適化】

switch (i) {
    
    
    case 1 :
        ... // 分支1
        break;
    case 2 :
        ... // 分支2
        break;
    case ... :
        ... // 分支n
        break;
    default :
        ... // 分支n+1
        break;
}
6.分岐が三項演算子に変更されます

判定結果の戻り値が1つしかないブランチの場合は比較的単純なので、三項演算子を使用して対応するブランチを置き換えることができます。たとえば、数値を比較します(a> = b)?A:b。1行のコードで解決できるこの種のロジックでは、&&演算子と||演算子を組み合わせて使用​​することもできます。
通常

String title;
if (isMember(phone)) {
    
    
    title = "会员";
} else {
    
    
    title = "访客";
}

最適化

String title = isMember(phone) ? "会员" : "访客";

注:パッケージタイプの算術計算では、解凍時にnullポインターの問題を回避するように注意する必要があります。

7.マップデータ構造+戦略モード+ファクトリモードを使用して、複雑なビジネスIF-ELSEを処理します

実際のビジネスコードでは、特定のタイプに応じて異なるビジネスロジック処理が実行される場合が多く、これは通常、多くのブランチの判断に関連付けられています。さらに、非常に重要な点は、ビジネスのこの部分は後で変更して増やす必要があると判断されるということです。ビジネスコードのこの部分を最適化するにはどうすればよいでしょうか。実用的な参考資料として、マップデータ構造+戦略モードで対処することをお勧めします。

マッピング関係のif-elseステートメントの場合、Mapを使用して単純化できます。さらに、このルールは、マッピング関係を単純化し、Mapデータ構造を使用して分岐の問題を解決するswitchステートメントにも適用できます。

【普通】

 public static String getNameByType(String type) {
    
    
        switch (type) {
    
    
            case "A001":
                return "登录成功";
            case "B001":
                return "密码错误";
            case "C001":
                return "验证码错误";
            case "D001":
                return "短信发送失败";

        }
    }

【最適化】

private static final Map<String, String> MAP = ImmutableMap.<String, String>builder()
            .put("A001", "登录成功")
            .put("B001", "密码错误")
            .put("C001", "验证码错误")
            .put("D001", "短信发送失败").build();


    public static void main(String[] args) {
    
    
        String type = "A001";
        String result = MAP.get(type);

    }

上記のコードは、さまざまな種類の情報を格納するためにMapを使用していますが、上記のコードは比較的固定されています。一方で、マップデータを展開する場合は変更する必要があり、他方では、複雑なビジネスには適していません。処理。

この種の問題では、戦略パターン+ファクトリメソッドを使用して、複雑なビジネスと簡単な拡張の問題を解決できます。

詳細なコード設計はもう記載されていません。詳細については、次のブログ投稿を参照してください:
https //juejin.cn/post/6844903974525468680

概要:
1。ストラテジーインターフェイスを提供します
。2。マップコンテナにさまざまなブランチ処理オブジェクトを格納するためのStrategyFactoryファクトリクラスを
提供します。3。各ビジネス処理クラスがロードされるときに、Springが提供するInitializingBeanインターフェイスを使用して、StrategyFactoryを介してコンテナに挿入します。
4.さまざまなビジネスに応じて、特定のビジネス処理を実行するためにさまざまなBeanを取得してオブジェクトを取得します

おすすめ

転載: blog.csdn.net/Octopus21/article/details/114412950