Vận dụng "Cái chung, cái riêng" trong quy trình phát triển và triển khai phần mềm

Hẳn chúng ta còn nhớ, khi chúng ta mới lập trình, chúng ta chưa làm mọi thứ theo cách riêng của chúng ta. Các developer thường xây dựng các hàm riêng mà không "buồn" kiểm tra xem hàm đó đã có trong thư viện chung hay chưa, hoặc đã có ai đó đã viết hàm đó hay chưa. Kết quả là sau khi dự án kết thúc, có rất nhiều đoạn code trùng lặp nhau về mặt chức năng mà thay vào đó có thể tách ra làm các hàm chung. Điều này làm cho toàn bộ mã nguồn dự án phình lên, khó kiểm soát và hình thành nên cái gọi là “rác mã nguồn”…
 
Qua một thời gian khi chúng ta có kinh nghiệm, chúng ta thường tư duy về “cái chung” nhiều hơn. Chúng ta sẽ thiết kế làm sao để các module có độ dính kết chặt chẽ cao (cohesion), có ảnh hưởng đến nhau ít nhất có thể (loose coupling) và chia sẻ tối đa phần chung (các thư viện, các tài nguyên ảnh…).
Một kiến trúc sư sẽ cố gắng đưa ra một tầm nhìn xa hơn, cố gắng đưa ra “cái chung” là các thư viện đã dùng ở các dự án cũ, hoặc sau khi phân tích yêu cầu bài toán sẽ quyết định tách ra một module chung để từ đó chia sẻ cho các module khác. Rõ ràng “cái chung” có nhiều ưu điểm hơn “cái riêng”. Đây chính là xu hướng mà các dự án nguồn mở luôn hướng tới. “Cái chung”, “cái riêng” cũng được đưa vào lập trình hướng đối tượng trong đó Interface, Abstract Class là các “cái chung”, các lớp kế thừa nó là “cái riêng”, “cái cụ thể”.
 
Liệu có một viễn cảnh nào mà “cái chung” được phát huy tối đa trong kiến trúc phần mềm. Chắc chắn là không? Tại sao vậy? Nếu mọi thứ phụ thuộc quá nhiều vào “cái chung” như thư viện, tài nguyên… thì khi có một lỗi xảy ra đặc biệt là ở module nhỏ ít quan trọng, nó sẽ kéo theo sự sụp đổ ở các module khác quan trọng hơn… và hình thành nên hiệu ứng domino. Như vậy các kiến trúc sư sẽ cần phải thận trọng khi thiết kế. Khi quyết định tách ra “cái chung” cần xác định tầm quan trọng thực sự của “cái chung” đó, cũng như quan hệ của nó với các phần khác ra sao. "Cái riêng" cũng không phụ thuộc quá nhiều vào "cái chung". Thí dụ nếu chức năng "Upload" không hoạt động, thì các thông tin cơ bản khác vẫn phải được cập nhật bình thường.
 
Trong cơ sở dữ liệu, chúng ta đều biết 4 loại chuẩn hóa dữ liệu. Mục đích để làm gì? Rõ ràng là để giảm dư thừa dữ liệu và đảm bảo tính logic được nhất quán, giảm thiểu sự phức tạp của cấu trúc dữ liệu. Đây chính là vận dụng “cái chung” khá hiệu quả vào bài toán cấu trúc dữ liệu. Nhưng chúng ta cũng lại biết có một kỹ thuật gọi là “phá chuẩn” (denormalization), có nghĩa là “cái chung” bị phá vỡ. Tại sao vậy? Vì trong một số trường hợp, phá chuẩn sẽ tăng hiệu suất chương trình và làm đơn giản hóa công việc, giảm thiểu nỗ lực viết code do quá nhiều liên kết giữa các bảng, tức là liên kết giữa các “cái chung” và “cái riêng”. Nhưng có phải là lúc nào cũng nên “phá chuẩn” không? Câu trả lời là không vì còn phụ thuộc vào mô hình dòng chảy dữ liệu, giống như không phải con đường nào cũng cho phép rẽ trái hoặc rẽ phải. Nếu như nhận thấy việc làm dư thừa dữ liệu không đáng kể thì chúng ta có thể phá chuẩn ở một số liên kết…, tức là tập trung xử lý vào những “cái riêng” và cắt đứt quan hệ với “cái chung”. Như vậy xử lý vấn đề “cái chung”, “cái riêng” trong lập trình cần đòi hỏi sự khéo léo và sáng tạo của những người thiết kế.
 
Một lưu ý nữa là nếu chúng ta chỉ tư duy “cái chung” thì sẽ không có sự sáng tạo nào được đưa ra, sẽ không có sự đột phá cho các phiên bản tiếp theo. Các lập trình viên mới sẽ phải đi theo con đường cũ của các lập trình viên đi trước vì tất cả đều đã được “dọn sẵn” như thư viện chung, tài nguyên chung…Là một Project Manager, bạn phải khơi mào sự sáng tạo từ các tư duy “cái riêng” của các lập trình viên.
 
Còn bạn, bạn sẽ nghĩ sao về điều này?
 
Tác giả: Phạm Đình Trường
Category