Áp dụng Pipeline Design Pattern trong Laravel

Là một lập trình viên, chắc hẳn mỗi chúng ta đều không xa lạ với khái niệm Design Pattern. Đó là các mẫu thiết kế chuẩn, những khuôn mẫu cho các vấn đề chung trong thiết kế phần mềm. Trong bài viết này, mình sẽ giới thiệu một design pattern phổ biến – Pipeline Pattern

Là một lập trình viên, chắc hẳn mỗi chúng ta đều không xa lạ với khái niệm Design Pattern. Đó là các mẫu thiết kế chuẩn, những khuôn mẫu cho các vấn đề chung trong thiết kế phần mềm. Trong bài viết này, mình sẽ giới thiệu một design pattern phổ biến – Pipeline Pattern và cách triển khai nó trong Laravel.

1. Pipeline Design Pattern là gì ?

Ta có một dữ liệu đầu vào, dữ liệu được xử lý qua các giai đoạn (stage). Đầu ra của giai đoạn trước chính là đầu vào của giai đoạn tiếp theo. Bạn có thể pipeline tương tự như dây chuyền sản xuất trong nhà máy, nơi mỗi hạng mục trong dây chuyền sản xuất được xây dựng theo từng giai đoạn. Vật phẩm được chuyển từ công đoạn sản xuất này sang công đoạn sản xuất khác. Như vậy, Pipeline design pattern là một design pattern cung cấp khả năng xây dựng và thực thi một chuỗi các hành động theo từng bước. Các quy trình phức tạp có thể phân rã ra thành các nhiệm vụ đơn lẻ. Mỗi nhiệm vụ đơn lẻ lại có tính tái sử dụng cao. Chia nhỏ một quy trình lớn thành các tác vụ nhỏ hơn để xử lý dữ liệu và sau đó chuyển dữ liệu đó đến bước tiếp theo cho đến khi nhận được kết quả mong muốn.

Ý tưởng của Pipeline nhằm mục đích cho phép chúng ta xử lý dữ liệu trong một chuỗi các bước thực thi bằng một đầu vào thông qua các công đoạn và đầu ra sẽ được sử dụng cho bước tiếp theo. Trong đó, mỗi công đoạn xử lý sẽ trả về kết quả thành công hoặc thất bại. Trong trường hợp một trong các bước thất bại cả chuỗi xử lý sẽ dừng hoàn toàn. Trong trường hợp bước xử lý thành công, đầu ra của bước xử lý đó sẽ được sử dụng làm đầu vào cho công đoạn tiếp theo tới khi toàn bộ các bước đều được thực hiện theo đúng quy trình.

brewing-process.jpg

Laravel đã xây dựng sẵn khung Pipeline giúp chúng ta có thể dễ dàng ứng dụng design pattern này trong thực tế. Khi tìm hiểu về request lifecycle của Laravel, ta thấy Laravel cũng áp dụng Pipeline để cài đặt middleware nằm giữa Request và Response. Middleware cung cấp một cơ chế thuận tiện để lọc hoặc kiểm tra các yêu cầu HTTP trước khi các yêu cầu đó được chuyển tới controller. Trong class IlluminateFoundationHttp của Laravel, ta sẽ bắt gặp phương thức sau:

/**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array<int, class-string|string>
     */protected$middleware=[// AppHttpMiddlewareTrustHosts::class,AppHttpMiddlewareTrustProxies::class,IlluminateHttpMiddlewareHandleCors::class,AppHttpMiddlewarePreventRequestsDuringMaintenance::class,IlluminateFoundationHttpMiddlewareValidatePostSize::class,AppHttpMiddlewareTrimStrings::class,IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,];/**
     * Send the given request through the middleware / router.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */protectedfunctionsendRequestThroughRouter($request){$this->app->instance('request',$request);Facade::clearResolvedInstance('request');$this->bootstrap();return(newPipeline($this->app))->send($request)->through($this->app->shouldSkipMiddleware()?[]:$this->middleware)->then($this->dispatchToRouter());}

Có thể thấy, Request để đi vào được ứng dụng phải đi qua 1 Pipeline, bao gồm các middleware như HandleCors, PreventRequestsDuringMaintenance, ValidatePostSize, TrimStrings, ConvertEmptyStringsToNull, các route middleware, controller middleware và cuối cùng mới dispatch đến router để nhận về một Response.

3. Ví dụ minh họa

Một trong những usecase phổ biến mà ta nghĩ ngay đến việc áp dụng Pipeline Pattern chính là chức năng lọc để thực hiện tìm kiếm.
Screenshot 2022-12-22 at 23.05.12.png

Bài toán: Xây dựng một hệ thống ATS quản trị tuyển dụng có chức năng tìm kiếm ứng viên. Chức năng này cho phép chuyển viên tuyển dụng tìm kiếm các ứng viên theo nhiều tiêu chí khác nhau (họ tên, địa chỉ, giới tính…)
Tạo một abstract class cho các Filter:

<?phpnamespaceAppFilters;useClosure;useIlluminateDatabaseEloquentBuilder;abstractclassFilter{publicfunctionhandle($request,Closure$next){if(!request()->has($this->filterName())){return$next($request);}return$this->applyFilter($next($request));}protectedfunctionfilterName(){returnStr::snake(class_basename($this));}/**
     * @param $filter
     * @param  Builder  $builder
     * @return Builder
     */abstractprotectedfunctionapplyFilter($filter,Builder$builder):Builder;}

Tạo các class Filter cho mỗi bước lọc ứng viên. Ví dụ class Name:

<?phpnamespaceAppFilters;useIlluminateDatabaseEloquentBuilder;classNameextendsFilter{/**
     * @param $filter
     * @param  Builder  $builder
     * @return Builder
     */protectedfunctionapplyFilter(Builder$builder):Builder{return$builder->where('name','like','%'.request($this->filterName).'%');}}

Sử dụng trong controller hoặc repository:

useIlluminatePipelinePipeline;useAppFiltersName;useAppFiltersAddress;useAppFiltersGender;$builder=Candidate::query();$data=app(Pipeline::class)->send($builder)->through([Name::class,Address::class,Gender::class,])->thenReturn();return$data->get();

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ