Tìm hiểu kiến trúc của Laravel – Phần 2. Service Container.

Tiếp tục với serie “Tìm hiểu kiến trúc của Laravel”, hôm nay mình xin được viết một bài về Service Container. Service Container trong Laravel là nơi quản lý class Dependency và thực hiện Dependency Injection (‘Laravel beauty’). Qua đó, trong bài viết này, mình muốn được giới thiệu về Dependency Injection, trình bày về bind và resolve trong Service Container. Nào chúng ta đi vào chi tiết nhé.

Giới thiệu về Dependency Injection.

Nguyên lý cuối cùng trong SOLID chính là Dependency Inversion:

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

Nguyên lý này hoàn toàn có thể được hiểu là “ Các module nhờ vào ( dependency ) sẽ được inject vào module cấp cao ”. Nó giúp những module hoặc những class sẽ không quá nhờ vào lẫn nhau, tạo ra loose coupling giữa những thành phần trong code nên thuận tiện hơn trong thao tác bảo dưỡng code .
Một ví dụ về Dependency Injection mà mình thấy cũng có rất nhiều bài khi nói về nó đó là về class Computer mà mình cũng xin được lấy làm ví dụ :

dependency-injection

Trong ví dụ này, class Computer cần 2 class cấp thấp hơn là class Monitor và class Keyboard. Tuy nhiên, 2 class này lại được inject vào class Computer trải qua contructor nên điều đó không làm class Computer nhờ vào vào 2 class con này. Khi đó để tạo được một object Computer ta sẽ cần truyền vào 2 object Monitor và Keyboard .
Qua đó ta hoàn toàn có thể thấy được 1 số ít ích lợi của Dependency Injection như sau :

  1. Giúp viết Unit test dễ dàng hơn.
  2. Giảm thiểu được boilerplate code vì việc khởi tạo dependency được làm bởi một component khác.
  3. Giúp ích trong việc liên kết lỏng (loose coupling) giữa các thành phần trong dự án.

=> Mở rộng dự án Bất Động Sản thuận tiện hơn .
Tuy nhiên Dependency Injection cũng có một số ít hạn chế :

  1. Nó khá là phức tạp để học, và nếu dùng quá đà thì có thể dẫn tới một số vấn đề khác.
  2. Rất nhiều các lỗi ở compile time có thể bị đẩy sang runtime.
  3. Có thể làm ảnh hưởng tới chức năng auto-complete hay find references của một số IDE

Service Container.

Sau khi đã có một chút ít khái niệm về Dependency Injection thì tất cả chúng ta hoàn toàn có thể mở màn điều tra và nghiên cứu một chút ít về Service Provider .
Từ những phiên bản Laravel thấp thì đã Open Service Container nhưng với cái tên khác là IoC Container. Từ phiên bản 5.1 trở đi, IoC Conatiner được đổi tên là Service Container như lúc bấy giờ .
Có 2 khái niệm trong Service Container đó là bind và resolve :

Bind để chỉ việc đăng ký một class hay một interface với Container.

Resolve để lấy ra instance từ Container.

Cùng lấy ví dụ về class Computer phía trên, dưới đây là cách viết khi sử dụng cùng với Service Container. Ta sẽ có class Monitor và class Keyboard được inject vào class Computer như sau

Screenshot at Feb 05 14-20-15

Khi đó ta sẽ ĐK class Computer này với Container trải qua lời gọi :

binding-service-container

Và lấy object của class đã được khai báo trong Container bằng một trong những cách viết sau :

resolving-service-containers

Với mỗi lần resolve như vậy, một object khác nhau sẽ được lấy ra so với class Computer. Trên đây là một ví dụ đơn thuần để hiểu về Service Container. Trong Laravel ngoài cách binding đơn thuần ( binding basics ) như phía trên kia còn 1 số ít cách binding class vào Container khác như :

Binding a Singleton.

$this

-

>

app

-

>

singleton

(

'HelpSpot\API'

,

function

(

$app

)

{

return

new

\

HelpSpot

\

API

(

$app

-

>

make

(

'HttpClient'

)

)

;

}

)

;

Khi sử dụng binding a singleton, mỗi khi ta resolve để lấy ra object trong một request đã sẽ thu được cùng một object .

Binding an Instance.

$api

=

new

\

HelpSpot

\

API

(

new

HttpClient

)

;

$this->app->instance('HelpSpot\API', $api);

Ta cũng hoàn toàn có thể binding một object đã sống sót vào Container trải qua Instance Binding. Kết quả khi resolve cũng tương tự như như Singleton Binding .

Binding Primitive.

$this

-

>

app

-

>

when

(

'App\Http\Controllers\UserController'

)

-

>

needs

(

'$age'

)

-

>

give

(

10

)

;

Khi việc inject của bạn cần một giá trị nguyên thủy ( primitive ) như một giá trị integer, ta hoàn toàn có thể sử dụng Primitive Binding để thực thi việc này .
Ngoài những kiểu binding đơn thuần này ( Binding Basics ) có một số ít cách binding khác như Binding Interface, Contexture Binding, … mà tùy trường hợp đơn cử ta sẽ sử dụng. Để khám phá về những kiểu binding này những bạn hoàn toàn có thể vào từng đường link mình đã gắn vào tiêu đề của kiểu binding để tìm hiểu và khám phá cụ thể .
Cám ơn những bạn đã đón đọc, bài viết sau mình sẽ viết về Service Provider nhé. Xin chào và hẹn gặp lại .

Tài liệu tham khảo.

Series bài viết về kiến trúc Laravel.

Chia sẻ: