กลยุทธ์สำหรับการกำหนดเวอร์ชันของฟิลด์และ Directive
โปรดอ่านคู่มือ การพัฒนาสคีมาผ่านการกำหนดเวอร์ชันของฟิลด์ ก่อน ซึ่งอธิบายฟีเจอร์ "field versioning" ใน Gato GraphQL
Gato GraphQL อนุญาตให้ฟิลด์และ Directive รับอาร์กิวเมนต์ versionConstraint เพื่อเลือกเวอร์ชันที่ต้องการ (หรือการนำไปใช้งาน) ของฟิลด์/Directive:
query GetPosts {
posts(versionConstraint: "^1.0") {
id
title(versionConstraint: ">=2.1")
excerpt @strUpperCase(versionConstraint: "~1.5.3")
}
}จะเกิดอะไรขึ้นหากเราไม่ระบุอาร์กิวเมนต์ versionConstraint? ตัวอย่างเช่น ฟิลด์ surname ในคำสั่ง queries ด้านล่างควรใช้เวอร์ชันใด?
query GetSurname {
account(id: 1) {
# ควรใช้เวอร์ชันใด? 1.0.0? 2.0.0?
surname
}
}เรามีข้อกังวลสองประการที่นี่:
- การตัดสินใจว่าเวอร์ชันเริ่มต้นที่จะใช้เมื่อไม่มีการระบุคือเวอร์ชันใด
- การแจ้งให้ client ทราบว่ามีหลายเวอร์ชันให้เลือก
ก่อนจะแก้ไขข้อกังวลเหล่านี้ เราต้องตรวจสอบก่อนว่า GraphQL ให้ข้อมูล Contextual Feedback ได้ดีเพียงใดเมื่อรัน queries
การให้ข้อมูล Contextual Feedback เมื่อรัน queries
เราต้องชี้ให้เห็นถึงสถานการณ์ที่ไม่เหมาะสมของ GraphQL ในขณะนี้: มันไม่ให้ข้อมูลบริบทที่ดีเมื่อรัน queries ซึ่งชัดเจนในเรื่องของการ Deprecation โดยข้อมูล Deprecation จะแสดงเฉพาะผ่าน introspection โดยการ queries ฟิลด์ isDeprecated และ deprecationReason บนประเภท Field และ Enum:
{
__type(name: "Account") {
name
fields {
name
isDeprecated
deprecationReason
}
}
}การตอบสนองจะเป็นดังนี้:
{
"data": {
"__type": {
"name": "Account",
"fields": [
{
"name": "id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "surname",
"isDeprecated": true,
"deprecationReason": "Use `personSurname`"
},
{
"name": "personSurname",
"isDeprecated": false,
"deprecationReason": null
}
]
}
}
}อย่างไรก็ตาม เมื่อรัน queries ที่เกี่ยวข้องกับฟิลด์ที่ถูก Deprecated…
query GetSurname {
account(id: 1) {
surname
}
}…ข้อมูล Deprecation จะไม่ปรากฏในการตอบสนอง:
{
"data": {
"account": {
"surname": "Owens"
}
}
}ซึ่งหมายความว่านักพัฒนาที่รัน queries จะต้องรัน introspection queries เองเพื่อตรวจสอบว่าสคีมาได้รับการอัปเกรดหรือไม่ และฟิลด์ใดถูก Deprecated บ้าง ซึ่งอาจเกิดขึ้น… บางครั้ง? ส่วนใหญ่แล้วอาจไม่เกิดขึ้นเลย?
จะเป็นการปรับปรุงที่ยอดเยี่ยมในการทบทวน queries ที่ล้าสมัยหาก GraphQL API ให้ข้อมูล Deprecation เมื่อรัน queries ที่เกี่ยวข้องกับฟิลด์ที่ถูก Deprecated ข้อมูลนี้ควรปรากฏภายใต้ entry ระดับบนสุดใหม่ deprecations ที่ปรากฏหลัง errors และก่อน data (ตามข้อเสนอแนะของ spec สำหรับรูปแบบการตอบสนอง)
เนื่องจาก entry ระดับบนสุด deprecations ไม่ได้เป็นส่วนหนึ่งของ spec ฟีเจอร์ "Proactive Feedback" ของ Gato GraphQL จึงรองรับการให้ Feedback ที่ดีขึ้นในการตอบสนองต่อ queries โดยใช้ wildcard entry ระดับบนสุด extensions ซึ่งอนุญาตให้ขยาย protocol ตามต้องการ:

การประกาศเวอร์ชันผ่าน Warnings
เราเพิ่งเรียนรู้ว่า GraphQL server สามารถใช้ entry ระดับบนสุด extensions เพื่อให้ข้อมูล Deprecation ได้ เราสามารถใช้วิธีการเดียวกันนี้เพื่อเพิ่ม entry warnings ซึ่งเราแจ้งนักพัฒนาว่าฟิลด์ได้รับการกำหนดเวอร์ชันแล้ว เราไม่ได้ให้ข้อมูลนี้ตลอดเวลา แต่เฉพาะเมื่อ queries เกี่ยวข้องกับฟิลด์ที่ได้รับการกำหนดเวอร์ชัน และไม่มีอาร์กิวเมนต์ versionConstraint
การกำหนดเวอร์ชันเริ่มต้นของฟิลด์
มีหลายแนวทางที่เราสามารถใช้ได้ รวมถึง:
- ทำให้
versionConstraintเป็นสิ่งจำเป็น - ใช้เวอร์ชันเก่าเป็นค่าเริ่มต้นจนถึงวันที่กำหนด เมื่อเวอร์ชันใหม่จะกลายเป็นค่าเริ่มต้น
- ใช้เวอร์ชันล่าสุดเป็นค่าเริ่มต้นและส่งเสริมให้นักพัฒนา queries ระบุเวอร์ชันที่ต้องการอย่างชัดเจน
มาสำรวจแต่ละกลยุทธ์เหล่านี้และดูการตอบสนองเมื่อรัน queries นี้:
query GetSurname {
account(id: 1) {
surname
}
}1. ทำให้ versionConstraint เป็นสิ่งจำเป็น
นี่คือแนวทางที่ชัดเจนที่สุด: ห้าม client ไม่ให้ไม่ระบุ version constraint โดยทำให้อาร์กิวเมนต์ฟิลด์เป็นสิ่งจำเป็น จากนั้น เมื่อใดก็ตามที่ไม่ได้ระบุ queries จะส่งคืนข้อผิดพลาด
การรัน queries จะตอบสนองด้วย:
{
"errors": [
{
"message": "Argument 'versionConstraint' in field 'surname' cannot be empty"
}
],
"data": {
"account": {
"surname": null
}
}
}2. ใช้เวอร์ชันเก่าเป็นค่าเริ่มต้นจนถึงวันที่กำหนด เมื่อเวอร์ชันใหม่จะกลายเป็นค่าเริ่มต้น
ใช้เวอร์ชันเก่าต่อไปจนถึงวันที่กำหนด เมื่อเวอร์ชันใหม่จะกลายเป็นค่าเริ่มต้น ในช่วงการเปลี่ยนผ่านนี้ ขอให้นักพัฒนา queries เพิ่ม version constraint ให้กับเวอร์ชันเก่าก่อนวันนั้นผ่าน entry extensions.warnings ใหม่ใน queries
การรัน queries อาจตอบสนองด้วย:
{
"extensions": {
"warnings": [
{
"message": "Field 'surname' has a new version: '2.0.0'. This version will become the default one on January 1st. We advise you to use this new version already and test that it works fine; if you find any problem, please report the issue in https://github.com/mycompany/myproject/issues. To do the switch, please add the 'versionConstraint' field argument to your query (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints): surname(versionConstraint:\"^2.0\"). If you are unable to switch to the new version, please make sure to explicitly point to the current version '1.0.0' before January 1st: surname(versionConstraint:\"^1.0\"). In case of doubt, please contact us at name@company.com.",
]
},
"data": {
"account": {
"surname": "Owens"
}
}
}3. ใช้เวอร์ชันล่าสุดและส่งเสริมให้ผู้ใช้ระบุเวอร์ชันที่ต้องการอย่างชัดเจน
ใช้เวอร์ชันล่าสุดของฟิลด์เมื่อไม่ได้ตั้งค่า versionConstraint และส่งเสริมให้นักพัฒนา queries กำหนดเวอร์ชันที่ต้องการอย่างชัดเจน โดยแสดงรายการเวอร์ชันที่มีทั้งหมดสำหรับฟิลด์นั้นผ่าน entry extensions.warnings ใหม่:
การรัน queries อาจตอบสนองด้วย:
{
"extensions": {
"warnings": [
{
"message": "Field 'surname' has more than 1 version. Please add the 'versionConstraint' field argument to your query to indicate which version to use (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints). To use the latest version, use: surname(versionConstraint:\"^2.0\"). Available versions: '2.0.0', '1.0.0'.",
]
},
"data": {
"account": {
"surname": "Owens"
}
}
}การกำหนดเวอร์ชันของ Directive
เราสามารถใช้กลยุทธ์เดียวกันเพื่อกำหนดเวอร์ชันของ Directive ตัวอย่างเช่น เมื่อรัน queries โดยไม่ระบุ version constraint:
query {
post(by: { id: 1 }) {
title @strTitleCase
}
}มันสามารถสมมติเวอร์ชันเริ่มต้นที่จะใช้และสร้างข้อความเตือนให้นักพัฒนาทบทวน queries:
