0

God Function: "Ác mộng" bảo trì code của dân Dev

Vẫn là câu chuyện muôn thuở - God Function

Đợt rồi cu em team mình gặp một bug khá khó chịu. Không phải bug kiểu crash ngay, mà là bug logic – chỉ sai trong một vài trường hợp đặc biệt.

Thế là bắt đầu hành trình quen thuộc: mò lại code.

Mở code ra, nhìn vào cái hàm xử lý chính… và mình chết lặng 😨. Trước mắt là một hàm xử lý chính dài gần 1.000 dòng. Bên trong đó là một "nồi lẩu" thực thụ: từ check validation, query DB, tính toán nghiệp vụ phức tạp, mapping dữ liệu cho đến logging... Tất cả trộn lẫn vào nhau với những cấu trúc if-else, for lồng nhau tầng tầng lớp lớp 😀.

Nhìn cậu em loay hoay đặt breakpoint rồi "step over" từng dòng một cách mệt mỏi, mình nhận ra: Vấn đề không nằm ở cái bug, mà nằm ở cách chúng ta tổ chức tư duy trong code.

Vấn đề không phải là bug – mà là cách chúng ta viết code

Bug thì project nào cũng có. Nhưng cái khiến việc fix bug trở thành ác mộng chính là cách code được tổ chức.
Có thể nhiều anh em chưa quen với việc chia nhỏ hàm, mỗi hàm làm một việc. Nhưng chí ít, hãy cố gắng chia logic ra, để khi debug còn biết:

Đoạn này xử lý việc gì?

Nhưng thú thật qua quá trình mình đi làm thì mình thấy việc chia nhỏ hàm... những người áp dụng được rất ít. Và chủ yếu anh em Fresher hay Junior hay dính lỗi này.
Và mình nhận ra một điều:

  • Vấn đề không nằm ở việc anh em không biết chia hàm
  • Vấn đề nằm ở tư duy viết code

Rất nhiều người code theo kiểu:

  • Nghĩ tới đâu → viết tới đó.
  • Áp lực Deadline => Chạy được đã, maintain là câu chuyện tương lai. (Cái này thì không chối được này 😀)
  • Flow đang liền mạch thì nhét hết vào một hàm cho “dễ theo dõi”

Nhưng anh em ạ:

“Dễ theo dõi” lúc viết ≠ “dễ đọc” lúc debug. Cái giá phải trả cho việc "tiết kiệm" vài phút chia hàm chính là hàng giờ (hoặc hàng ngày) vật lộn với nó trong tương lai

Một hàm dài = một quả bom nổ chậm

Ngày xưa chính mình cũng từng code những hàm dài vài nghìn dòng, và cảm nhận rất rõ:

  • Khi debug một hàm quá dài thì rất khó nắm được hết flow
  • Một phần nhỏ muốn test lại là phải đi từ đầu
  • Debug cực mệt

Và kết quả là: Mỗi lần đụng bug là một lần “tra tấn tinh thần”.

Hãy code cho "Người đến sau"
Chia nhỏ hàm không phải để làm màu hay cho code đẹp. Mục đích cốt lõi là tăng khả năng đọc hiểu (Readability) và khả năng bảo trì (Maintainability).

Ví dụ:

public async Task ProcessOrderAsync(OrderRequest request) {
    ValidateRequest(request);
    var order = MapToEntity(request);
    await _repository.SaveAsync(order);
    await _emailService.SendConfirmationAsync(order.UserEmail);
}

Nhìn vào ví dụ trên là anh em hiểu hàm trên hàm những cái gì ngay đúng không ? 😄

Lời kết

Bài viết này không nhằm chỉ trích ai cả. Mình tin là rất nhiều người trong chúng ta từng (hoặc đang) code những hàm như vậy, kể cả mình trong quá khứ. Bug là thứ không thể tránh khỏi, nhưng cách chúng ta đối diện với nó như thế nào phụ thuộc vào việc chúng ta đặt bút viết code hôm nay ra sao.

Nhưng nếu có thể thay đổi một chút:

  • Nghĩ thêm vài phút trước khi viết
  • Tách logic ra thành các hàm nhỏ
  • Đặt tên hàm có ý nghĩa hơn

Thì:
👉 Bug sẽ dễ fix hơn
👉 Code review đỡ đau đầu hơn
👉 Đồng nghiệp của chúng ta hay chính chúng ta trong tương lai sẽ biết ơn bản thân mình của hôm nay

Anh em đi qua cho mình xin 1 cảm nhận chia sẻ của anh em nhé, anh em xử lý thế nào khi gặp vấn đề trên, hay bài viết của mình còn đoạn nào chưa chuẩn. Rất cảm ơn anh em đã ngồi lại và đọc bài viết của mình. Cảm ơn anh em rất nhiều.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí