[Swift] Guard-let vs If-let - Chọn người gác cổng nào cho code của bạn?

Swift 5 Th09 2024

Trong Swift, cả guard-letif-let đều là những công cụ hữu ích để unwrap optional một cách an toàn. Tuy nhiên, việc lựa chọn sử dụng câu lệnh nào phụ thuộc vào mục đích và ngữ cảnh của code.

Bài viết này sẽ so sánh guard-letif-let, giúp bạn hiểu rõ ưu nhược điểm của từng loại và cách sử dụng chúng hiệu quả.

1. If-let: Kiểm tra điều kiện và thực thi khối lệnh

Cú pháp if-let cho phép kiểm tra xem một optional có chứa giá trị hay không, và nếu có, unwrap giá trị đó và gán cho một constant mới. Constant này chỉ có thể được sử dụng trong khối lệnh nằm trong cặp dấu ngoặc nhọn của if-let.

Code mẫu:

func printName(name: String?) {
  if let unwrappedName = name {
    print("Tên của bạn là: \(unwrappedName)")
  } else {
    print("Bạn chưa nhập tên.")
  }
}

Ưu điểm:

  • Dễ đọc và dễ hiểu, đặc biệt cho những người mới học Swift.
  • Thích hợp cho các trường hợp đơn giản, khi bạn chỉ cần kiểm tra một điều kiện và thực thi một khối lệnh nhỏ.

Nhược điểm:

  • Khi có nhiều optional cần unwrap, code có thể trở nên lồng nhau và khó đọc.
  • Phạm vi sử dụng của constant được unwrap bị giới hạn trong khối lệnh if-let.

2. Guard-let: Kiểm tra điều kiện và thoát sớm (early exit)

Guard-let cũng kiểm tra optional như if-let, nhưng nó được thiết kế để "thoát sớm" khỏi function nếu điều kiện không được đáp ứng. Nếu optional là nil, code trong khối else của guard-let sẽ được thực thi, thường là return để thoát khỏi function.

Code mẫu:

func greet(name: String?) {
  guard let unwrappedName = name else {
    print("Bạn chưa nhập tên.")
    return 
  }
  print("Xin chào, \(unwrappedName)!")
}

Ưu điểm:

  • Giúp code dễ đọc hơn khi có nhiều điều kiện cần kiểm tra, tránh "kim tự tháp doom".
  • Constant được unwrap có thể được sử dụng trong toàn bộ scope của function sau câu lệnh guard-let.

Nhược điểm:

  • Có thể khó hiểu hơn if-let đối với người mới học Swift.

3. Khi nào nên sử dụng Guard-let và If-let?

Nên sử dụng guard-let khi:

  • Bạn muốn kiểm tra nhiều điều kiện trước khi thực thi logic chính của function.
  • Bạn cần sử dụng constant được unwrap trong toàn bộ scope của function.

Nên sử dụng if-let khi:

  • Bạn chỉ cần kiểm tra một điều kiện đơn giản.
  • Bạn chỉ cần sử dụng constant được unwrap trong một khối lệnh nhỏ.

4. Ví dụ so sánh

Ví dụ 1: Unwrap nhiều optional

Sử dụng if-let (code lồng nhau, khó đọc):

func printUserInfo(user: User?) {
  if let unwrappedUser = user {
    if let unwrappedName = unwrappedUser.name {
      if let unwrappedAge = unwrappedUser.age {
        print("Tên: \(unwrappedName), Tuổi: \(unwrappedAge)")
      } else {
        print("Tên: \(unwrappedName), Tuổi: Không xác định")
      }
    } else {
      print("Người dùng không có tên.")
    }
  } else {
    print("Không tìm thấy người dùng.")
  }
}

Sử dụng guard-let (code dễ đọc hơn):

func printUserInfo(user: User?) {
  guard let unwrappedUser = user else {
    print("Không tìm thấy người dùng.")
    return
  }
  guard let unwrappedName = unwrappedUser.name else {
    print("Người dùng không có tên.")
    return
  }
  guard let unwrappedAge = unwrappedUser.age else {
    print("Tên: \(unwrappedName), Tuổi: Không xác định")
    return
  }
  print("Tên: \(unwrappedName), Tuổi: \(unwrappedAge)")
}

Ví dụ 2: Phạm vi sử dụng của constant

Sử dụng if-let (constant chỉ sử dụng được trong khối lệnh):

func calculateArea(width: Double?, height: Double?) {
  if let unwrappedWidth = width {
    if let unwrappedHeight = height {
      let area = unwrappedWidth * unwrappedHeight // area chỉ sử dụng được trong khối if-let này
      print("Diện tích: \(area)")
    } else {
      print("Thiếu chiều cao.")
    }
  } else {
    print("Thiếu chiều rộng.")
  }
  // print(area) // Lỗi: area không thể truy cập ở đây
}

Sử dụng guard-let (constant sử dụng được trong toàn bộ function):

func calculateArea(width: Double?, height: Double?) {
  guard let unwrappedWidth = width else { 
    print("Thiếu chiều rộng.")
    return 
  }
  guard let unwrappedHeight = height else { 
    print("Thiếu chiều cao.")
    return 
  }
  let area = unwrappedWidth * unwrappedHeight // area có thể sử dụng được trong toàn bộ function
  print("Diện tích: \(area)")
}

5. Kết luận

Việc lựa chọn sử dụng guard-let hay if-let phụ thuộc vào ngữ cảnh và logic của code. Hiểu rõ ưu nhược điểm của từng loại sẽ giúp bạn viết code Swift an toàn, dễ đọc và dễ bảo trì hơn.

Tags

Tony Phạm

Là một người thích vọc vạch và tò mò với tất cả các lĩnh vực từ khoa học tự nhiên, lập trình, thiết kế đến ... triết học. Luôn mong muốn chia sẻ những điều thú vị mà bản thân khám phá được.