VISEN GROUP
Technology & Engineering

Tránh lạm dụng Nested If-Else bằng nguyên lý Early Return (Guard Clauses)

September 11, 20264 min readUncategorized

Đã bao nhiêu lần bạn đọc một đoạn code và phải cuộn chuột qua 4–5 tầng if-else lồng nhau dạng hình kim tự tháp (Pyramid of Doom / Arrow Anti-pattern)?

Mỗi lần thụt dòng (indentation) không chỉ khiến code bị đẩy tít sang mép phải màn hình, mà còn ép não bộ của người đọc phải “ghi nhớ ngăn xếp” (stack memory) hàng loạt điều kiện chỉ để hiểu được luồng xử lý chính nằm tận đáy.

Dưới đây là cách refactor kinh điển nhưng cực kỳ hiệu quả để làm phẳng code: Early Return kết hợp Guard Clauses.

    1.”Kim tự tháp” điều kiện – Cơn ác mộng khi bảo trì

    Hãy thử đọc một hàm xử lý thanh toán đơn hàng khá quen thuộc:

    // CÁCH CŨ: Lồng nhau 4 tầng (Nested Hell)
    function processPayment(order, user) {
      if (order) {
        if (order.items.length > 0) {
          if (user.isVerified) {
            if (user.balance >= order.totalAmount) {
              // Xử lý thanh toán chính
              user.balance -= order.totalAmount;
              order.status = "PAID";
              const invoice = generateInvoice(order, user);
              return { success: true, invoice };
            } else {
              return { success: false, message: "Số dư ví không đủ" };
            }
          } else {
            return { success: false, message: "Tài khoản chưa xác thực" };
          }
        } else {
          return { success: false, message: "Giỏ hàng rỗng" };
        }
      } else {
        return { success: false, message: "Đơn hàng không tồn tại" };
      }
    }

    Điểm yếu chí mạng:

      • Lỗi nằm quá xa điều kiện: Bạn kiểm tra if (order) ở dòng đầu, nhưng khối else báo lỗi đơn hàng không tồn tại lại nằm tít tận dòng cuối cùng.
      • Happy Path bị bọc kín: Luồng logic quan trọng nhất và thành công nhất lại bị giấu vào góc sâu nhất của hàm.
      • Khó mở rộng: Muốn thêm kiểm tra mã giảm giá hay tình trạng kho? Bạn lại phải thụt dòng thêm một tầng nữa.

      2. Giải pháp: Đảo ngược tư duy với Guard Clauses (Early Return)

      Tư duy của Guard Clauses (Mệnh đề bảo vệ) rất đơn giản:

      Hãy bắt các trường hợp lỗi, dữ liệu rỗng hoặc sai quyền hạn trước tiên. Nếu không hợp lệ, lập tức return hoặc ngắt hàm ngay tại chỗ. Sau khi vượt qua các trạm kiểm soát này, luồng chính sẽ nằm phẳng hoàn toàn.

      Refactor lại hàm trên:

      // CÁCH MỚI: Phẳng hóa code với Early Return
      function processPayment(order, user) {
        // 1. Các chốt chặn (Guard Clauses) - Bắt lỗi & thoát sớm
        if (!order) {
          return { success: false, message: "Đơn hàng không tồn tại" };
        }
      
        if (order.items.length === 0) {
          return { success: false, message: "Giỏ hàng rỗng" };
        }
      
        if (!user.isVerified) {
          return { success: false, message: "Tài khoản chưa xác thực" };
        }
      
        if (user.balance < order.totalAmount) {
          return { success: false, message: "Số dư ví không đủ" };
        }
      
        // 2. Happy Path - Xử lý logic nghiệp vụ chính (Phẳng 100%)
        user.balance -= order.totalAmount;
        order.status = "PAID";
        const invoice = generateInvoice(order, user);
      
        return { success: true, invoice };
      }

      3. Bảng so sánh trực quan

      Tiêu chíNested If-Else (Cách cũ)Early Return / Guard Clauses (Cách mới)
      Độ sâu thụt lề4–5 cấp tab, khó nhìn trên màn hình nhỏDuy nhất 1 cấp thụt lề, code phẳng
      Vị trí lỗiPhân tán: Điều kiện ở trên, thông báo lỗi ở đáyTập trung: Kiểm tra lỗi và return xử lý nằm cạnh nhau
      Happy PathBị vùi sâu ở lõi trong cùngRõ ràng, nằm thẳng thớm ở cuối hàm
      Viết Unit TestDễ bỏ sót các nhánh lồng nhau phức tạpMock test từng chốt chặn từ trên xuống cực dễ

      Ba nguyên tắc nằm lòng khi refactor

      1. Invert Conditions (Đảo ngược điều kiện): Thay vì hỏi “Nếu đúng thì làm tiếp”, hãy tự hỏi “Nếu sai thì thoát ngay bằng cách nào?”.
      2. Khử sạch từ khóa else thừa thãi: Khi nhánh if đã có return hoặc throw, bạn hoàn toàn không cần viết thêm else.
      3. Giữ hàm làm đúng một việc: Nếu có quá nhiều chốt chặn (trên 5 điều kiện), hãy cân nhắc tách riêng logic kiểm tra thành một hàm validation riêng biệt.

      Đừng để code của bạn biến thành “kim tự tháp”. Hãy thử mở lại dự án và làm phẳng một hàm ngay hôm nay nhé!

      Leave a Reply

      Your email address will not be published. Required fields are marked *