Ghi chép về SOLID

Một trong những nguyên tắc nền tảng của coder – SOLID.

SOLID – Viết tắt từ các chữ cái đầu tiên của các nguyên tắc nền tảng cho thiết kế hướng đối tượng (OOP), bao gồm:

  • Single Responsibility Principle
  • Open – Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Áp dụng các nguyên tắc này giúp code dễ đọc hiểu, dễ maintain. Và nếu ai tham gia dự án đều hiểu về SOLID thì sẽ dễ dàng transfer hơn.

Mình sẽ đi sâu vào từng nguyên tắc để giải thích kỹ càng hơn.

1. Single Responsibility Principle

Mỗi một class chỉ nên tập trung vào giữ MỘT nhiệm vụ duy nhất

Nghe có vẻ như một “điều hiển nhiên” đúng không? Mỗi class sẽ tập trung vào một trách nhiệm/nhiệm vụ duy nhất sẽ khiến cho mọi thứ trở nên rõ ràng hơn.

Tuy nhiên đây lại là nguyên tắc mà các developer hay mắc phải nhất. Khi sửa đổi một class, thường thì chúng ta hay viết thêm các method hoặc property thêm để thoả mãn tính năng và thường làm cho class rắc rối thêm.

Trong trường hợp này, nếu các chức năng cần tạo có nhiệm vụ khác thì ta nên tạo class mới. Tuy có nhiều class hơn, nhưng mỗi class sẽ ngắn và tập trung vào 1 nhiệm vụ cụ thể, dẫn tới việc code và debug sẽ dễ dàng hơn, khả năng sinh bug ít hơn.

2. Open – Closed Principle

Có thể thoải mái mở rộng (extend) một class, nhưng không được sửa đổi nội dung của nó.

Nguyên tắc này bổ sung cho nguyên tắc số 1 ở trên.

Việc sửa đổi, thêm mới tính năng vào một chương trình đang chạy là điều rất dễ xảy ra. Nhưng để làm việc đó, chúng ta nên mở rộng class thay vì sửa đổi nội dung của nó. Việc làm này sẽ giúp code nhìn rõ ràng và dễ chỉnh sửa hơn.

3. Liskov Substitution Principle

Trong một chương trình, có thể thay thế class cha bằng class con mà không làm thay đổi tính đúng đắn của chương trình

4. Interface Segregation Principle

Nên tách các interface nhỏ và liên quan với chức năng thay vì viết một interface lớn.

Việc tách nhỏ các interface sẽ giúp sử dụng các interface hiệu quả hơn. Thay vì có 1 interface với 100 method thì ta nên tách thành nhiều interface hơn. Nó sẽ giúp code có khả năng dùng lại các interface được định nghĩa tốt hơn, dễ dàng quản lý và sử dụng.

5. Dependency Inversion Principle

Các module cấp cao không phụ thuộc vào module cấp thấp, cả hai nên phụ thuộc vào interface (abstraction).
Các class giao tiếp với nhau thông qua interface, chứ không thông qua implementation.

Khi các module giao tiếp với nhau thông qua interface, chúng ta có thể dễ dàng thay đổi các implementation mà không bị thay đổi tính đúng đắn của chương trình.

Ví dụ, để kết nối database, hệ thống sẽ phụ thuộc vào interface DatabaseConnection với các method connect/get/save… Khi cần thay đổi database từ mysql sang mongodb hoặc bất kỳ một CSDL nào khác, miễn là implementation kết nối tới CSDL mới được implement từ interface DatabaseConnection thì tính đúng đắn của chương trình sẽ được đảm bảo