Kiến trúc
Kiến trúcServer GraphQL code-first

Server GraphQL code-first

Schema GraphQL định nghĩa các hợp đồng cho một dịch vụ GraphQL, bằng cách xuất tập hợp các kiểu, trường và mutation có thể được thực thi đối với dịch vụ. Khi tạo một dịch vụ GraphQL, chúng ta có thể quyết định:

  • để schema là nguồn sự thật, và để toàn bộ code triển khai của chúng ta khớp với các định nghĩa của nó
  • để code của chúng ta là nguồn sự thật, và để schema là một tạo phẩm được tạo ra từ code

Trong cả hai trường hợp, chúng ta sẽ có một dịch vụ GraphQL hoạt động đầy đủ, nhưng tùy thuộc vào phương pháp chúng ta sử dụng, chúng ta có thể thực hiện được nhiều hay ít tính năng hơn, dễ dàng hay khó khăn hơn, về lâu dài. Hai phương pháp này được gọi lần lượt là "schema-first" (còn được gọi chính xác hơn là "SDL-first") và "code-first".

Gato GraphQL sử dụng phương pháp code-first. Hãy cùng xem tại sao lại như vậy.

Tại sao Gato GraphQL sử dụng code-first

Trong phương pháp code-first, chúng ta bắt đầu bằng cách viết code cho các resolver, sau đó từ code với tư cách là nguồn sự thật duy nhất, chúng ta tạo ra schema như một tạo phẩm. Do đó, schema được tạo bằng cách chạy một script, thay vì được tạo thủ công như trong SDL-first. Vì code-first cũng có schema, nên nó không bỏ lỡ bất kỳ điều gì đáng kể mà SDL-first cung cấp.

Tuy nhiên, code-first cung cấp một tính năng quan trọng hơn so với SDL-first: khả năng cung cấp các schema động, có thể thay đổi hình dạng và thuộc tính tùy theo ngữ cảnh, và được điều chỉnh thông qua code trong thời gian chạy. Thực vậy, tất cả các tính năng tuyệt vời mà Gato GraphQL cung cấp đều là hệ quả trực tiếp từ việc áp dụng code-first.

Ưu điểm của code-first

Một schema động cung cấp tất cả các lợi ích được liệt kê dưới đây, trong số các lợi ích khác:

Nguồn sự thật cho schema là một tập siêu (superset) của những gì GraphQL yêu cầu. Các thuộc tính bổ sung (chẳng hạn như các trường toàn cục, kết nối toàn cục, chỉ thị toàn cục và các fragment được lưu trữ) đã có thể được sử dụng trong API của chúng ta mà không cần phải chờ chúng được thêm vào đặc tả GraphQL, nếu điều đó có xảy ra.

Vì nguồn sự thật không bị ràng buộc vào schema, chúng ta có thể tạo ra bất kỳ schema nào cho bất kỳ hệ thống nào khác: GraphQL chỉ là một trong các mục tiêu. Ví dụ, nó có thể tạo ra một JSON-schema cho dịch vụ REST từ cùng một nguồn sự thật.

API có thể vừa công khai vừa riêng tư cùng lúc, tùy thuộc vào việc người dùng đã đăng nhập hay chưa và vào các vai trò của người dùng đã đăng nhập, hoặc cung cấp nhiều hay ít trường tùy thuộc vào một số thuộc tính khác, chẳng hạn như liệu người dùng đã trả tiền cho gói thành viên PRO hay chưa.

Các kiểu không biết trước chúng sẽ phân giải những trường nào. Thay vào đó, các resolver trường tự gắn kết với các resolver kiểu bằng cách sử dụng mẫu publish-subscribe, và các resolver trường có thể ghi đè lên các resolver trường khác. Tính năng này làm cho API rất có khả năng mở rộng, cho phép chúng ta có code chung cho API của mình, và tùy chỉnh nó ở cấp độ ứng dụng cho một client hoặc dự án cụ thể.

Một trường có thể được xử lý không chỉ bởi một, mà bởi nhiều resolver trường: mỗi resolver trường trong chuỗi có thể quyết định, trong thời gian chạy, có xử lý trường hay không dựa trên một thuộc tính nào đó, hoặc chuyển nó dọc theo chuỗi. Ví dụ, một resolver trường đặc biệt có thể chỉ được sử dụng nếu đối số trường "source: testing" được truyền vào, cho phép kiểm tra trên một vài trang web trong môi trường production trước khi phát hành chính thức; cùng chiến lược này cũng cho phép cung cấp các bản vá lỗi nhanh cho một client hoặc môi trường cụ thể mà không có nguy cơ gây ra các tác dụng phụ ngoài ý muốn ở những nơi khác.

Các kiểu và interface có thể được tự động đặt vào namespace để tránh xung đột với các bên thứ ba.