Phân biệt Dependency Inversion, Dependency Injection và Inversion Of Control

Chào mọi người, hôm nay mình xin chia sẻ một số kiến thức liên quan đến các khái niệm Dependency Inversion, Dependency Injection và Inversion Of Control để chúng ta có thể phân biệt được 3 khái niệm trên một cách dễ dàng không bị nhầm lẫn.

1. Dependency Inversion

Là một trong những nguyên lý SOLID, cụ thể nó là nguyên lý cuối cùng (nguyên lý SOLID là gì thì mình để link tham khảo ở đây Link).
Nguyên lý Denpendency Inversion có nói:

  • Các module cấp cao không nên phụ thuộc vào các module cấp thấp hơn và ngược lại, chúng nên phụ thuộc vào abstraction
  • Interface không nên phụ thuộc vào các chi tiết mà ngược lại. Các class phải giao tiếp với nhau thông qua interface chứ không phải implementation

Để hiểu rõ hơn các khái niệm trên mình xin đưa ra một ví dụ về cách tổ chức code như nhau:

class LoginFaceBook
{
    // Logic code
    function loginFace {

    }
}

class UserLogin
{
    private $login;
    function __contruct(LoginFaceBook $logInFace) {
        $this->login = $loginFace;
    }

    // Logic code
}

Các bạn có thể nhìn đoạn code trên về mặt logic thì không sai như về mặt tổ chức code gặp một số vấn đề: như không tuân thủ nguyên lý Dependency Inversion đó là một module cấp cao không nên phụ thuộc vào module cấp thấp mà chúng chỉ lên phụ thuộc vào Interface. Để khác phục vấn đề trên code nên được tổ chức như sau

interface LoginWithAnOtherAccount
{
    public function login();
}   

class LoginFaceBook implements LoginWithAnOtherAccount
{
    // Code login login facebook
    public function login();
}

class UserLogin
{
    private $login;
    function __contruct(LoginWithAnOtherAccount $login) {
        $this->login = $login;
    }
    
    // Logic tiếp theo ....
}

Như vậy với cách thiết kế trên thì module UserLogin chỉ phụ thuộc vào Interface và chúng ta có thể dễ dàng thêm các cách login khác mà không cần phải sửa trực tiếp vào Module UserLogin.

Dependency Injection(DI) và Inversion Of Control(IOC)

Khái niệm đầu tiên là Inversion Of Control nó là một design pattern được tạo ra nhằm mục đích tuân thủ theo nguyên lý Dependency Inversion, còn DI là một cách thể hiện của IOC. Thông thường DI sẽ là viết tắt của Dependency Injection chứ không phải là Dependency Inversion nhé mọi người ^--^.

Đối với DI:

  • Các module cấp module phụ thuộc sẽ được inject vào module cấp cao.
    • Một module A mà sử dụng một hoặc một số chức năng của Module B thì ta có thể gọi A phụ thuộc B.
  • Các module không giao tiếp trực tiếp với nhau, các module cấp thấp sẽ implements interface, các module cấp cao sẽ gọi các module cấp thấp thông qua interface(Trong ví dụ trên các module cấp thấp như LoginFaceBook sẽ implements interface LoginWithAnOtherAccount và module cấp cao UserLogin sẽ gọi các module cấp thấp thông qua các interface LoginWithAnOtherAccount).
  • Việc khởi tạo các module cấp thấp sẽ được thực hiện bởi DI container mà không cần phải thực hiện new LoginFaceBook trong LoginUser.

Ưu điểm của DI

  • Giảm bớt sự phụ thuộc và kết dính giữa các module
  • Code dễ bảo trì
  • Dễ viết test cho các thành phần
  • Thấy rõ được các quan hệ giữa các module

Kết luận

Nói chung Inversion Of Control chỉ một design pattern được thiết kế để tuân thủ nguyên lý SOLID cụ thể đó là Dependency Inversion và một trong số cách để triển khai IOC đó là Dependency Injection(DI). Hi vọng bài viết này có thể giúp mọi người không bị nhầm lẫn giữa các khái niệm với nhau và có thể vận dụng DI một cách linh hoạt trong dự án của mình.
Chân thành cảm ơn !!!

Tài liệu tham khảo

  1. https://toidicodedao.com/2015/11/03/dependency-injection-va-inversion-of-control-phan-1-dinh-nghia/
  2. https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design#dependency-inversion-principle