Bốn tiêu chí khi áp dụng design pattern

Nghe mấy ông prồ thỉnh thoảng bắn một câu kiểu như "cậu muốn tiến xa trong cái nghiệp lập trình này thì phải rành design patterns". Thì đúng thế, ai chả biết. Design pattern vốn là tinh hoa của những người đi trước, đúc kết lại mà thành. Nhưng động vào thì ôi thôi, nhiều quá, biết rẽ lối nào đây?

Design Patterns: Elements of Reusable Object-Oriented Software là bí kíp vỡ lòng gối đầu giường của bất kì ai muốn theo học design pattern. Học đạo cần biết tên biết mặt sư tổ sư thúc sư huynh. Chính 4 sư tổ (the Gang of Four) của design pattern đã viết bí kíp này: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.

Bí kíp nêu và miêu tả kĩ 23 chiêu. Như nhan đề bí kíp, những chiêu này dùng cho phong cách hướng đối tượng. Học đạo là học cái tinh thần, cái cốt lõi, sao cho dạt tới cảnh giới vô chiêu thắng hữu chiêu. Ai chưa thấm nhuần ý nghĩa của "vô chiêu", xin đọc (lại?) các siêu phẩm của Kim Dung hoặc bài nghiên cứu của Nguyễn Duy Chính. Nắm được tinh thần của design pattern rồi, thì hoàn toàn áp dụng được 23 chiêu trên vào những ngôn ngữ không hướng đối tượng, như C chẳng hạn.

23 chiêu vẫn chỉ là chiêu. Có thể tóm tắt tinh thần chúng lại thành 4 tiêu chí có quan hệ mật thiết với nhau:

  • Refactor
  • Lập trình cho interface hơn là implementation
  • Nên dùng composition hơn là inheritance
  • Delegate

Phần dưới bàn về 4 tiêu chí này. Design pattern là một phần của software engineering. Ai nghĩ bàn về software engineering mà không dính tí mã nào là kì khôi, thì thật sai lầm. Bởi vì về bản chất, software engineering không dạy cú pháp ngôn ngữ, mà dạy tinh thần (<- đã bảo là "đạo" mà lị).

Refactor

Hãy nhớ lại các bài toán đặt làm nhân tử chung ở cấp 1, cấp 2. Refactor nghĩa là tìm những cái giống nhau đặt riêng ra ngoài.

Dấu hiệu cho thấy có thể refactor, là khi cứ phải cắt dán cả một khối mã. Để đỡ phải cắt dán trong cùng một chương trình, người ta nghĩ ra hàm hoặc class. Để đỡ phải cắt dán từ chương trình này sang chương trình kia, người ta nghĩ ra framework.

Chương trình có hàng chục chỗ cần vẽ tiêu đề cửa sổ, mà chỗ nào cũng phải dùng đến 10 dòng mới vẽ xong, thì sao không gom 10 dòng đó thành một hàm, lúc nào muốn vẽ chỉ cần 1 dòng gọi hàm?

Nếu vin cớ rằng project gấp quá không có thời gian refactor, thì nên bỏ việc lập trình vì nó không phù hợp với bạn. Làm phần mềm khó chứ không dễ, không phải thằng dở hơi có bản tính chụp giựt nào cũng tự dưng thành công. Mất có 1 tiếng để refactor mà lợi được cả nhiều ngày tháng sau mà còn không làm, thì bạn còn phải thức khuya dài dài để làm cho xong project.

Nếu vin cớ rằng xong project rồi hẵng refactor, thì quả là ngụy biện. Vì xong project rồi thì refactor để làm gì nữa? Bạn còn hứng thú để ngồi mò mẫm refactor nữa không? Những thư viện và framework có ý nghĩa thực tế đều là những thứ được sinh ra từ những project thực tế. Thư viện và framework do giáo sư tiến sĩ ngồi chơi xơi nước nghĩ ra chỉ đáng ném sọt rác.

Refactor mang lại quá nhiều cái lợi: mã ngắn gọn dễ hiểu, dễ bảo trì, dễ sửa, dễ sử dụng, dễ mở rộng v.v.

Lập trình cho interface hơn là implementation

Nếu bạn nghĩ kế thừa (inheritance) chỉ đem lại cho bạn lợi ích "code reusable" thì đó mới chỉ là một nửa câu chuyện. Phần còn lại của câu chuyện là kế thừa tạo ra một họ các đối tượng có chung một giao diện (interface) thống nhất, từ đó thực hiện polimophism. Thông qua polimophism, client không cần (và không muốn) làm việc trực tiếp với object nào mà chỉ muốn làm việc với interface thôi. Nhờ đó mà hệ thống uyển chuyển hơn nhiều.

Chẳng hạn bưu điện là interface có chức năng gửi thư. Bạn là client. Có nhiều kiểu (type) chuyển thư: xe bò, xe gắn máy, ô tô, máy bay. Với tư cách là client, bạn chỉ muốn và chỉ cần quan tâm đến thằng interface, tức là bưu điện: cho thư (đã dán tem) vào thùng là thư được gửi đến nơi, mà không muốn quan tâm đến chuyện người ta dùng xe bò hay máy bay.

Dùng composition hơn là inheritance

Khi cấu trúc inheritance (thừa kế) càng dài, thì hệ thống càng kém uyển chuyển. Khi B và C thừa kế A, thì giữa B-A và C-A có mối ràng buộc theo chiều dọc. Khi B muốn A thay đổi thì khó mà thay đổi A ngay, vì còn đụng đến C. Chẳng phải các văn bản thủ tục hành chính càng chồng chéo, thì nhân dân càng mệt hay sao? Chẳng phải người ta cũng muốn cải cách mà không thể cải cách ngay (hoặc chẳng thể?) hay sao?

Do đó, nên làm cho cây thừa kế càng thấp càng tốt, biến chiều dọc thành chiều ngang bằng cách dùng composition.

Delegate

Nôm na là: nhờ được thằng hàng xóm cái gì, thì hãy nhờ ngay. Thoạt nghe thì rất vô trách nhiệm, nhưng hóa ra lại rất dân chủ. Các thể chế độc tài chẳng phải cái gì cũng ôm vào mình (điện, nước...), chẳng muốn nhả ra cái gì hay sao? Càng ôm thì càng đuối, đuội.

Thay vì ôm vào một cục, hãy san sẻ công việc ra.

Reference: Blog cong dong ve CNTT