Dependency injection là gì? 3 điều cần biết về DI
Việc tổ chức code tốt giúp lập trình viên có thể dễ dàng thực hiện mở rộng code hoặc bảo trì trong tương lai. Có thể nói, việc nắm vững các design pattern sẽ hỗ trợ rất nhiều trong việc phát triển phần mềm. Bài viết hôm nay sẽ đi sâu vào tìm hiểu về Dependency Injection (DI) - một dạng design pattern có khả năng làm giảm thiểu sự phụ thuộc giữa các class, giúp cho code trở nên trực quan và dễ hiểu hơn.
Tìm hiểu về kỹ thuật Dependency injection trong công nghệ phần mềm
Dependency injection là một kỹ thuật lập trình giúp tách một class độc lập với các biến phụ thuộc. Giải nghĩa theo Wikipedia ta có: Trong công nghệ phần mềm, Dependency injection là một kỹ thuật nhờ đó một đối tượng (hoặc phương thức tĩnh) có thể cung cấp các phụ thuộc của một đối tượng khác. Một biến phụ thuộc là một đối tượng có thể sử dụng (như một dịch vụ).
Tuy nhiên, khái niệm này có thể không mấy dễ hiểu ngay lần đầu tiên bạn đọc nó. Do đó, để hiểu cụ thể về kỹ thuật này dưới góc độ kỹ thuật, trước tiên chúng ta cùng phân tích khái niệm theo cách tổng quan và thông thường nhất.
Phụ thuộc có nghĩa trông cậy vào một sự hỗ trợ, trợ giúp nào đó. Nếu nói chúng ta đang dựa dẫm quá nhiều vào điện thoại di động, điều đó có nghĩa là chúng ta đang phụ thuộc vào chúng.
Tiếp theoBizfly Cloud sẽ cùng phân tích về phụ thuộc trong lập trình qua bài viết này nhé:
Khi lớp A sử dụng một số chức năng của lớp B, có nghĩa là lớp A có một phụ thuộc của lớp B.
Trong Java, trước khi bạn có thể sử dụng các method của lớp khác, bạn sẽ cần tạo đối tượng của lớp đó (tức là lớp A cần tạo một đối tượng của lớp B).
Và việc chuyển nhiệm vụ tạo đối tượng cho người khác và trực tiếp sử dụng biến phụ thuộc được gọi là dependency injection.
Có 3 loại dependency injection phổ biến
1. constructor injection: các biến phụ thuộc được cung cấp thông qua một hàm tạo lớp.
2. setter injection: client đưa ra một phương thức setter mà injector sử dụng để dependency injection
3. interface injection: biến phụ thuộc sẽ đưa ra một method mà để đưa biên này vào bất kỳ máy khách nào chạy qua. Máy khách sẽ phải triển khai một giao diện có chứa setter method chấp nhận biến phụ thuộc.
Nhiệm vụ của dependency injection
1. Tạo các đối tượng
2. Hiểu lớp nào sẽ cần những đối tượng nào
3. Cung cấp cho lớp đó toàn bộ những đối tượng đó
Nếu có bất kỳ thay đổi nào xảy ra với các đối tượng, DI sẽ xem xét các thay đổi đó mà không quan tầm đến lớp đang sử dụng các đối tượng đó. Như vậy, nếu các đối tượng thay đổi trong tương lai, trách nhiệm của DI là cung cấp các đối tượng thích hợp cho lớp sử dụng các đối tượng đó.
Đảo ngược kiểm soát — khái niệm đằng sau DI
Một lớp không nên được cấu hình với các biến phụ thuộc tĩnh mà nên được cấu hình bởi 1 số lớp khác từ bên ngoài. Đây là nguyên tắc thứ năm trong S.O.L.I.D - năm nguyên tắc cơ bản của lập trình hướng đối tượng – theo như nguyên tắc này, một lớp nên dựa vào abstraction chứ không phải concretions (theo thuật ngữ đơn giản, mã hóa cứng – hard-coded).
Theo đó, một lớp nên tập trung vào việc hoàn thành nhiệm vụ của mình chứ không phải tạo ra các đối tượng cần thiết cho việc thực hiện các nhiệm vụ đó.
Một số lợi ích và hạn chế từ việc sử dụng DI
Lợi ích
Vì Dependency Injection giúp giảm thiểu sự phụ thuộc lẫn nhau giữa các module, điều này sẽ mang lại những lợi ích sau:
- Code sẽ trở nên dễ hiểu hơn, thuận tiện cho việc thay thế, bảo trì phần mềm
- Việc viết unit test và test cũng trở nên dễ dàng hơn khi người dùng có thể “tiêm” các mock Object vào trong các Class
- Hỗ trợ mở rộng các ứng dụng hoặc tính năng
- Dễ dàng thay đổi quan hệ giữa các Object
Một số hạn chế của DI
- Dependency Injection khá phức tạp để học. Nếu lạm dụng quá nhiều có thể dẫn đến nhiều vấn đề nghiêm trọng khác.
- Một số lỗi ở compile time có thể bị đẩy sang runtime, gây khó khăn cho việc debug. Nếu debug bằng source code, đôi khi người dùng sẽ không thể biết được implement nào được truyền vào.
- Đối với người mới, sẽ cần nhiều thời gian để có thể thay đổi tư duy từ Dependency sang Dependency Injection.
- Để có thể thực hiện Dependency Injection một cách hiệu quả, lập trình viên cần phải có kinh nghiệm lâu năm và tư duy theo nguyên tắc SOLID.
- Các chức năng như autocomplete hay find references của một số IDE có thể sẽ bị ảnh hưởng. Một số Dependency Injection sẽ làm ẩn các Dependency, làm phát sinh lỗi khi chạy chương trình thay vì biên dịch chương trình.
Thư viện và Framework triển khai DI
Spring (Java)
Google Guice (Java)
Dagger (Java và Android)
Castle Windsor (.NET)
Unity (.NET)
Theo Bizfly Cloud chia sẻ
>> Có thể bạn quan tâm: Trở lại với cơ bản: OOP, Dependency Injection và Cake Pattern