Think Like a Programmer — Chương 8: Solving Problems with Code Reuse (Tái sử dụng mã nguồn)

Phong

Mở đầu

Chào mấy bạn, mình lại tiếp tục series đọc sách "Think Like a Programmer" của tác giả V. Anton Spraul rồi đây. Hồi đầu mình cũng hơi ngờ ngợ khi cầm cuốn này lên, tại tựa nhìn "chiến" quá — nghĩ kiểu gì mà "think like a programmer" dạy tư duy lập trình viên. Nhưng đọc rồi mới thấy cuốn này đúng kiểu "gãi đúng chỗ ngứa" cho dân dev tụi mình, nhất là mấy bạn mới đi làm hay tự học.

Tác giả V. Anton Spraul làm giáo sư dạy lập trình ở đại học Mỹ, ổng viết sách rất thực tế, không lòng vòng. Mỗi chương ổng chọn một kỹ năng cốt lõi và phân tích nó qua nhiều góc nhìn, kèm bài tập có lời giải. Đọc một cuốn sách kỹ thuật mà mình thấy thư giãn, không bị ngợp — đó là cái hay của ổng.

Ảnh: Lukas Blazek — Pexels

Solving Problems with Code Reuse — Tái sử dụng mã nguồn

Chương 8 này có cái tựa rất đời: "Solving Problems with Code Reuse" — giải quyết vấn đề bằng cách tái sử dụng code. Nghe thì tưởng đơn giản, ai mà chả biết copy-paste hay dùng thư viện, nhưng Spraul đi sâu hơn nhiều. Ổng chỉ ra rằng tái sử dụng code không chỉ là kỹ thuật — nó là tư duy.

Ba cấp độ tái sử dụng

Spraul chia việc tái sử dụng code thành ba cấp độ:

1. Hàm (functions): Cấp độ cơ bản nhất — viết một hàm để xử lý một tác vụ và dùng nó nhiều lần trong chương trình. Nhưng ổng cũng nhấn mạnh: đừng vội vã tạo hàm ngay từ đầu. Lập trình viên thường có thói quen refactor quá sớm, tạo ra các hàm "trừu tượng hóa sai" chỉ vì nghĩ rằng sẽ cần dùng lại. Lời khuyên của ổng là: "Write the code first, then look for reuse opportunities" — viết code trước, sau đó mới tìm cơ hội tái sử dụng.

2. Thư viện và framework (libraries & frameworks): Đây là nơi mà nhiều lập trình viên mắc sai lầm nhất. Ai cũng thích dùng thư viện cho nhanh, nhưng mấy bạn có hiểu rõ cái thư viện đó đang làm gì không? Spraul đưa ra một ví dụ rất hay trong chương: khi bạn dùng một hàm sort có sẵn, bạn cần biết độ phức tạp của nó là O(n log n) hay O(n²), cần biết nó có stable sort không, có dùng thêm bộ nhớ không. Nếu không hiểu, code của bạn có thể chạy rất chậm mà không biết tại sao.

3. Design patterns: Cấp độ cao nhất — các mẫu thiết kế đã được chứng minh qua thời gian. Spraul không liệt kê 23 patterns như GoF (Gang of Four), mà ổng tập trung vào cách nhận ra vấn đề đang thuộc một "khuôn mẫu" nào đó. Khi bạn nhìn thấy một bài toán và nghĩ "à, cái này giống bài toán X", đó là lúc tư duy tái sử dụng thực sự hoạt động.

Ảnh: ThisIsEngineering — Pexels

Vấn đề nan giải: "Not invented here" vs. "Copy-paste programming"

Spraul dành hẳn một phần để bàn về sự cân bằng giữa hai thái cực:

  • Not Invented Here (NIH) Syndrome: Thích tự viết hết, không tin dùng code của người khác. Hệ quả: mất thời gian, code dễ lỗi vì chưa được kiểm nghiệm rộng rãi.
  • Copy-paste programming: Dùng code mà không hiểu. Hệ quả: bug tiềm ẩn, không biết cách fix khi thư viện thay đổi, gặp lỗi edge case là tê liệt.

Cái hay của chương này là Spraul không bảo "hãy tái sử dụng" một cách khiên cưỡng, mà ổng đưa ra cả một quy trình ra quyết định để biết khi nào nên dùng lại và khi nào nên tự viết. Nghe thì đơn giản nhưng mình thấy ít sách nào dạy kỹ như vậy.

Đọc code người khác — một kỹ năng sống còn

Một điểm rất hay nữa là Spraul nói về việc đọc và hiểu code trước khi reuse. Đây là kỹ năng mà trường lớp không dạy, nhưng ngoài đời làm việc thì nó quan trọng hơn viết code gấp nhiều lần. Ổng đưa ra chiến thuật đọc code: bắt đầu từ hàm main / entry point, theo dõi luồng dữ liệu, không cần hiểu từng dòng — giống như đọc bản đồ thành phố trước khi lái xe vào từng con hẻm.

Cảm nhận của mình

Cá nhân mình thấy chương 8 này như một "cú đập vai" tỉnh ngộ. Hồi mới đi làm, mình thuộc dạng NIH nặng — cái gì cũng muốn tự viết cho oách, thư viện nào cũng ngờ vực. Kết quả là dự án đầu tiên mình chậm gấp 3 lần đồng nghiệp, mà code còn đầy bug vì tự chế thuật toán lung tung.

Càng về sau, mình càng hiểu rằng lập trình giỏi không phải là viết được nhiều code, mà là biết code nào không cần viết. Kinh nghiệm thực tế cho thấy: một lập trình viên senior khác một lập trình viên junior ở chỗ biết cái gì "đã có người giải quyết rồi" và tái sử dụng nó một cách thông minh.

Một điểm mình tâm đắc là cái khái niệm "black box" vs "glass box" — dùng code của người khác như một hộp đen thì nguy hiểm lắm. Cần phải hiểu đủ để biết giới hạn của nó, ít nhất là biết nó không làm được gì, chứ không chỉ biết nó làm được gì. Cái này đúng với mọi cấp độ: từ hàm con cho đến cả một framework lớn.

Ví dụ điển hình: hồi mình dùng ORM mà không hiểu cơ chế lazy loading — kết quả là câu query "đơn giản" biến thành N+1 query, kéo sập cả database staging. Nếu hiểu cái ORM đó hoạt động thế nào, mình đã biết dùng select_related hoặc tối ưu ngay từ đầu. Đó chính là cái Spraul muốn nói: hiểu trước khi dùng.

Ảnh: Brett Jordan — Pexels

Kết

Chương 8 là một chương rất thực tế — giống như cầm tay chỉ việc cho dân dev tụi mình. Không có lý thuyết cao siêu, mà là những bài học xương máu từ thực tế lập trình hàng ngày. Tái sử dụng code là con dao hai lưỡi: dùng đúng thì tiết kiệm thời gian, dùng sai thì rước họa vào thân.

Bài học lớn nhất mình rút ra: Đừng tái sử dụng code một cách mù quáng, cũng đừng tự viết lại từ đầu một cách bảo thủ. Hãy là người dùng code thông thái — biết cái gì đang dùng, hiểu giới hạn của nó, và luôn sẵn sàng mở hộp đen ra khi cần.

Cảm ơn mấy bạn đã đọc tới đây. Hẹn gặp lại ở chương tiếp theo của series "Think Like a Programmer". Nếu mấy bạn có câu chuyện gì về code reuse — từ "cứu cánh" đến "thảm họa" — thì comment bên dưới cho mình biết với nha!