Bí Kíp Viết Hàm "Sạch Sẽ" (Clean Function) Ai Đọc Cũng Hiểu: 3 Nguyên Tắc Vàng Giúp Bạn "Nâng Tầm" Code!
Lê Lân
1
3 Nguyên Tắc Vàng Để Viết Hàm Trong Lập Trình Hướng Đối Tượng Dễ Hiểu và Dễ Bảo Trì
Mở Đầu
Trong phát triển phần mềm, độ phức tạp của mã nguồn luôn là thách thức lớn đối với các lập trình viên và đội ngũ phát triển. Việc duy trì, mở rộng và sửa lỗi trong mã phức tạp sẽ làm tốn rất nhiều thời gian và nguồn lực.
Ở bài viết trước, tôi có chia sẻ về những vấn đề liên quan đến độ phức tạp của phần mềm và một nguyên tắc tôi luôn tuân thủ đó là: "Mỗi đoạn code tôi can thiệp vào nên trở nên dễ hiểu và dễ bảo trì hơn trước đó, trừ khi tôi đang viết mới hoàn toàn." Trong lập trình hướng đối tượng (OOP), hàm (function) là đơn vị cơ bản nhất cấu thành nên các lớp (class). Một mã nguồn dù lớp có thể rất lớn, trên 1.000 dòng, thì việc giữ cho các hàm nhỏ gọn, rõ ràng sẽ giúp toàn bộ mã dễ làm việc, đặc biệt trong việc cải tiến hoặc tái cấu trúc.
Bài viết này sẽ giúp bạn hiểu và áp dụng 3 nguyên tắc quan trọng trong việc viết hàm: Giữ hàm ngắn, chỉ có một lý do thay đổi và duy trì mức độ trừu tượng nhất quán.
1. Giữ Hàm Ngắn (Số Dòng Mã)
1.1 Tại Sao Cần Giữ Hàm Ngắn?
Ở Ruby, việc giữ hàm ngắn là phong cách phổ biến. Hàm ngắn giúp:
Tăng độ readability (độ dễ đọc)
Giảm thiểu lỗi phát sinh do logic phức tạp
Dễ dàng bảo trì và cập nhật
Khi làm leader, tôi thường đặt giới hạn mềm cho hàm từ 10-12 dòng, tuy nhiên tùy vào trình độ team, 20 dòng là mức cân bằng hợp lý để vừa ngắn gọn, vừa không làm chậm tiến độ.
1.2 Ví Dụ Trước Và Sau
Trước
Sau
Một hàm dài lồng nhiều hành vi, khó quét và sửa lỗi
Các hàm nhỏ rõ ràng, mỗi hàm đảm nhiệm một chức năng riêng
ruby<br />def process_payment(user, order_id)<br /> order = Order.find(order_id)<br /> if charge_order(user, order)<br /> handle_successful_payment(user, order)<br /> else<br /> handle_failed_payment(user, order)<br /> end<br />end<br /># Các hàm phụ đảm nhiệm từng phần riêng biệt<br />
1.3 Ý Nghĩa Của Việc Tách Hàm
Giúp giảm độ phức tạp nhận thức khi đọc từng phần nhỏ
Hỗ trợ tái sử dụng code trong nhiều ngữ cảnh
2. Một Hàm Chỉ Có Một Lý Do Để Thay Đổi
2.1 Nguyên Tắc Đơn Trách Nhiệm (Single Responsibility Principle)
Một hàm nên chịu trách nhiệm cho một mục đích duy nhất. Khi hàm làm quá nhiều việc, chúng ta sẽ gặp phải:
Khó sửa đổi vì liên quan nhiều phần
Nguy cơ lỗi cao khi thay đổi một phần dẫn đến hỏng các phần còn lại
2.2 Cách Kiểm Tra Hàm
Hỏi bản thân: “Hàm này làm gì?”
Nếu câu trả lời chứa từ “và” nghĩa là hàm đang đảm nhiệm nhiều nhiệm vụ
Ví dụ: “Nó thực hiện thanh toán và gửi email xác nhận” → nên tách riêng hai nhiệm vụ
2.3 Áp Dụng Trong Ví Dụ Process Payment
Ban đầu process_payment thực hiện thanh toán, cập nhật trạng thái, ghi log, gửi thông báo, xử lý thưởng người giới thiệu, thực thi job nền, v.v.
Sau khi refactor:
charge_order chỉ lo xử lý thanh toán
handle_successful_payment chỉ quản lý các tác vụ sau thanh toán thành công
Và các hàm nhỏ khác tập trung riêng từng nhiệm vụ
Việc tách rõ ràng như thế giúp khi thay đổi một phần (ví dụ thay đổi cách gửi mail) bạn không cần phải lo lắng ảnh hưởng tới luồng thanh toán.
3. Mức Độ Trừu Tượng Nhất Quán Trong Hàm
3.1 Tại Sao Quan Trọng?
Một hàm mà pha trộn nhiều cấp độ trừu tượng — ví dụ vừa truy cập database (cấp thấp), gọi API bên ngoài (hạ tầng), áp dụng luật nghiệp vụ (trung bình), vừa gửi email hay chạy job nền (I/O) — sẽ gây khó khăn khi đọc hiểu và bảo trì.
3.2 Cách Giữ Mức Độ Trừu Tượng Đồng Nhất
Hàm chính là nơi phối hợp các bước lớn (orchestration level)
Hàm phụ tương ứng chỉ làm việc ở một mức trừu tượng ổn định, dễ theo dõi
3.3 Trong Ví Dụ Process Payment
Hàm process_payment chỉ nhập vai điều phối, kiểm soát luồng xử lý
Các hàm như charge_order, log_payment_success tách ra, giữ bản chất tác vụ cụ thể, ít thay đổi mức độ trừu tượng
Mức độ trừu tượng nhất quán giúp giảm bớt context-switching não khi đọc code, từ đó tăng tốc độ hiểu và phát triển.
Kết Luận
Viết hàm sạch không chỉ giúp mã dễ đọc, mà còn giảm thiểu lỗi và tăng tính mở rộng trong phát triển phần mềm. Ba nguyên tắc sau sẽ là kim chỉ nam cho bạn:
Giữ hàm đủ ngắn - đến mức dễ nắm bắt, thường là khoảng 20 dòng hoặc ít hơn
Một hàm - một nhiệm vụ duy nhất - tránh trộn lẫn nhiều trách nhiệm trong cùng một hàm
Giữ mức độ trừu tượng đồng nhất - hàm không nên pha trộn nhiều cấp độ logic
Hãy bắt đầu thực hành ngay hôm nay để mã nguồn của bạn ngày càng trở nên tinh gọn và dễ bảo trì hơn. Đừng quên chia sẻ thêm những nguyên tắc hay bạn đang áp dụng nhé!
Tham Khảo
Martin, Robert C. “Clean Code: A Handbook of Agile Software Craftsmanship”, Prentice Hall, 2008
Fowler, Martin. “Refactoring: Improving the Design of Existing Code”, Addison-Wesley, 2018