SOLID - Nguyên tắc thiết kế để code trở nên "đẹp" và "thông minh" hơn

SOLID là nguyên tắc thiết kế trong lập trình OOP. Như tiêu đề, nguyên tắc này sẽ giúp cho code dễ đọc, dễ test, rõ ràng hơn và đặc biệt là maintenance dễ dàng hơn rất nhiều.
SOLID là viết tắt của 5 nguyên tắc:
Single responsibility priciple
- Open/closed principle
- Liskov substitution principle
- Interface segregation principle
- Dependency inversion principle
5 nguyên tắc sẽ được mô tả cụ thể hơn như sau:
1. Single responsibility principle: Một class chỉ nên giữ 1 trách nhiệm duy nhất (Chỉ có thể sửa đổi class với 1 lý do duy nhất)
Với mỗi 1 class chỉ nên có 1 nhiệm vụ riêng, ví dụ như 1 class dùng để kết nối DB, 1 class dùng để chứa logic, chứ không nên để 1 class thực hiện cả 2 nhiệm vụ trên. Nếu như khi để chung 2 mục trên vào 1 class thì khi cần chỉnh sửa logic chúng ta lại phải vào class có chứa cả đoạn code kết nối DB, trong khi phần code kết nối vẫn chạy tốt. Việc này có thể dẫn đến việc chỉnh sửa làm ảnh hưởng đến kết nối DB từ đúng thành sai, hoặc tốn thời gian để xác định xem chỉnh sửa logic ở đoạn nào trong đoạn code đang lẫn lộn cả logic và kết nối.
Hay như lớp Repository, mỗi class trong lớp này thường sẽ được sử dụng cho 1 entity riêng biệt. Ví dụ như chúng ta có 2 entity là Student và Subject, khi có 2 class riêng để xử lý 2 entity này, có thể dễ dàng modify hàm Add của Student mà không làm ảnh hưởng gì đến Subject và cũng không cần check xem đâu là hàm của Add của Student, đâu là hàm Add của Subject.
2. Open/closed principle: Có thể thoải mái mở rộng 1 class nhưng không được sửa đổi bên trong class đó
Chúng ta có thể thêm 1 class để xử lý việc phát sinh, nhưng không nên chỉnh sửa lại những class đã có. Khá là dễ để nhận thấy ưu điểm của nguyên tắc thứ 2 này. Ví dụ như những class cũ đã được sử dụng trước đó ở nhiều nơi, nếu thay đổi class đó dễ dẫn đến việc làm ảnh hưởng đến đoạn code đang sử dụng class này, đặc biệt khi dự án to, nhiều file, sẽ khó xác định được việc class này thay đổi sẽ ảnh hưởng đến những phần nào khác. Thay vào đó chúng ta có thể viết 1 class mới để xử lý vấn đề hoặc viết 1 class mới và kế thừa lại class cũ và viết thêm những phần khác.
3. Liskov substitution principle: Bất cứ instance nào của class cha cũng có thể được thay thế bởi instance của class con của nó mà không làm thay đổi tính đúng đắn của chương trình.
4. Interface segregation principle: Thay vì dùng 1 interface lớn, ta nên tách thành nhiều interface nhỏ, với nhiều mục đích cụ thể Client không nên phụ thuộc vào interface mà nó không sử dụng.
Khi tách 1 interface lớn thành nhiều interface nhỏ gồm các hàm giống nhau sẽ giúp cho quản lý dễ dàng và logic hơn.
5. Dependency inversion principle: Các module cấp cao không nên phụ thuộc vào các modules cấp thấp. Cả 2 nên phụ thuộc vào abstraction. 2. Abstraction không nên phụ thuộc vào chi tiết, mà ngược lại.
1 trong những cách để thực hiện nguyên tắc này đó là dependency injection.

Nhận xét