Khái niệm về OOD – Object oriented design

Bài viết được sự cho phép của tác giả Lê Chí Dũng
Trong việc Design Parttern cho OOP  người ta bàn về vấn đề thiết kế một pattern làm sao để lớp con kế thừa lớp cha nhưng tự loại bỏ những method mà nó không mong muốn. Điều đó có nghĩa là lớp con không tuân thủ nguyên tắc định trước, tức là nó không tuân thủ một trong những nguyên tắc cơ bản của thiết kế hướng đối tượng (OOD – Object oriented design) là Liscov substitution principle.
Điều đó cho thấy khi thiết kế, tìm giải pháp cho một vấn đề nào đó, việc nắm rõ các nguyên lí cơ bản của OOD là vô cùng quan trọng. Bài này xin giới thiệu về 5 nguyên tắc cơ bản của OOD là:
  1. Open closed
  2. Liskov substitution
  3. Dependency inversion
  4. Interface segregation
  5. Single responsibility

Open closed

Ivar Jacobson từng nói: “Để thiết kế các hệ thống lâu dài, cần luôn tâm niệm rằng các hệ thống luôn thay đổi trong quá trình sử dụng”. (All systems change during their life cycles. This must be borne in mind when developing systems expected to last longer than the first version.”). Năm 1988, Bertrand Meyer đưa ra mục tiêu để thực hiện điều mà Ivar Jacobson nói trên mà sau này trở thành nguyên lí open-closed nổi tiếng. Đó là: SOFTWARE ENTITIES (CLASSES, MODULES, FUNCTIONS, ETC.) SHOULD BE OPEN FOR EXTENSION, BUT CLOSED FOR MODIFICATION.

Các chương trình áp dụng nguyên lí open-close được thay đổi bằng cách thêm code mới chứ không phải sửa code có sẵn. Bằng cách này, tránh được thay đổi dây chuyền trong toàn bộ chương trình. Tuy nhiên, mỗi entity của chương trình có thể đóng với thay đổi này nhưng lại không đóng với thay đổi nào đó khác. Do đó, tính đóng này chỉ là tương đối và nhiệm vụ của người thiết kế là với mỗi đặc thù của chương trình, ưu tiên đóng các thuộc tính dễ thay đổi nhất.

Để “đóng” các entity của chương trình, có thể sử dụng giải pháp abstraction, data driven, ..
Open-closed là nguyên li trung tâm, rất quan trọng trong thiết kế hướng đối tượng vì chính nguyên lí này làm cho lập trình hướng đối tượng có tính tái sử dụng (reusability) và dễ bảo trì (maintainability).

Liskov substitution

Nguyên lí này được phát biểu như sau:

FUNCTIONS THAT USE POINTERS OR REFERENCES TO BASE CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED CLASSES WITHOUT KNOWING IT.

Tức là hoạt động của các function có sử dụng reference hay pointer tới object của lớp cha cần được đảm bảo là không bị ảnh hưởng khi thay thế reference hay pointer tới object của lớp cha bởi reference hay pointer tới object của lớp con và function đó không cần biết về sự tồn tại của lớp con. Khi đó, các virtual member functions ở lớp cha cũng phải có ở lớp con, và phải thực hiện một công việc có nghĩa.

Nếu nguyên lí này bị vi phạm, function có sử dụng reference hay pointer tới object của lớp cha phải kiểm tra kiểu của object để đảm bảo chương trình có thể chạy đúng, và việc này vi phạm nguyên lí open-closed nhắc đến ở trên.

Dependency inversion

Việc áp dụng hai nguyên lí open-closed và Liskov substitute một cách chặt chẽ có thể tổng quát hóa thành nguyên lí depndency inversion được phát biểu như sau:

  1. HIGH LEVEL MODULES SHOULD NOT DEPEND UPON LOW LEVEL MODULES. BOTH SHOULD DEPEND UPON ABSTRACTIONS.
  2. ABSTRACTIONS SHOULD NOT DEPEND UPON DETAILS. DETAILS SHOULD DEPEND UPON ABSTRACTION.

Thực hiện một bằng cách dùng abstract layer như hình dưới.

Interface segregation

Nguyên lí này được phát biểu như sau:

CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE
Khi một client bị ép phải phụ thuộc vào những interface mà nó không sử dụng thì nó sẽ bị lệ thuộc vào những thay đổi của interface đó. Chúng ta cần phải tránh điều này nhiều nhất có thể bằng cách chia nhỏ interface.

Single responsibility

Nguyên lí này được phát biểu như sau:

THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE.
Chú ý: để hiểu bài này, cần có kiến thức cơ bản về lập trình hướng đối tượng, nhất là các khái niệm encapsulation, inheritance, polimorphism.
Bài viết gốc được đăng tải tại lcdung.top
Có thể bạn quan tâm: