I. DI (Dependency Injection)
DI = Dependency + Injection
1. Dependency
Nói một cách đơn giản thì dependency là sự phụ thuộc. Nếu một class A sử dụng một số tính năng của class B thì có nghĩa rằng class A có sự phụ thuộc vào class B.
Dưới đây là một ví dụ cho thấy sự phụ thuộc. Khi khởi tạo instance của class A thì bạn phải khởi tạo instance của B để sử dụng tính năng của B.
A là dependent class. B là depedency của A.
2. Injection
Injection nếu dịch một cách thô thiển có nghĩa là tiêm vào. Rõ ràng là bạn không thể tiêm một cái gì không có sẵn được cho nên hành động injection cần hiểu là depedency đã được khởi tạo và binding bên ngoài depedent class.
Có nhiều cách để inject depedency và ở ví dụ trên mình đang dùng constructor injection, một trong những cách làm phổ biến nhất.
3. Programming to an interface
Bạn có thể thấy DI cũng chỉ là một kỹ thuật giúp chúng ta khởi tạo depedency của một object có sẵn. Nhưng tóm lại là nó giải quyết vấn đề gì mà bạn đi đâu cũng thấy người ta nói về nó?
Như ở ví dụ 1, nếu bạn khởi tạo instance của A thì bạn cũng phải khởi tạo instance của B. Mối quan hệ giữa A và B được gọi là tight-coupling. Tuy nhiên ở ví dụ 2 thì ngược lại, nếu B là một interface thì bạn có thể khởi tạo A với bất cứ concrete implementation nào của B. Lúc này mối quan hệ hệ giữa A và B được gọi là loose-coupling (aka programming to an interface).
Bạn sẽ dễ dàng thấy sự hiệu quả của kĩ thuật này trong khi test.
II. Inversion Of Control
Bởi vì mọi cái tên được đặt ra đều có ý nghĩa của nó cho nên khi bắt đầu tiếp cận một khái niệm thì mình cứ dịch ngựa ra trước. Inversion of control là đảo ngược sự kiểm soát chăng? Wtf? Kiểm soát là kiểm soát cái gì? Xin thưa rằng đó chính là luồng đi hay flow của code.
Muốn biết hành động đảo ngược luồng đi của code diễn ra như thế nào thì hãy xem lại cách một chương trình thực thi trước khi IoC ra đời thông qua hai ví dụ ở trên. Khi bạn chạy hàm Main, mọi thứ sẽ thực thi từ trên xuống dưới, từng dòng một. Tuy nhiên với đoạn code Spring Boot sau đây bạn sẽ trải nghiệm một điều hoàn toàn khác biệt.
Bạn chỉ cần viết hai mẫu code đơn giản như thế này cùng một vài thư viện có sẵn là bạn đã có một REST API. Bạn vẫn có thể gọi vào method mà không cần phải viết bất cứ một mapping, handler method nào cả. Thậm chí cũng không cần khởi tạo instance của Controller. Và đó chính là sức mạnh của kỹ thuật IoC.
IoC được giới thiệu lần đầu vào năm 1988 được phát biểu như sau:
One important characteristic of a framework is that the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user’s application code. The framework often plays the role of the main program in coordinating and sequencing application activity. This inversion of control gives frameworks the power to serve as extensible skeletons. The methods supplied by the user tailor the generic algorithms defined in the framework for a particular application.
Đại khái là luồng đi của chương trình sẽ do framework điều phối. Code của user sẽ do framework tự gọi.
Ý nghĩa của Inversion Of Control có nghĩa rằng thay vì chúng ta phải tự gọi method, tự làm mọi thứ một cách tuần tự thì sẽ có ai đó làm hộ chúng ta như Spring Boot chẳng hạn.
The major difference between an object-oriented framework and a class library is that the framework calls the application code. Normally the application code calls the class library. This inversion of control is sometimes named the Hollywood principle, “Do not call us, we call You”.
Michael Mattson
Hy vọng qua bài viết ngắn này mọi người có thể nắm được bản chất của DI và IoC.
Thanks for reading.
References
- https://stackoverflow.com/questions/47001196/what-does-dependency-dependant-mean
- https://medium.com/ssense-tech/dependency-injection-vs-dependency-inversion-vs-inversion-of-control-lets-set-the-record-straight-5dc818dc32d1
- https://medium.com/free-code-camp/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f
- https://medium.com/ssense-tech/dependency-injection-vs-dependency-inversion-vs-inversion-of-control-lets-set-the-record-straight-5dc818dc32d1
- https://reflectoring.io/dependency-injection-and-inversion-of-control/