- vừa được xem lúc

IoC Container in PHP (Part 1)

0 0 13

Người đăng: Nguyen You

Theo Viblo Asia

Trong chuỗi bài viết này, chúng ta sẽ tự tay implement một cái IoC Container (Inversion of Control Container), sử dụng ngôn ngữ lập trình PHP. Nhưng trước khi implement IoC Container, chúng ta cần bàn một chút về Dependency Injection (DI)

1. Dependency Injection & Inversion of Control (IoC).

Xem qua đoạn code này:

public function __construct()
{ $this->connection = new MySqlConnection('127.0.0.1');
}

Thay vì tạo một instance của MySqlConnection ngay bên trong constructor của class như ví dụ trên.

Ta muốn truyền một instance của MySqlConnection vào trong class này.

public function __construct(MySqlConnection $connection)
{ $this->connection = $connection;
}

Làm như này, nó chính là Dependency Injection rồi đấy!


But Why?

Tại sao chúng ta lại muốn code như vậy ?

Hãy cùng xem qua một ví dụ khác:

public function __construct(Mailer $mailer)
{ $this->mailer = $mailer;
}

Giả sử chúng ta muốn thực hiện việc gửi mail ở trong một class, chúng ta sẽ truyền một instance của Mailer vào trong class này. Việc này sẽ giúp chúng ta test dễ dàng hơn.

$mailer = Mockery::mock('Illuminate\Contracts\Mail\Mailer');
$mailer->shouldReceive('send')->once();
$instance = new Service($mailer);

Ở đây chúng ta có thể mock một mailer, rồi thiết lập expectation cho nó, và truyền nó vào một class. Rồi thực hiện test cái function mà có sử dụng mailer instance trong class đó,...

Đó là lợi ích đầu tiên của DI, Easy To Test.

Một lợi ích thứ hai nữa là Easy To Swap Implementation.

Nói về swap implementation, nó xứng đáng có một bài viết riêng để bàn về. Về bản chất cốt lỗi, là các thành phần code của chúng ta, sẽ liên kết và phụ thuộc vào nhau thông qua Interface thay vì Implementation.

Lấy một ví dụ, một ứng dụng cần có tính năng lưu thông tin người dùng. Ta định nghĩa ra một class FileSystemUserRepository có các phương thức cơ bản như readwrite. Tới đây, ta đã biết và đã quen áp dụng Dependency Injection, Ta inject một instance của class FileSystemUserRepository này vào và sử dụng.

Nhưng vài tuần sau, yêu cầu thay đổi, thay vì lưu thông tin người dùng vào file text như hiện tại. Ta sẽ phải lưu nó vào database. Vậy là ta định nghĩa một class PostgresqlDatabaseUserRepository. Và phải thay thế tất cả các FileSystemUserRepository này.

Mà quan trọng, là nếu viết có cấu trúc tốt, thì đổi còn đơn giản. Còn như, trong hai class đó mà function tên gọi, tham số khác nhau, thì refactor điên mất, căng thẳng lắm. b


Nhưng giả sử, giờ ta viết ra một Interface, ví dụ, UserRepositoryInterface, sau đó Implement cái interface này, rồi ta thay vì DI cái class name vô, thì giờ ta DI cái Interface.


$container->bind('UserRepositoryInterface', 'PostgreSQLImplementation'); class Something { public function __construct(UserRepositoryInterface $repository) { $this->repository = $repository; }
} 

Rồi nhờ có IoC Container, ta sẽ có thể map cái Interface với cái ImplementationDI khi cần.

Việc code của chúng ta phụ thuộc (depend) vào Interface thay vì Implementation là một best pratice quan trọng khi thực hiện DI.

Note: việc này chỉ có thể thực hiện khi có sự giúp sức của IoC Container.

Nếu chỉ là Dependency Injection, thì đoạn code sau đã là Dependency Injection.

$discountBroker = new DiscountBroker( new ProductRepository, new EventDispatcher, new Logger( new EmailLoggingDriver( new SmtpTransport( $emailServerCredentials ) ) )
)

Ta đã tiêm instance vào constructor của các class như thế, nó đã áp dụng đúng DI. Tuy nhiên, nếu cứ viết như này, thì cái codebase của chúng ta sẽ như nào ? sẽ rất dài và khó maintain ?

Đó là lúc, chúng ta cần sự trợ giúp của IoC Container, và vận dụng Reflection in PHP

2. IoC Container and Reflection base implementation

... to be continue

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 376

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 421

- vừa được xem lúc

Sử dụng Swagger để xây dựng API documentation

Giới thiệu về Swagger. RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho các ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource.

0 0 1k

- vừa được xem lúc

So sánh Interface và Abstract trong lập trình hướng đối tượng.

Tổng quan. Interface và Abstract class là 2 khái niệm cơ bản trong lập trình OOP.

0 0 49

- vừa được xem lúc

CURL và cách sử dụng trong PHP

Giới Thiệu. CURL là bộ thư viện được sử dụng để giúp thực hiện việc chuyển dữ liệu thông qua nhiều giao thức khác nhau (như HTTP, FPT...). Với giao thức HTTP, cURL hỗ trợ việc gửi dữ liệu sử dụng tất cả các phương thức hiện có như GET, POST, PUT, DELETE... cURL cũng hỗ trợ việc chuyền dữ liệu sử dụn

0 0 81

- vừa được xem lúc

Thêm dòng dữ liệu mới (MySQL) trong Laravel

Chào các bạn, Laravel hiện đang là hot trend trong "thế giới PHP". 1. Cấu hình cơ bản ban đầu. .

0 0 38