Rẽ nhánh lồng nhau

Khái niệm

Rẽ nhánh lồng nhau xuất hiện khi một quyết định chỉ được xét tiếp sau khi một quyết định khác đã thỏa mãn. Cấu trúc này cần được dùng cẩn thận, vì quá nhiều tầng lồng nhau sẽ làm mã khó đọc.

Sơ đồ luồng

graph TD; A((Bắt đầu)) --> B{Điều kiện\nngoài?}; B -- Sai --> E[Nhánh ngoài\nsai]; B -- Đúng --> C{Điều kiện\ntrong?}; C -- Đúng --> D[Nhánh trong\nđúng]; C -- Sai --> F[Nhánh trong\nsai]; D --> G((Tiếp tục)); E --> G; F --> G;

Ví dụ kiểm tra điều kiện đăng ký

age = 20
has_id = True

if age >= 18:
    if has_id:
        print("Du dieu kien dang ky")
    else:
        print("Can bo sung giay to")
else:
    print("Chua du tuoi")
program NestedIfDemo;

var
  age: Integer;
  hasId: Boolean;

begin
  age := 20;
  hasId := True;

  if age >= 18 then
  begin
    if hasId then
      Writeln('Du dieu kien dang ky')
    else
      Writeln('Can bo sung giay to');
  end
  else
    Writeln('Chua du tuoi');
end.
#include <stdbool.h>
#include <stdio.h>

int main(void) {
    int age = 20;
    bool hasId = true;

    if (age >= 18) {
        if (hasId) {
            printf("Du dieu kien dang ky\n");
        } else {
            printf("Can bo sung giay to\n");
        }
    } else {
        printf("Chua du tuoi\n");
    }

    return 0;
}
#include <iostream>
using namespace std;

int main() {
    int age = 20;
    bool hasId = true;

    if (age >= 18) {
        if (hasId) {
            cout << "Du dieu kien dang ky" << endl;
        } else {
            cout << "Can bo sung giay to" << endl;
        }
    } else {
        cout << "Chua du tuoi" << endl;
    }

    return 0;
}
int age = 20;
bool hasId = true;

if (age >= 18)
{
    if (hasId)
    {
        Console.WriteLine("Du dieu kien dang ky");
    }
    else
    {
        Console.WriteLine("Can bo sung giay to");
    }
}
else
{
    Console.WriteLine("Chua du tuoi");
}
const age = 20;
const hasId = true;

if (age >= 18) {
    if (hasId) {
        console.log("Du dieu kien dang ky");
    } else {
        console.log("Can bo sung giay to");
    }
} else {
    console.log("Chua du tuoi");
}
const age: number = 20;
const hasId: boolean = true;

if (age >= 18) {
    if (hasId) {
        console.log("Du dieu kien dang ky");
    } else {
        console.log("Can bo sung giay to");
    }
} else {
    console.log("Chua du tuoi");
}
package main

import "fmt"

func main() {
    age := 20
    hasId := true

    if age >= 18 {
        if hasId {
            fmt.Println("Du dieu kien dang ky")
        } else {
            fmt.Println("Can bo sung giay to")
        }
    } else {
        fmt.Println("Chua du tuoi")
    }
}
fn main() {
    let age = 20;
    let has_id = true;

    if age >= 18 {
        if has_id {
            println!("Du dieu kien dang ky");
        } else {
            println!("Can bo sung giay to");
        }
    } else {
        println!("Chua du tuoi");
    }
}

Khi nào nên cân nhắc lại thiết kế

  • Khi số tầng lồng nhau vượt quá hai hoặc ba mức.
  • Khi cùng một biến bị kiểm tra lặp lại ở nhiều tầng.
  • Khi quy tắc có thể tách thành các hàm nhỏ hoặc các điều kiện ghép rõ ràng hơn.

Kết luận

Rẽ nhánh lồng nhau có ích trong những bài toán nhiều điều kiện phụ thuộc. Tuy nhiên, nên ưu tiên cấu trúc phẳng hơn khi có thể để mã nguồn dễ đọc và dễ bảo trì.

Ghi chú theo ngôn ngữ

Thông tin</div>

Python dùng thụt đầu dòng để phân tầng nhánh. Cần giữ nhất quán số khoảng trắng mỗi cấp — pha trộn tab và space là lỗi cú pháp. Mã Python dễ đọc nhất khi tránh quá ba tầng lồng.

Pascal dùng begin...end bắt buộc cho khối nhiều câu lệnh trong nhánh if. Mỗi tầng lồng thêm một cặp begin...end, giúp ranh giới khối rõ ràng nhưng cũng làm mã dài hơn.

C dùng cặp { } để gộp nhiều câu lệnh thành một khối. Khi lồng nhiều tầng, dễ nhầm cặp ngoặc. Căn lề xuyên suốt và thêm chú thích đóng ngoặc giúp tránh lỗi.

C++ giống C về cú pháp. Một kỹ thuật phổ biến trong C++ để giảm tầng lồng là “early return”: kiểm tra điều kiện thất bại trước, return sớm, thay vì lồng toàn bộ vào khối if (success).

C# dùng cú pháp giống C/C++ với { }. Các công cụ phân tích mã (như Roslyn analyzers) của C# thường cảnh báo khi có quá nhiều tầng lồng và đề xuất cách tái cấu trúc như dùng && ghép điều kiện.

JavaScript hỗ trợ các kỹ thuật giảm lồng nhau như: optional chaining (?.), nullish coalescing (??), và early return. Trong code async, async/await với try-catch thường thay thế chuỗi callback lồng nhau.

TypeScript bổ sung kiểu dữ liệu cho JavaScript, giúp IDE phát hiện điều kiện dư thừa tại thời điểm biên dịch. Ví dụ: kiểm tra null sau khi đã khai báo giá trị không-null sẽ được cảnh báo.

Go khuyến khích phong cách “flat code” — xử lý lỗi và trường hợp đặc biệt trước bằng if err != nil { return }, giữ luồng chính ở ngoài cùng. Điều này tự nhiên giảm thiểu rẽ nhánh lồng nhau.

Rust thường dùng match thay cho if lồng nhau khi có nhiều nhánh. if let cũng giúp kiểm tra và giải nén giá trị cùng lúc mà không cần tầng lồng thêm.

iên, nên ưu tiên cấu trúc phẳng hơn khi có thể để mã nguồn dễ đọc và dễ bảo trì.

Bình luận