- Nguyên lí SOLID là gì ? Để trở thành 1 developer giỏi thì phải thành thục nguyên lí này
- Single Responsibility Principle – Nguyên lí đơn trách nhiệm
- Open/Closed Principle – Nguyên lí đóng mở thế giới
- Liskov Substitution principle – Nguyên lí thay thế Liskow
- Interface Segregation Principle – Nguyên lí phân biệt interface
- Dependency inversion principle – Nguyên lí nghịch đảo phụ thuộc
Dependency inversion principle – Nguyên lí nghịch đảo phụ thuộc
Dương Quá 16 năm mới được gặp lại Tiểu Long Nữ, khi gặp lại Dương Quá đã trở thành một trong 5 đại cao thủ Trung Nguyên, còn bạn sau 4 phần của nguyên lí SOLID không biết đã “cứng” thêm được tí nào chưa. Đã đến giai đoạn cuối của bí kíp SOLID, nhưng để học được thì chúng ta cần phải tự cung :)), có nghĩa là phải “cắt”, cắt hết.
Nhảm nhí tí thôi, nhắc lại một tí kẻo bạn nào đọc nhanh quá thì quên mất, nguyên lí này được phát biểu thành 2 ý, bao gồm:
– High–level modules should not depend on low-level modules. Both should depend on abstraction . Modules cấp cao không nên phụ thuộc vào các modunles cấp thấp, cả hai nên phụ thuộc vào abstraction.
– Abstractions should not depend on details. Details should depend on abstractions. Abstraction không nên phụ thuộc vào các chi tiết mà phải ngược lại, chi tiết nên phụ thuộc vào abstraction
Theo cách thông thường thì code sẽ có cấu trúc như sau:
Với cấu trúc như trên hình thì các module cấp cao được xây dựng trước và module cấp thấp được xây dựng sau. Module cấp thấp thì được thiết kế để được thực hiện bởi các lớp cấp thấp hơn, nó cho phép tăng khả năng xây dựng hệ thống và các module cấp cao hơn thì phụ thuộc trực tiếp vào module các module cấp thấp hơn để hoàn thành vài công việc. Sự phụ thuộc vào các cấp thấp hơn làm giảm khả năng tái sử dụng của các thành phần cấp cao. Bạn thử tưởng tượng điều gì sẽ xẩy ra khi các module cấp thấp bị thay thế hoặc sửa đổi ?
Giả sử như bạn có một module Wifi có nhiệm vụ nhận và kết nối wifi. Trong đó class cấp cao nhất là Wifi và class cấp thấp là DataWifi và ConnectWifi. Nếu chúng được thiết kế như cách trên thì các class DataWifi và ConnectWifi được thiết kế sau và class Wifi phụ thuộc trực tiếp vào hai class cấp thấp. Trong trường hợp này, nếu bạn muốn thay đổi thiết kế để có một lớp NetworkManage khác quản lí thay thế class Wifi thì sẽ thật khó khăn và phức tạp, giả sử đây là một class phức tạp và khó test.
public class DataWifi { public ArrayList getDataWifi(...) { // có thể trả về list wifi ... ... } } public class ConnectWifi { public void connect(...) { ... } } public class Wifi { DataWifi dataWifi; ... listWifi = dataWifi.getDataWifi(); ... } public class NetWorkManage { ... }
Để tránh phải điều này thì Dependency inversion principle – Nguyên lí nghịch đảo phụ thuộc được đưa ra. Thật tuyệt vời :)).
Bạn có thể thấy các module cấp cao và module cấp thấp đều được phụ thuộc vào interface hoặc abstraction và chúng không được phụ thuộc vào nhau. Vì vậy toàn bộ code sẽ được viết lại như sau:
interface IConnectWifi { public void connect(); } public class ConnectWifi implements IConnectWifi { public void connect() { // code ở đây } }
interface IDataWifi { public void getDataWifi(); } public class DataWifi implement IDataWifi { public ArrayList getDataWifi() { // code ở đây } }
interface IWifi { public void manage(); } public class Wifi implements IWifi { ... }
public class NetworkManage { }
Bạn có thể thấy việc áp dụng nguyên lí này sẽ tăng khả năng tái sử dụng của các class cấp cao hơn. Khi các thành phần trong class cấp thấp hơn bị sửa hoặc bạn nhận được thêm vài yêu cầu mới từ khách hàng và cần thiết phải thêm thành phần mới thì chỉ cần thêm các mối liên kết trung gian là các interface hoặc abtraction.