Dependency Injection trong PHP
Bài đăng này đã không được cập nhật trong 8 năm
Khái niệm liên quan
-
Dependency Injection(DI) là khái niệm thường được nghe trong giới lập trình. Có khá nhiều cái tên nghe liên quan và na ná nhau làm dev bị hoang mang như:Dependency Injection,Inversion of Control,Dependency Inversion,Dependency Injection Container. -
Các khái niệm trên được hiểu như sau:
Dependency Inversionlà một nguyên lý để thiết kế và viết code trong 5 nguyên lý S.O.L.I.D do Robert C.Martin viết. Các khái niệm tiếp theo đều được phát triển để thực hiện hóa nguyên lý này.Inversion of Control(IoC) là mộtdesign patternđược tạo ra có thể tuân thủ nguyên lýDependency Inversiontrong thiết kế và code. Có nhiều cách hiện thực pattern này: ServiceLocator, Event, Delegate, …Dependency Injectionlà một trong các cách đó.Dependency Injectionlà một phương thức để thực hiện design parternInversion of Control, tức là một phương thức để viết code tốt hơn.Dependency injection containerlà một tool để giúp DI tốt hơn, đơn giản hơn , phổ biết trongPHPnhư làPHP-DI,Dice,Symfony-dependency,Pimple...
Các cách Dependency Injection
Có 3 dạng Dependency Injection:
Constructor Injection
- Các dependency sẽ được container truyền vào (inject vào) 1 class thông qua constructor của class đó. Đây là cách thông dụng nhất.
class A {
public $b;
public function __construct(B $b)
{
$this->b = $b;
}
}
Setter Injection
- Các dependency sẽ được truyền vào 1 class thông qua các hàm Setter.
class A {
public $b;
public function __construct()
{
}
public function setB(B $b)
{
$this->b = $b;
}
}
Interface Injection
- Class cần inject sẽ implement 1 interface. Interface này chứa 1 hàm tên Inject. Container sẽ injection dependency vào 1 class thông qua việc gọi hàm Inject của interface đó. Đây là cách rườm rà và ít được sử dụng nhất.
Ưu điểm và khuyết điểm của DI
Ưu điểm
- 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
- Dễ dàng thấy quan hệ giữa các module (vì các dependecy đều được inject vào constructor)
Khuyết điểm
- Khái niệm DI khá khó cho các developer mới
- 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
- Các object được khởi tạo toàn bộ ngay từ đầu, có thể làm giảm performance
- Làm tăng độ phức tạp của code
Đối vơi dự án lớn thì việc sử dụng DI là cần thiết vì code sẽ linh hoạt, dễ mở rộng và bảo trì. Hiên nay, tất cả các Framework PHP đều dùng DI
Dependency injection container (DI container)
- Có một vấn đề đặt ra trong DI đó là. Các module inject chia thành nhiều tầng nhiều lớp. Ví dụ module
AinjectB,BinjectC,CinjectD,DinjectE,F... Khi số lượng module inject lớn thì việc kiểm soát DI rất phức tạp khi khởi tạo đối tượngA. Chúng ta phải biết rõ từng module inject vào phụ thuộc module nào.
$a = new A(new B(new C(new D(new E, new F))));
Dependency injection containerra đời để giải quyết vấn đề này. Tức là chúng ta sẽ khởi tạo đối tượng qua DI container mà không cần quan tâm đến các phụ thuộc DI của nó. DI container sẽ tự động inject chính xác các DI cần thiết. Điều này rất tuyệt vời.- Ví dụ mình sẽ dùng
DiceDI container để khởi tạo một instanceAvô cùng đơn giản. Các DI nhưB,C,D,E,Fđã tự động inject rồi.
require_once 'Dice.php';
$dice = new \Dice\Dice;
$a = $dice->create('A');
Kết luận
DIlà một kĩ thuật tuyệt vời để thiết kết và code rõ ràng, mạch lạc, dễ mở rộng và bảo trì hơn. Việc sử dụngDI containersẽ giúp việcDIdễ dàng và đơn giản hơn. Vậy nên việc ứng dụngDIvàDI containersẽ giúp chúng ta có những đoạn code pro hơn, nâng cao trình độ hơn.
All rights reserved