Software Quality Assurance Phát Triển Phần Mềm Việt Nam Risk Management

[97 điều lập trình viên nên biết – #07] Tái sử dụng code cần thận trọng: Đừng bỏ qua ngữ cảnh

Thứ bảy, 24 Th10 2026 13 phút đọc 7 lượt xem

[97 điều lập trình viên nên biết – #07] Tái sử dụng code cần thận trọng: Đừng bỏ qua ngữ cảnh

Tóm tắt

Tái sử dụng code thường được xem là một phương pháp tốt trong phát triển phần mềm vì giúp giảm trùng lặp và đơn giản hóa việc bảo trì. Tuy nhiên, chia sẻ code giữa những thành phần không liên quan có thể tạo ra các phụ thuộc không cần thiết. Trước khi xây dựng thư viện dùng chung, lập trình viên cần hiểu ngữ cảnh, mối quan hệ giữa các thành phần và khả năng thay đổi của chúng.

Vì sao tái sử dụng code không phải lúc nào cũng tốt?

Trong lập trình, tái sử dụng code (Code Reuse) thường được xem là một dấu hiệu của thiết kế phần mềm tốt.

Thay vì viết đi viết lại cùng một logic, chúng ta có thể tách phần xử lý chung thành hàm, thư viện hoặc component để sử dụng ở nhiều nơi.

Cách tiếp cận này giúp giảm code trùng lặp và có thể đơn giản hóa việc bảo trì. Tuy nhiên, nếu áp dụng mà không xem xét cấu trúc hệ thống, nó cũng có thể gây ra những vấn đề không mong muốn.

Trong cuốn 97 Things Every Programmer Should Know, tác giả Udi Dahan chia sẻ một trải nghiệm từ dự án đầu tiên sau khi tốt nghiệp đại học.

Khi đó, ông rất muốn chứng minh năng lực của mình. Ông dành nhiều thời gian nghiên cứu code hiện có và cố gắng áp dụng những kiến thức đã học vào công việc.

Trong nhiệm vụ đầu tiên, ông bổ sung comment, ghi log và đưa những đoạn code có logic tương tự vào các thư viện dùng chung.

Tuy nhiên, trong buổi code review, ông nhận ra rằng việc thúc đẩy tái sử dụng code không phải lúc nào cũng được đánh giá cao.

Vấn đề không nằm ở bản thân việc tái sử dụng code.

Điều ông đã bỏ qua chính là ngữ cảnh (Context).

Ngữ cảnh quan trọng hơn sự giống nhau của code

Giả sử trong hệ thống có hai thành phần chứa những đoạn code gần như giống hệt nhau.

Thoạt nhìn, việc tách logic trùng lặp thành một hàm chung có vẻ hoàn toàn hợp lý. Chúng ta sẽ giảm được số dòng code và tránh phải duy trì hai phiên bản giống nhau.

Nhưng điều gì xảy ra nếu hai thành phần đó đảm nhiệm những vai trò hoàn toàn khác nhau?

Mặc dù cách xử lý hiện tại giống nhau, trách nhiệm nghiệp vụ và lý do thay đổi của chúng có thể rất khác biệt.

Sự giống nhau đó đôi khi chỉ mang tính tạm thời.

Trước khi được gộp lại, hai thành phần có thể hoạt động độc lập. Việc thay đổi logic ở một nơi không ảnh hưởng đến nơi còn lại.

Tuy nhiên, khi đưa logic vào thư viện dùng chung, cả hai bắt đầu phụ thuộc vào cùng một phần triển khai.

Udi Dahan sử dụng một hình ảnh so sánh rất thú vị: giống như dùng chung một sợi dây giày để buộc cả hai chiếc giày.

Hai thành phần vốn độc lập giờ đây bị liên kết với nhau.

Chỉ một thay đổi nhỏ trong thư viện cũng có thể ảnh hưởng đến nhiều nơi sử dụng.

Giảm số dòng code trùng lặp không đồng nghĩa với giảm độ phức tạp của hệ thống. Đôi khi, chúng ta chỉ chuyển sự phức tạp sang các mối quan hệ phụ thuộc.

Tại sao chia sẻ code có thể làm tăng chi phí bảo trì?

Hãy tưởng tượng hai thành phần trong hệ thống cùng chứa bốn dòng code có logic tương tự.

Ban đầu, chúng hoàn toàn độc lập. Nếu yêu cầu nghiệp vụ của một thành phần thay đổi, lập trình viên có thể chỉnh sửa mà không ảnh hưởng đến thành phần còn lại.

Sau khi tách bốn dòng code đó thành một thư viện chung, cả hai đều phụ thuộc vào thư viện này.

Giờ đây, mỗi lần thay đổi logic dùng chung, nhóm phát triển có thể cần:

  • Kiểm tra ảnh hưởng đến những thành phần đang sử dụng thư viện.
  • Xác nhận các chức năng liên quan vẫn hoạt động chính xác.
  • Thực hiện thêm các bài kiểm thử để tránh phát sinh lỗi ngoài ý muốn.

Mặc dù tổng số dòng code ít hơn, chi phí bảo trì có thể lại tăng lên.

Điều này cho thấy sự khác biệt giữa code trùng lặp (Duplication) và sự phụ thuộc giữa các thành phần (Coupling).

Code trùng lặp nghĩa là có những logic tương tự xuất hiện ở nhiều nơi. Coupling thể hiện mức độ các thành phần phụ thuộc vào nhau.

Việc loại bỏ code trùng lặp thường đồng thời tạo ra một mối quan hệ phụ thuộc. Mối quan hệ đó có thực sự mang lại lợi ích hay không phụ thuộc vào ngữ cảnh.

Nếu các thành phần nằm trong cùng một phạm vi nhỏ và có liên quan chặt chẽ, lợi ích của việc chia sẻ code có thể lớn hơn rủi ro.

Ngược lại, khi thư viện được sử dụng rộng rãi bởi những thành phần có trách nhiệm khác nhau, một thay đổi nhỏ có thể kéo theo nhiều công việc kiểm thử và điều chỉnh.

Khi nào nên tái sử dụng code?

Bài học này không có nghĩa rằng chúng ta nên tránh tái sử dụng code.

Tái sử dụng vẫn là một phương pháp có giá trị khi các thành phần có cùng ngữ cảnh và thực sự cần chia sẻ logic.

Trước khi tạo thư viện dùng chung, lập trình viên nên xem xét bốn câu hỏi:

  1. Các thành phần có cùng trách nhiệm không? Code giống nhau chưa chắc đồng nghĩa với vai trò giống nhau.
  2. Chúng có thay đổi vì cùng một lý do không? Nếu chịu ảnh hưởng bởi những yêu cầu nghiệp vụ khác nhau, việc giữ độc lập có thể phù hợp hơn.
  3. Phạm vi phụ thuộc lớn đến đâu? Chia sẻ logic trong một module nhỏ khác với việc tạo sự phụ thuộc giữa nhiều khu vực độc lập của hệ thống.
  4. Việc tái sử dụng có thực sự giúp bảo trì dễ hơn không? Giảm vài dòng code chưa chắc đáng để đánh đổi bằng chi phí kiểm thử và phối hợp cao hơn.

Bảng dưới đây tóm tắt các tình huống thường gặp.

Tình huốngHướng cân nhắc
Code giống nhau và có cùng trách nhiệmCó thể tách thành logic dùng chung
Code giống nhau nhưng phục vụ nghiệp vụ khác nhauCân nhắc giữ độc lập
Các thành phần liên quan trong một modulePhụ thuộc thường dễ kiểm soát hơn
Các thành phần thuộc nhiều khu vực độc lậpCần đánh giá kỹ ảnh hưởng khi thay đổi

Điều quan trọng không chỉ là hai đoạn code trông có giống nhau hay không.

Mà là chúng có thực sự nên được liên kết với nhau về mặt thiết kế và nghiệp vụ hay không.

Áp dụng bài học vào phát triển phần mềm

Trong các dự án thực tế, việc loại bỏ code trùng lặp thường được xem là một phần của quá trình cải thiện chất lượng phần mềm.

Tuy nhiên, refactoring không nên chỉ tập trung vào việc giảm số dòng code.

Lập trình viên còn cần hiểu ranh giới giữa các thành phần, trách nhiệm nghiệp vụ và những phụ thuộc mới có thể phát sinh.

Đối với các nhóm phát triển phần mềm như VAON, đây là một nguyên tắc đáng cân nhắc khi đánh giá kiến trúc hoặc thực hiện refactoring.

Trước khi xây dựng một thư viện hoặc utility dùng chung, cần xem xét liệu các thành phần liên quan có thực sự thuộc cùng một ngữ cảnh hay không.

Một thư viện được thiết kế phù hợp có thể giúp bảo trì dễ dàng hơn. Ngược lại, một thư viện dùng chung không cần thiết có thể làm tăng chi phí thay đổi của toàn hệ thống.

Kết luận: Hãy thận trọng khi chia sẻ code

Tái sử dụng code là một phương pháp tốt, nhưng không phải lúc nào cũng là lựa chọn phù hợp nhất.

Hai đoạn code có thể giống nhau ở thời điểm hiện tại, nhưng đảm nhiệm những vai trò khác nhau và sẽ thay đổi theo những hướng khác nhau trong tương lai.

Đưa chúng vào thư viện dùng chung giúp giảm trùng lặp, nhưng đồng thời cũng tạo ra sự phụ thuộc.

Vì vậy, mục tiêu của thiết kế phần mềm tốt không phải giảm số dòng code bằng mọi giá, mà là xây dựng hệ thống dễ hiểu, dễ thay đổi và dễ bảo trì.

Trước khi chia sẻ code, hãy hiểu rõ ngữ cảnh. Tái sử dụng nên giúp đơn giản hóa hệ thống, không phải khiến những thành phần độc lập trở nên phụ thuộc không cần thiết.

 

Về series "97 điều lập trình viên nên biết"

97 điều lập trình viên nên biết là series chia sẻ những bài học thực tiễn về thiết kế phần mềm, tư duy giải quyết vấn đề và phát triển nghề nghiệp của lập trình viên.

Bài viết được biên soạn dựa trên nội dung số #07 –「共有は慎重に」 (Chia sẻ cần thận trọng), do Udi Dahan viết, trong cuốn 『プログラマが知るべき97のこと』.

Nội dung giữ nguyên thông điệp cốt lõi của tác giả, đồng thời được tổ chức lại để phù hợp với độc giả blog kỹ thuật.

Tìm hiểu thêm về VAON và các dịch vụ phát triển phần mềm.

Sẵn sàng chuyển đổi doanh nghiệp?

Hãy thảo luận về cách chúng tôi có thể giúp bạn tận dụng AI và chuyển đổi số.

Câu hỏi thường gặp

Code trùng lặp có phải lúc nào cũng xấu không?
Không. Mặc dù code trùng lặp có thể làm tăng chi phí bảo trì, việc giữ những đoạn code tương tự ở các thành phần độc lập đôi khi lại hợp lý. Đặc biệt khi chúng phục vụ những mục đích khác nhau hoặc có khả năng thay đổi theo những hướng khác nhau.
Khi nào nên tạo thư viện dùng chung?
Thư viện dùng chung phù hợp khi nhiều thành phần thực sự có cùng trách nhiệm và có khả năng thay đổi cùng nhau. Trước khi tạo thư viện, cần đánh giá phạm vi phụ thuộc và lợi ích bảo trì mà việc tái sử dụng mang lại.
Rủi ro lớn nhất của việc tái sử dụng code quá mức là gì?
Rủi ro chính là tạo ra những mối quan hệ phụ thuộc không cần thiết. Một thay đổi trong thư viện dùng chung có thể ảnh hưởng đến nhiều thành phần, làm tăng công việc kiểm thử và khiến hệ thống khó bảo trì hơn.
Có nên ưu tiên giảm số dòng code không?
Không nhất thiết. Giảm số dòng code chỉ có giá trị khi cải thiện khả năng hiểu và bảo trì hệ thống. Một codebase lớn hơn đôi chút nhưng có các thành phần độc lập đôi khi dễ thay đổi hơn một codebase nhỏ với quá nhiều phụ thuộc.

Chia sẻ bài viết