Service Provider Pattern: Kẻ đứng sau những dự án không "toang" khi thay đổi.
Chào bạn, lại là một ngày dài ngồi "code dạo" và bỗng dưng mình muốn chia sẻ chút tâm sự về cái nghề này.
Lúc mới vào nghề, mình cứ nghĩ viết code chạy được là đủ. Nhưng rồi đời (và sếp) vả cho vài cái "deadline" cùng đống "legacy code" rối như tơ vò, mình mới nhận ra: Viết code thì dễ, nhưng viết code sao cho sau này mình không muốn tự đấm chính mình mới khó.
Hôm nay, hãy cùng mình ngồi xuống, làm ly cà phê và nói về một "người hùng thầm lặng" trong các framework hiện đại (như Laravel): Service Provider Pattern.
1. Khi "mối quan hệ" trở nên quá toxic
Hãy tưởng tượng bạn đang xây dựng một tính năng gửi email. Bạn viết một class EmailService. Trong cái class đó, bạn phải khai báo API Key, Cổng kết nối, Tên người gửi...
Ở đâu cần gửi mail, bạn lại new EmailService(...).
Một ngày đẹp trời, công ty chuyển từ SendGrid sang Mailchimp. Bạn tá hỏa nhận ra mình đã new EmailService ở 50 file khác nhau. Lúc này, bạn chỉ muốn "bỏ nghề" vì phải đi sửa từng file một.
Đó chính là hậu quả của việc Tightly Coupling (Phụ thuộc quá chặt chẽ). Và Service Provider ra đời như một vị cứu tinh để giải quyết cái mớ bòng bong này.
2. Service Provider là gì mà nghe kêu thế?
Nói một cách dân dã, Service Provider giống như một "trạm trung chuyển" hay một "người quản gia".
Thay vì bạn phải tự tay đi mua rau, thái thịt, nấu cơm (khởi tạo đối tượng với đủ loại tham số), bạn chỉ cần nói với quản gia: "Tôi muốn ăn cơm". Người quản gia (Service Provider) sẽ biết cách kết nối với nhà bếp, chuẩn bị nguyên liệu và bưng lên cho bạn một bát cơm nóng hổi.
Trong thế giới lập trình:
- Nó là nơi tập trung tất cả logic để khởi tạo (bootstrap) và đăng ký (register) các dịch vụ vào hệ thống.
- Nó giúp tách biệt việc "Sử dụng" và "Khởi tạo" đối tượng.
3. Cách nó vận hành (Dưới góc nhìn thực tế)
Thường thì một Service Provider sẽ có hai "trạm dừng" chính mà bạn cần nhớ:
Trạm 1: register()
Đây là nơi bạn "khai báo" với hệ thống.
"Này App ơi, nếu sau này có ai hỏi mượn cái PaymentGateway, thì hãy đưa cho họ cái StripePayment này nhé!"
Ở bước này, bạn tuyệt đối không được thực hiện logic kinh doanh nào, vì có thể các dịch vụ khác chưa kịp khởi tạo xong.
Trạm 2: boot() Đây là nơi mọi thứ đã sẵn sàng. Bạn có thể gọi đến các dịch vụ khác, đăng ký sự kiện (events), hay cấu hình thêm cho view...
4. Tại sao "người trải đời" lại yêu nó?
Sau vài lần "đập đi xây lại" những dự án nghìn line, mình rút ra được 3 cái lợi của Service Provider:
- Dễ bảo trì (Maintainability): Thay đổi cấu hình ở một nơi, cả hệ thống chạy theo. Không cần đi "lùng sục" khắp project.
- Dễ kiểm thử (Testability): Bạn có thể dễ dàng "tráo" một Service thật bằng một Service giả (Mock) khi viết Unit Test.
- Gọn gàng (Clean Code): Controller hay Business Logic của bạn sẽ không còn chứa đống code khởi tạo rườm rà. Nó chỉ việc lấy ra và dùng thôi.
5. Lời kết từ một kẻ từng "lầm đường lạc lối"
Đừng nhìn Service Provider như một thứ lý thuyết khô khan trong sách giáo khoa. Hãy coi nó là một triết lý về sự tự do. Bạn tự do thay đổi công nghệ bên dưới mà không làm sụp đổ tòa tháp bên trên.
Nếu bạn đang làm việc với Laravel, hãy mở thư mục Providers ra. Bạn sẽ thấy đó là linh hồn của framework này. Còn nếu bạn đang dùng các ngôn ngữ khác, hãy thử áp dụng tư duy này, bạn sẽ thấy cuộc đời lập trình viên nhẹ nhõm hơn hẳn.
**Đời có thể rối, nhưng Code thì nên rõ ràng. ** Bạn có đang gặp khó khăn trong việc tách biệt các thành phần trong dự án hiện tại không? Hãy để lại comment chúng ta cùng thảo luận nhé!
Hy vọng bài viết này giúp bạn có một cái nhìn "đời" hơn về Service Provider Pattern. Hẹn gặp lại anh em ở bài viết tiếp theo!
All rights reserved