Viết logic điều kiện là điều mà mọi lập trình viên đều làm, bất kể ngôn ngữ nào. Nhưng cách mà lập trình viên cấu trúc các điều kiện đó sẽ ảnh hưởng đến mức độ dễ đọc, dễ kiểm thử và dễ bảo trì của mã nguồn.

Trong bài viết này, chúng ta sẽ xem xét hai cách tiếp cận phổ biến:

  • Return First (còn gọi là Early Return )
  • if...elseLồng nhau cổ điển

Những quy tắc này áp dụng được cho mọi ngôn ngữ lập trình — từ PHP và JavaScript đến Python, Go hoặc Java.

Return First là gì?

Return First có nghĩa là thoát khỏi một hàm ngay khi một điều kiện nhất định được đáp ứng — thường là để xử lý trường hợp ngoại lệ hoặc đầu vào không hợp lệ.

Return First còn được gọi là Early Return. Một cách sử dụng phổ biến của Early Return là Guard Clause (mệnh đề bảo vệ), trong đó các điều kiện quan trọng được kiểm tra ngay ở đầu hàm. Nếu điều kiện không được đáp ứng, hàm sẽ kết thúc ngay thay vì tiếp tục thực hiện các logic phía sau.

Điều này giúp tránh việc lồng ghép if không cần thiết và giữ cho logic cốt lõi của hàm đơn giản, dễ đọc hơn.

Ví dụ:

Thay vì viết các điều kiện lồng nhau:

public void ProcessOrder(Order order)
{
    if (order != null)
    {
        if (order.IsValid)
        {
            Console.WriteLine("Processing order...");
        }
    }
}

Có thể sử dụng Return First:

public void ProcessOrder(Order order)
{
    if (order == null)
        return;

    if (!order.IsValid)
        return;

    Console.WriteLine("Processing order...");
}

Ở đây, các trường hợp không thể xử lý được sẽ được loại bỏ ngay từ đầu. Khi chương trình đi đến phần Console.WriteLine, chúng ta có thể biết rằng order tồn tại và hợp lệ.

Nhờ đó, phần logic chính không cần phải nằm bên trong nhiều tầng if.

Return First và if...else

Return First không có nghĩa là if...else sai hoặc không nên sử dụng. Hai cách đều có thể phù hợp tùy vào trường hợp.

Return First thường phù hợp khi muốn loại bỏ sớm các trường hợp đặc biệt hoặc không hợp lệ, sau đó thực hiện logic chính ở phần còn lại của hàm.

Trong khi đó, if...else có thể phù hợp khi các nhánh điều kiện đều là những trường hợp chính và cần được xử lý như những lựa chọn khác nhau.

Ví dụ 1: Cổ điển if...else(Logic lồng nhau)

Phiên bản PHP:

function send_welcome_email($user) {
    if ($user) {
        echo "Sending welcome email to {$user['email']}";
    } else {
        return;
    }
}

Phiên bản JavaScript:

function sendWelcomeEmail(user) {
    if (user) {
        console.log(`Sending welcome email to ${user.email}`);
    } else {
        return;
    }
}

Trong cả hai trường hợp, logic thực sự được gói gọn bên trong một ifkhối lệnh, điều này có thể trở nên phức tạp khi hàm phát triển.

Ví dụ 2: Điều khoản trả lại sớm / Điều khoản bảo vệ

Phiên bản PHP:

function send_welcome_email($user) {
    if (!$user) {
        return;
    }

    echo "Sending welcome email to {$user['email']}";
}

Phiên bản JavaScript:

function sendWelcomeEmail(user) {
    if (!user) {
        return;
    }

    console.log(`Sending welcome email to ${user.email}`);
}

Cấu trúc này xử lý trường hợp không hợp lệ ngay lập tức, sau đó tiếp tục với logic chính. Nó dễ đọc hơn và yêu cầu ít thụt lề hơn.

Lợi ích của việc sử dụng mệnh đề bảo vệ

  • Giảm độ lồng ghép mã và gánh nặng nhận thức.
  • Giữ cho logic cốt lõi được ưu tiên hiển thị trực quan.
  • Xử lý các trường hợp ngoại lệ sớm và rõ ràng.
  • Giúp việc sửa đổi và mở rộng chức năng trở nên dễ dàng hơn.

Cách tiếp cận này hoạt động tốt trong bất kỳ ngôn ngữ nào , bởi vì đó là một lựa chọn về cấu trúc logic chứ không phải là một đặc điểm của ngôn ngữ.

Ví dụ thực tế: Xác thực yêu cầu

Kiểu lồng nhau cổ điển (PHP)

function process_payment($request) {
    if (isset($request['amount'])) {
        if ($request['amount'] > 0) {
            // process payment
        } else {
            throw new Exception("Amount must be positive");
        }
    } else {
        throw new Exception("Amount is required");
    }
}

Kiểu mệnh đề điều kiện (JavaScript)

function processPayment(request) {
    if (!request.amount) {
        throw new Error("Amount is required");
    }

    if (request.amount <= 0) {
        throw new Error("Amount must be positive");
    }

    // process payment
}

Trong cả hai ví dụ, các đường dẫn không hợp lệ đều thoát ra sớm. Kết quả là đường dẫn gọn gàng hơn, phẳng hơn và dễ theo dõi hơn.

Phần kết luận

Việc sử dụng câu lệnh trả về sớm và câu lệnh điều kiện là một kỹ thuật phổ biến để viết mã tốt hơn. Cho dù bạn đang sử dụng PHP, JavaScript, Python, Go hay Java, ý tưởng đều giống nhau:

Xử lý dữ liệu đầu vào xấu ngay từ đầu, thoát nhanh chóng và giữ cho logic chính luôn gọn gàng và tập trung.

Hãy cân nhắc tránh các cấu trúc if...else lồng nhau quá sâu khi có thể đơn giản hóa hàm bằng các kiểm tra ban đầu. Tuy nhiên, việc sử dụng Early Return hay if...else vẫn phụ thuộc vào logic cụ thể của từng trường hợp.

Nguồn tham khảo:

Bài viết khác

Logging – Monitoring – CI/CD

Logging, Monitoring và CI/CD là gì? Vai trò trong phát triển Backend 1. Tổng quan Khi xây dựng một ứng dụng Backend, viết code và chạy được chương trình mới chỉ là bước đầu. Khi ứng dụng được đưa vào sử dụng, lập trình viên còn cần biết ứng dụng đang hoạt động như thế […]

Docker là gì?

Docker là gì? Hướng dẫn sử dụng Docker trong Backend với Go 1. Docker là gì? Docker là nền tảng hỗ trợ đóng gói và chạy ứng dụng trong các môi trường độc lập gọi là container. Thay vì chỉ chia sẻ mã nguồn, lập trình viên có thể mô tả môi trường chạy ứng […]

Logging / Monitoring / CI/CD

1. Tổng quan: Ba thành phần giải quyết ba vấn đề khác nhau Khi một Backend chạy trên production, việc code hoạt động đúng trên máy local chưa đủ. Hệ thống cần có khả năng ghi nhận sự kiện, phát hiện sự cố và triển khai phiên bản mới một cách an toàn. Ba thành […]

Unit & Integration Testing

1. Unit Testing và Integration Testing là gì? Trong quá trình phát triển phần mềm, viết code để triển khai chức năng mới chỉ là một phần của công việc. Lập trình viên còn cần kiểm tra xem chương trình có hoạt động đúng theo yêu cầu hay không, đồng thời bảo đảm những thay […]

Docker

1. Docker là gì? Docker là nền tảng giúp đóng gói và chạy ứng dụng trong các môi trường được gọi là container. Một ứng dụng Backend thường phụ thuộc vào nhiều thành phần: Ngôn ngữ lập trình và runtime như Go, PHP hoặc Node.js. Thư viện và package. Database như PostgreSQL hoặc MySQL. Cache […]

Message Broker

Message Broker là gì? Vai trò của Message Broker trong Backend 1. Message Broker là gì? Message Broker là phần mềm trung gian cho phép các thành phần trong hệ thống trao đổi thông điệp với nhau mà không cần giao tiếp trực tiếp. Nó tiếp nhận thông điệp từ bên gửi, sau đó định […]

Leave a Reply

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