Trong bài viết trước về Inversion of Control (IoC), Got It cũng đã đề cập tới khái niệm Dependency Injection (DI). Nhiều kỹ sư vẫn đang gặp khó khăn trong việc phân biệt DI, Dependency Inversion và IoC. Vậy chúng là gì? Hãy cùng tìm hiểu câu trả lời qua bài viết sau nhé!
Mục lục
1. Dependency Injection là gì?
Có nhiều quan điểm cho rằng, DI là một mô hình phát triển dựa trên nguyên lý IoC, tuy nhiên nhiều người lại coi Dependency Injection là một design pattern có cùng nguyên lý Dependency Inversion với IoC. Đây là một kỹ thuật quan trọng, giúp lập trình viên tiết kiệm thời gian và công sức trong lập trình hướng đối tượng.
Để giải thích một cách kĩ lưỡng thì thì DI vận hành như sau:
Giả sử chúng ta có hai class, A và B. Khi Class A phải sử dụng một tính năng gì đó của Class B thì có nghĩa là Class A phụ thuộc vào Class B. Mặt khác, trong ngôn ngữ lập trình Java, trước khi Class A có thể sử dụng method của class B thì class A phải tạo ra một object của class B. Việc chuyển giao trách nhiệm tạo Object đấy cho một ai đó khác và trực tiếp sử dụng mối phụ thuộc giữa A và B thì được gọi là Dependency Injection.
Nói một cách ngắn gọn, Dependency Injection là kỹ thuật tách một class độc lập với các biến phụ thuộc. Trong lập trình hướng đối tượng, chúng ta luôn phải làm việc với nhiều class. Dependency là một loại quan hệ giữa hai class mà trong đó một class hoạt động độc lập và class còn lại phụ thuộc vào class kia.
2. Tại sao phải sử dụng Dependency Injection?
Dependency Injection là một design pattern giúp các kỹ sư IT có thể nâng cấp và bảo trì hệ thống dễ dàng hơn, giúp tiết kiệm thời gian lẫn chi phí trong dự án. Có thể nói nó là một design pattern giúp ngăn chặn sự lệ thuộc của Class A vào các object.
Giả sử chúng ta có class House, trong đó có nhiều object khác như Table, TV set, v.v… Nếu đang bình thường thì không sao, nhưng nếu chúng ta muốn nâng cấp chiếc bàn của mình lên thành Table 2 thì lúc này quá trình mới bắt đầu trở nên lằng nhằng. Do Class House chịu trách nhiệm khởi tạo hết các Object, do đó để thay object Table, chúng ta sẽ phải lập một Class House 2 rồi lúc đó mới có thể tạo Object Table 2. Cứ thế mỗi lần muốn nâng cấp thì chúng ta lại phải tạo ra class mới như vậy, nghĩa là thêm một đống code nữa và cực kỳ khó đọc.
Do đó, Dependency Injection đóng vai trò là một người trung gian, chịu trách nhiệm tạo ra các loại objects khác nhau, sau đó đẩy (inject) chúng vào Class A, khiến Class A không còn phải phụ thuộc vào bất kỳ object nào nữa.
3. Có mấy loại Dependency Injection?
Nếu là một design pattern, DI có thể được chia làm mấy loại? Theo trang codelearn.io, chúng ta sẽ gặp 3 loại phổ biến nhất của DI như sau:
- Constructor injection: Các dependency (biến phụ thuộc) được cung cấp thông qua constructor (hàm tạo lớp).
- Setter injection: Các dependency (biến phụ thuộc) sẽ được truyền vào 1 class thông qua các setter method (hàm setter).
- Interface injection: Dependency sẽ cung cấp một
Interface
, trong đó có chứa hàm có tên làInject
. Các client phải triển khai mộtInterface
mà có một setter method dành cho việc nhận dependency và truyền nó vào class thông qua việc gọi hàmInject
củaInterface
đó.
Như vậy, Dependency Injection có ba nhiệm vụ chính:
- Tạo ra các Object
- Tìm xem Class nào cần Object nào
- Sau đó, cung cấp cho các class đó object tương ứng.
Để phân biệt với IoC, các bạn có thể hiểu đơn giản rằng IoC giống như một hướng đi, và Dependency Injection là sự hiện thực hoá hướng đi đó.
4. Ưu điểm và khuyết điểm của Dependency Injection
4.1. Ưu điểm
- Dễ thực hiện kiểm thử nói chung và Unit Test nói riêng: Bởi Dependency Injection giúp inject các object vào class một cách dễ dàng, đương nhiên các mock object cũng có thể được thêm vào class để thực hiện các bài kiểm thử mong muốn
- Dễ đang quan sát quan hệ giữa các Module: Do các Dependency được Inject vào đều thông qua Constructor, do đó các kỹ sư có thể nhìn ra mối quan hệ giữa các Object thuận tiện hơn
- Các kỹ sư IT sẽ bảo trì và nâng cấp code, cũng như các module dễ dàng hơn. Ví dụ ở phần trên đã phần nào giúp giải thích ưu điểm này. Chúng ta không cần phải tạo hẳn 1 class mới chỉ để phục vụ việc nâng cấp một Object.
- Giảm sự phụ thuộc lẫn nhau của các module, giúp giảm lỗi khi thay thế hoặc chỉnh sửa
4.2. Nhược điểm
- Dependency Injection là một khái niệm phức tạp: Do đó các developers mới bước chân vào nghề sẽ rất khó để có thể học và hiểu rõ DI.
- Do DI sử dụng Interfaces, do đó sẽ rất khó để debug vì chúng ta không biết chính xác module nào sẽ được gọi.
- Do các object được khởi tạo ngay từ đầu, điều này có thể gây ảnh hưởng đến performance của dự án.
- Code tuy sẽ dễ bảo trì nhưng cũng phức tạp hơn.
Hy vọng qua bài viết trên, Got It Vietnam đã cung cấp tới các bạn đầy đủ khái niệm Dependency Injection là gì, cũng như một vài ưu, nhược của Dependency Injection trong lập trình hướng đối tượng để có thể ứng dụng tốt hơn trong công việc