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

Áp dụng Pipeline Design Pattern trong Laravel

0 0 21

Người đăng: Vu Minh Hieu

Theo Viblo Asia

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.

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 Illuminate\Foundation\Http 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 = [ // \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, \Illuminate\Http\Middleware\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, ]; /** * Send the given request through the middleware / router. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($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.

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:

<?php namespace App\Filters; use Closure;
use Illuminate\Database\Eloquent\Builder; abstract class Filter
{ public function handle($request, Closure $next) { if (!request()->has($this->filterName())) { return $next($request); } return $this->applyFilter($next($request)); } protected function filterName() { return Str::snake(class_basename($this)); } /** * @param $filter * @param Builder $builder * @return Builder */ abstract protected function applyFilter($filter, Builder $builder): Builder;
}

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

<?php namespace App\Filters; use Illuminate\Database\Eloquent\Builder; class Name extends Filter
{ /** * @param $filter * @param Builder $builder * @return Builder */ protected function applyFilter(Builder $builder): Builder { return $builder->where('name', 'like', '%' . request($this->filterName) . '%'); }
}

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

use Illuminate\Pipeline\Pipeline;
use App\Filters\Name;
use App\Filters\Address;
use App\Filters\Gender; $builder = Candidate::query();
$data = app(Pipeline::class) ->send($builder) ->through([ Name::class, Address::class, Gender::class, ]) ->thenReturn(); return $data->get();

Bình luận

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

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

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

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

Giới thiệu về Builder Design Pattern

Nguồn: refactoring.guru. Builder. Ý đồ.

0 0 34

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

Một ví dụ nhỏ về Factory method

Trong bài viết trước mình đã giới thiệu tới các bạn về Abstract Factory pattern, các bạn quan tâm có thể theo dõi lại tại đây. Để tiếp tục về chủ đề design pattern trong bài viết này mình sẽ trình bày những khái niệm, ưu nhược điểm và các sử dụng của một creational design pattern khác đó là Factory

0 0 27

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

Tôi đã dùng Service Pattern trong NuxtJS như thế nào ?

Giới thiệu. Trong quá trình làm VueJS NuxtJS hay thậm chí là Laravel mình cũng hay áp dụng các pattern như Service hoặc Repository.

0 0 59

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

Hướng dẫn Adapter Design Pattern

Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Adapter Design Pattern qua cấu trúc, cánh triển khai, ví dụ, ưu điểm nhược điểm và ứng dụng của nó. Đây là bài viết đầu tiên của mình nên sẽ không trán

1 1 53

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

Giới thiệu về Prototype Design Pattern

Ý đồ. Prototype là một creational design pattern cho phép bạn sao chép các object hiện có mà không làm cho code của bạn phụ thuộc vào các class của chúng.

0 0 44