SOLID trong tiếng anh nghĩa là cứng, vậy làm thế nào để thành lập trình viên SOLID hơn mỗi ngày ?
SOLID là viết tắt của:
- Single Responsibility principle (SRP).
- Open-Closed principle (OCP).
- Liskov substitution principle (LSP).
- Interface segregation principle (ISP).
- Dependency inversion principle (DIP).
-
Single responsibility principle (Nguyên tắc đơn nhiệm)
Nôi dung: mỗi class, module hoặc function chỉ thực hiện một chức năng, 1 action duy nhất (chỉ có thể sửa vì 1 lý do duy nhất)
VD: Thay vì viết một class ôm đồm tất cả các công việc liên quan đến việc quản lý sản phẩm như này:
class ProductManagement {
public function openConnection() {};
public function showListProducts() {};
}
Chúng ta nên tách thành các class con, mỗi class xử lý một công việc riêng kiểu như này:
class DBConnection {
public function openConnection() {};
}
class ListProducts {
public function showListProducts(User user) {};
}
-
Open/closed principle (nguyên tắc đóng mở)
Nội dung:
- Đóng: hạn chế sửa đổi class hoặc function đã có sẵn
- Mở: xem xét mở rộng hoặc kế thừa class sẵn có
Ví dụ: Lớp Mobiphone được thiết kế chỉ để đóng gói các chức năng cơ bản của 1 chiếc điện thoại (nghe, gọi, nhắn tin). Nếu muốn bổ sung thêm chức năng chụp ảnh, lướt web, chúng ta nên tách riêng một class SmartPhone kế thừa class Mobiphone, bởi vì không phải điện thoại nào cũng có chức năng chụp ảnh, lướt web.
-
Liskov substitution principle – Nguyên tắc thay thế Liskov
Nội dung: các object của lớp con có thể thay thế object của lớp cha mà vẫn đảm bảo tính đúng đắn của chương trình.
Ví dụ: Các đối tượng Square đều có thể xem là các đối tượng Rectangle.
nhưng nếu sử dụng đối tượng Circle thì sẽ vi phạm tính đúng đắn của chương trình
- Interface segregation principle – nguyên tắc chi nhỏ interfaceNội dung: Đối với các Interface quá lớn, nên chia nhỏ ra để sử dụngInterface khác với abstractions ở chỗ là khi sử dụng abstraction, chúng ta có thể lựa chọn các methods cần thiết phù hợp với requirement của mình để sử dụng, nhưng đối với interface thì khi implement thì phải sử dụng hết tất cả các method trong interface đó. Điều này dẫn đến sự lãng phí khi không cần đến mà vẫn phải sử dụng.Chúng ta có một interface Animal như sau:interface Animal { public function eat(); public function run(); public function fly();
}
Chúng ta có 2 class Dog và Snake implement interface Animal. Nhưng thật vô lý, Dog thì làm sao có thể fly(), cũng như Snake không thể nào run() được? Thay vào đó, chúng ta nên tách thành 3 interface như thế này:
interface Animal {
public function eat();
}
interface RunnableAnimal extends Animal {
public function run();
}
interface FlyableAnimal extends Animal {
public function fly();
}
- Dependency inversion principle Nội dung: – 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. – Interface (abstraction) không nên phụ thuộc vào chi tiết, mà ngược lại. ( Các class giao tiếp với nhau thông qua interface, không phải thông qua implementation.)VD: Sạc type C có thể sạc được điện thoại Iphone 5, 6, 7…Ở đây, type C chính là Interface, còn các dòng điện Iphone 5, 6, 7 … chính là các implementation, để có thể sạc pin, cục sạc chỉ quan tâm Interface là type C, miễn là đầu cắm type C là có thể sạc được, không quan tâm đến dòng điện thoại đó là gì.Khi áp dụng các nguyên tắc Solid sẽ giúp cho các lập trình viên code sạch hơn, dễ tái sử dụng code và giúp cho việc bảo trì về sau thuận lợi hơn.