Đã đăng vào thg 5 4, 2017 6:53 SA 4 phút đọc 4 phút đọc
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 Inversion
là 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ột
1 được tạo ra có thể tuân thủ nguyên lýclass A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
Dependency Inversion
trong thiết kế và code. Có nhiều cách hiện thực pattern này: ServiceLocator, Event, Delegate, …Dependency Injection
là một trong các cách đó.Dependency Injection
là 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.
6 là một tool để giúp DI tốt hơn, đơn giản hơn , phổ biết trongclass A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
7 như làclass A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
8,class A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
9,class A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
0,$a = new A[new B[new C[new D[new E, new F]]]];
1 ...$a = new A[new B[new C[new D[new E, new F]]]];
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
2 inject$a = new A[new B[new C[new D[new E, new F]]]];
3,$a = new A[new B[new C[new D[new E, new F]]]];
3 inject$a = new A[new B[new C[new D[new E, new F]]]];
5,$a = new A[new B[new C[new D[new E, new F]]]];
5 inject$a = new A[new B[new C[new D[new E, new F]]]];
7,$a = new A[new B[new C[new D[new E, new F]]]];
7 inject$a = new A[new B[new C[new D[new E, new F]]]];
9,$a = new A[new B[new C[new D[new E, new F]]]];
0... 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ượngrequire_once 'Dice.php'; $dice = new \Dice\Dice; $a = $dice->create['A'];
2. 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]]]];
$a = new A[new B[new C[new D[new E, new F]]]];
6 ra đờ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.class A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
- Ví dụ mình sẽ dùng
9 DI container để khởi tạo một instanceclass A { public $b; public function __construct[] { } public function setB[B $b] { $this->b = $b; } }
2 vô cùng đơn giản. Các DI như$a = new A[new B[new C[new D[new E, new F]]]];
3,$a = new A[new B[new C[new D[new E, new F]]]];
5,$a = new A[new B[new C[new D[new E, new F]]]];
7,$a = new A[new B[new C[new D[new E, new F]]]];
9,$a = new A[new B[new C[new D[new E, new F]]]];
0 đã tự động inject rồi.require_once 'Dice.php'; $dice = new \Dice\Dice; $a = $dice->create['A'];
require_once 'Dice.php';
$dice = new \Dice\Dice;
$a = $dice->create['A'];
Kết luận
Dependency Injection
0 là 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ụngDependency Injection
1 sẽ giúp việcDependency Injection
0 dễ dàng và đơn giản hơn. Vậy nên việc ứng dụngDependency Injection
0 vàDependency Injection
1 sẽ giúp chúng ta có những đoạn code pro hơn, nâng cao trình độ hơn.
All rights reserved