Giới thiệu
Magento là một hệ thống cho phép các nhà lập trình bên thứ ba có thể tùy chỉnh và ghi đè lên phần core của nó. Sự linh hoạt này khiến cho magento dễ tùy biến hơn, tuy nhiên, đi kèm theo nó là một số vấn đề gặp phải.
Đó là các extension của bên thứ ba cần phải gọi các hàm và giao tiếp với core của Magento. Do đó, nếu theo một cách code thông thường, rất dễ xảy ra khả năng sự thay đổi của Magento ảnh hưởng trực tiếp tới module của các bên thứ ba.
Để giải quyết vấn đề này, việc áp dụng nguyên lý Dependency Inversion và cụ thể là mô hình Service contract là cần thiết. Dependency Inversion là một trong những nguyên lý của SOLID, một trong số những nguyên lý khá nổi tiếng để thiết kế phần mềm. SOLID được đưa ra bởi Bob Martin và Michael Feathers, là viết tắt của 5 chữ cái đầu trong 5 nguyên tắc thiết kế hướng đối tượng, giúp cho lập trình viên tạo ra phần mềm dễ bảo trì, dễ đọc, giảm những chi phí về sau khi cần nâng cấp phần mềm. SOLID gồm:
- Single responsibility priciple (SRP)
- Open/Closed principle (OCP)
- Liskov substitution principe (LSP)
- Interface segregation principle (ISP)
- Dependency inversion principle (DIP)
Hôm nay mình sẽ giới thiệu mọi người nguyên lý Dependency Inversion trong SOLID và áp dụng của nó trong Magento 2, cụ thể là kiến trúc service contract của Magento.
Nguyên lý Dependency Inversion
Nội dung của nguyên lý Dependency Inversion như sau:
- High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
- Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.
- Các module cấp cao không nên phụ thuộc vào các module cấp thấp. Cả 2 nên phụ thuộc vào abstraction (ví dụ là các interface)
- Abstraction không nên phụ thuộc vào chi tiết. Chi tiết (các class implement nó) phải phụ thuộc vào abstractions. Có thể hiểu là các class giao tiếp với nhau thông qua interface, không phải thông qua implementation (details).
Để giải thích dễ hiểu hơn về lợi ích của Dependency Inversion, mình sẽ đưa ra ví dụ sau:
Giả sử có 2 công ty A và B. Công ty A yêu cầu công ty B làm cho mình một chiếc xe ô tô. Công ty A sẽ kí với công ty B một bản hợp đồng cam kết là sẽ ô tô phải có đủ tính năng và đặc điểm như: màu vàng, chạy êm, 20 chỗ ngồi, … . Công ty B sẽ giao dự án này cho team Eden thực hiện.
ở đây ta có thể hiểu:
-Công ty A ứng với Module A
-Công ty B ứng với Module B
-Hợp đồng ứng với Interface
-Team Eden là người thực hiện hợp đồng.
Như chúng ta thấy, Công ty A sẽ không giao tiếp trực tiếp với team Eden mà thông qua công ty và đại diện cho nó là bản hợp đồng đã được ký kết. Việc ai thực hiện dự án này sẽ do nội bộ công ty B quyết định, và công ty A sẽ không can thiệp và cũng không biết tới nó. Giả dụ, nếu team Eden không thực hiện dự án, thì công ty B sẽ giao cho một team khác (team Eagle). Sự thay đổi này chỉ diễn ra trong nội bộ công ty B và công ty A không phải chịu ảnh hương gì cả.
Do đó, ứng vào code, sự thay đổi của module B chỉ xảy ra ở bản thân module B mà thôi. Module A chỉ quan tâm tới các Interface , các interface này hoàn toàn không thay đổi. Nó sẽ chứa chữ ký của các phương thức. Vì vậy, code sẽ dễ dàng bảo trì hơn.
Với cách code thông thường không tuân theo nguyên lý này, các module cấp cao sẽ gọi các module cấp thấp. Điều này đối với các dự án lớn, có nhiều module, thì việc gọi trực tiếp các class implements mà không thông qua interface có thể dẫn tới hàng loạt các sự thay đổi về mặt source code.
Service contract trong Magento
Magento đã đề ra “Hợp đồng dịch vụ” (Service Contract) dựa theo nguyên lý Dependency Inversion.
Một hợp đồng dịch vụ (Service Contract) là gì?
“Hợp đồng dịch vụ” là một bộ PHP Interface được định nghĩa cho một module. Hợp đồng dịch vụ bao gồm các data interfaces dùng để bảo tồn tính toàn vẹn dữ liệu và service interfaces để cung cấp các xử lí. Chi tiết logic xử lí được ẩn đi với các phần sử dụng dịch vụ (như controller, web services và các module khác).
Nếu developer định nghĩa data và service interfaces theo một mẫu thiết kế, API của các modules khác và các extension bên thứ ba có thể implement nó thông qua Magento models và resource models.
Dưới đây là hình ảnh mô tả về cấu trúc của Magento 2 tuân theo Service Contract:

Trong hình ảnh trên, các bạn có thể thấy Controllers, Web Services, Other modules không thao tác trực tiếp với thành phần Model và Resource Model mà giao tiếp thông qua interface. Logic xử lí được ẩn đi, các thành phần sử dụng service chỉ quan tâm đến đầu ra và đầu vào chứ không cần quan tâm đến logic xử lí.
Interface được Model nào implement nó sẽ được file di.xml trong Magento mapping và reference đến.
Service contract trong module catalog
Interface (contract - hợp đồng)
Model (Details - Implement - người thực hiên)
File mapping - Quy định hợp đồng do ai thực hiện:
Các module khác gọi Interface thay vì gọi trực tiếp Model:
Cảm ơn các bạn đã quan tâm theo dõi. Phần tới mình sẽ trình bày các phần khác của SOLID được áp dụng trong Magento 2. Mời các bạn theo dõi.