Return First – Tư duy xử lý điều kiện trong code

Khi bắt đầu làm việc với code thực tế, chúng ta sẽ thường gặp những function chứa rất nhiều điều kiện. Ban đầu, việc sử dụng if/else để xử lý từng trường hợp là hoàn toàn bình thường. Tuy nhiên, khi logic ngày càng phức tạp, các điều kiện bắt đầu lồng vào nhau và khiến code khó đọc, khó hiểu và khó bảo trì.

Một cách tiếp cận thường được sử dụng để giải quyết vấn đề này là Return First.

Return First có thể hiểu đơn giản là:

Xử lý những trường hợp không thể tiếp tục trước và return ngay, thay vì để chúng bao quanh toàn bộ logic chính.

Trong tài liệu lập trình, cách tiếp cận này thường được gọi gần với Early Return hoặc được triển khai thông qua Guard Clause.

1. Return First là gì?

ví dụ đoạn code đơn giản:

if (user != null) {
    if (user.isActive()) {
        if (user.hasPermission()) {
            process(user);
        }
    }
}
code trên nhìn sơ qua không có gì sai hay lỗi nhưng để biết lúc nào process() được thực thi?? chúng cần đi qua các
tầng if để có thể thực thi được.

Có thể viết lại:

if (user == null) return;
if (!user.isActive()) return;
if (!user.hasPermission()) return;

process(user);

Ở đây, những trường hợp không thể xử lý được loại bỏ ngay từ đầu.

Không có user → dừng.

User không active → dừng.

Không có quyền → dừng.

Nếu tất cả đều hợp lệ → thực hiện logic chính.

Đó chính là tư duy của Return First.

2. Tại sao cần Return First?

Vấn đề lớn nhất mà Return First giải quyết là nested condition.

Ví dụ:

if (conditionA) {
    if (conditionB) {
        if (conditionC) {
            if (conditionD) {
                doSomething();
            }
        }
    }
}

Khi số lượng điều kiện tăng lên, code sẽ ngày càng bị đẩy sâu vào bên trong.

Người đọc phải liên tục theo dõi:

  • Điều kiện bên ngoài có đúng không?
  • Nếu đúng thì đi vào đâu?
  • Điều kiện tiếp theo là gì?
  • Có điều kiện nào phủ định điều kiện trước không?

Trong khi đó, Return First đưa các trường hợp không hợp lệ ra ngoài:

if (!conditionA) return;
if (!conditionB) return;
if (!conditionC) return;
if (!conditionD) return;

doSomething();

Code trở nên phẳng hơn và logic chính dễ nhìn thấy hơn.

3. Ý tưởng cốt lõi của Return First

Return First không đơn giản chỉ là “đặt return lên đầu function”.

Điều quan trọng là cách chúng ta tổ chức flow của function.

Một function thường có thể được nhìn theo cấu trúc:

Kiểm tra điều kiện
       ↓
Có vấn đề?
   ↓       ↓
 Có      Không
 ↓         ↓
Return   Logic chính

Thay vì để logic chính nằm bên trong rất nhiều điều kiện, chúng ta loại bỏ những trường hợp không thể tiếp tục trước.

Ví dụ:

function processOrder(order) {

    if (order == null) return;
    if (order.getItems().isEmpty()) return;
    if (!order.isValid()) return;

    // Logic chính
    calculatePrice(order);
    saveOrder(order);
}

Nhìn vào function, chúng ta có thể nhanh chóng hiểu:

  1. Không có order → không xử lý.
  2. Không có sản phẩm → không xử lý.
  3. Order không hợp lệ → không xử lý.
  4. Nếu vượt qua tất cả → xử lý order.

Đây là một flow rất rõ ràng.

4. Return First và Early Return

Hai khái niệm này rất gần nhau.

Early Return là cách gọi phổ biến hơn trong cộng đồng lập trình, dùng để mô tả việc function kết thúc sớm khi đã biết không cần xử lý tiếp.

Ví dụ:

if (user == null) return;

Function không cần chạy phần code phía sau nữa nên kết thúc ngay.

“Return First” có thể được hiểu như một cách diễn đạt về tư duy:

Kiểm tra những trường hợp cần loại bỏ trước, return ngay, rồi mới xử lý trường hợp bình thường.

Vì vậy, nếu gặp thuật ngữ Return First, có thể liên hệ trực tiếp đến:

Return First
     ↓
Early Return
     ↓
Guard Clause

Tuy nhiên, cần lưu ý rằng Return First không phải tên của một nguyên tắc thiết kế chính thức như SOLID. Đây thường là cách diễn đạt hoặc coding practice liên quan đến Early Return/Guard Clause.

5. Return First và Guard Clause

Một khái niệm rất quan trọng khi tìm hiểu Return First là Guard Clause.

Guard Clause là một điều kiện dùng để kiểm tra xem function có đủ điều kiện tiếp tục hay không.

Ví dụ:

if (user == null) return;

Đây chính là một guard clause.

Một function có thể có nhiều guard clause:

if (user == null) return;
if (!user.isActive()) return;
if (!user.hasPermission()) return;

Sau khi vượt qua tất cả guard clause, function mới thực hiện logic chính.

Có thể hình dung:

             Function
                │
        ┌───────┴───────┐
        │               │
     Invalid          Valid
        │               │
      Return        Continue
                        │
                   Main Logic

Guard Clause giúp chúng ta xử lý các trường hợp đặc biệt ngay từ đầu thay vì để chúng bao quanh logic chính.

6. Happy Path là gì?

Trong một function, Happy Path là flow chính xảy ra khi mọi điều kiện đều hợp lệ.

Ví dụ:

if (user == null) return;
if (!user.isActive()) return;
if (!user.hasPermission()) return;

process(user);

Ba dòng đầu xử lý những trường hợp không thể tiếp tục.

Dòng cuối:

process(user);

chính là happy path.

Một ưu điểm của Return First là nó giúp đưa happy path ra ngoài cùng, thay vì chôn nó bên trong nhiều tầng điều kiện.

Kết luận

Return First có thể được hiểu là cách tổ chức function theo hướng xử lý các trường hợp không thể tiếp tục trước và thoát khỏi function ngay, thay vì để toàn bộ logic chính nằm trong các điều kiện lồng nhau.

Bài viết khác

Series 7 — Web Quality – Engineering :Testing – Unit Testing, Integration Testing, Web Performance – Core Web Vitals, Code Splitting, Lazy Loading

Series 7 — Web Quality – Engineering Bài 3: Testing – Unit Testing, Integration Testing và End-to-End Testing trong ứng dụng web 1. Vì sao ứng dụng web cần Testing? Trong quá trình phát triển Frontend, chúng ta thường kiểm tra ứng dụng bằng cách chạy website trên trình duyệt, nhấn vào các nút, nhập […]

Series 7 — Web Quality – Engineering : Authentication & Authorization

Series 7 — Web Quality – Engineering Bài 1: Authentication & Authorization – Xác thực và phân quyền trong ứng dụng web 1. Mở đầu Khi xây dựng một ứng dụng web có chức năng đăng nhập, chúng ta thường nghĩ rằng chỉ cần tạo biểu mẫu nhập email, mật khẩu và kiểm tra thông […]

Series 6 – Next.js Advanced – Production: Next.js Build & Deployment

Series 6 – Next.js Advanced & Production Bài 5: Next.js Build & Deployment – Từ mã nguồn đến môi trường Production 1. Mở đầu Trong quá trình phát triển một ứng dụng web, việc chạy thành công trên máy tính cá nhân chưa có nghĩa là ứng dụng đã sẵn sàng để đưa đến người […]

Series 6 – Next.js Advanced – Production: Next.js Internationalized Routing Next.js Static Export

Series 6 – Next.js Advanced & Production   Bài 3: Next.js Internationalized Routing – Tổ chức URL cho website đa ngôn ngữ 1. Mở đầu Sau khi xây dựng cơ chế dịch nội dung và định dạng theo locale, ứng dụng cần một cách để người dùng truy cập đúng phiên bản ngôn ngữ. Ví […]

Series 6 – Next.js Advanced & Production: Metadata & SEO, Internationalization (i18n) & Localization (l10n)

Series 6 – Next.js Advanced & Production Bài 1: Metadata & SEO trong Next.js – Tối ưu thông tin và khả năng hiển thị trên công cụ tìm kiếm 1. Mở đầu Khi xây dựng một website, việc hoàn thiện giao diện và chức năng mới chỉ là một phần của quá trình phát triển. […]

Series 5 – Next.js Fundamentals: CSR, SSR, SSG, ISR và cách lựa chọn

Series 5 – Next.js Fundamentals   Bài 7 : CSR, SSR, SSG và ISR – Các chiến lược Rendering trong Next.js 1. Mở đầu Khi xây dựng một website bằng React, chúng ta thường tập trung vào việc tạo component, quản lý state và hiển thị giao diện trên trình duyệt. Tuy nhiên, khi ứng dụng […]

Leave a Reply

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