Nội dung nguyên lý
1. Các module cấp cao không nên phụ thuộc vào các module cấp thấp. Cả 2 nên phụ thuộc vào abstraction.
2. 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)
Với cách code thông thường, các module cấp cao sẽ gọi các module cấp thấp. Module cấp cao sẽ phụ thuộc và module cấp thấp, điều đó tạo ra các dependency. Khi module cấp thấp thay đổi, module cấp cao phải thay đổi theo. Một thay đổi sẽ kéo theo hàng loạt thay đổi, giảm khả năng bảo trì của code.
Nếu tuân theo DIP, các module cấp thấp lẫn cấp cao đều phụ thuộc vào 1 interface không đổi. Ta có thể dễ dàng thay thế, sửa đổi module cấp thấp mà không ảnh hưởng gì tới module cấp cao.
Ví dụ minh họa
Cùng đọc khai báo class dưới đây
Class Cart sẽ phụ thuộc vào các module cấp thấp hơn như Database, Logger, EmailSender.
Khi thay đổi các class phụ thuộc ta lại phải vào sửa đổi code ở class này. Với project nhỏ thì có thể nhưng với những project lớn chứa hàng trăm, hàng nghìn class thì điều này là rất khó và mất rất nhiều thời gian cũng như dễ gây ra lỗi
Áp dụng DIP, ta có thể viết lại class đó như sau
Trong thực tế, người ta thường áp dụng pattern Dependency Injection (DI) để đảm bảo nguyên lý DIP trong code. Các bạn tham khảo bài viết về Dependency Injection ở đây
Code sau khi áp dụng DI sẽ như sau
Kết luận
DIP được áp dụng nhiều nhất trong code, nhưng nó cũng gây ra nhiều điều tranh cãi. Bên cạnh một số ưu điểm như
- Giảm sự kết dính giữa các module
- Code dễ bảo trì, dễ thay thế module
- Rất dễ test và viết Unit Test
DIP cũng đi kèm một số khuyết điểm sau:
- Khái niệm DI khá “khó tiêu”, các developer mới sẽ gặp khó khăn khi học
- Sử dụng interface nên đôi khi sẽ khó debug, do không biết chính xác module nào được gọi
- Làm tăng độ phức tạp của code
Tùy vào quy mô của từng dự án khác nhau mà mình sẽ có những cách áp dụng khác nhau. Không nên máy móc áp dụng nguyên lý này nguyên lý kia.
Không có giải pháp nào là hoàn hảo cho mọi vấn đề!
Tiếp tục cập nhật ...